How to implement Amazon SNS email subscription on Gatsby website

Subscribe to my newsletter and never miss my upcoming articles

I had difficulty implementing Amazon Simple Notification Service email subscription on one of my Gatsby websites. Yes you've read it well 😊, Gatsby , a React-based framework that helps you quickly build and deploy super fast lightweight websites.

In this post I will share, through a demo project, how you can easily implement this feature in your Gatsby website.

Prerequisites

Configure Amazon SNS

Create a AWS programmatic user for aws-sdk

  • In the same AWS console with the same signed In user for above sns topic, choose IAM in Services menu
  • Choose Users in the IAM Dashboard and clic on Add user image.png
  • Give the user name (here : SnsUser)
  • Select : programmatic access and clic Next permission
  • In the Set permissions tab, select Attach existing policies directly
  • In the Policies table, search for AmazonSNSFullAccess and check it
  • Then hit Next - Next - create. snsuser.png
  • Copy or download the created user's cridentials (Access key ID and Secret Access key) for next steps.

Setting up the Gatsby website project

Now that we've created the sns subscription endpoint and the according user on AWS, we are going to setup our project.

  • Create a new project : gatsby new my-gatsby-project https://github.com/gatsbyjs/gatsby-starter-default

  • In the root of the project, type gatsby develop to run

  • Open the browser and type : http://localhost:8000

image.png

Create Subscription component

  • In the component folder, create : subscribeform.js file
  • Install aws-sdk in the gatsby project npm install -save aws-sdk
  • Install Formik and Yup schema builder npm install formik yup
  • Copy and paste the below code snipet
import React from "react"
import { useFormik } from "formik"
import * as Yup from "yup"
export default function SubscribeForm() {
    const formik = useFormik({
    initialValues: {
      email: "",
    },
    validationSchema: Yup.object({
      email: Yup.string().email().required(),
    }),
    onSubmit(values, { resetForm }) {
      const { email } = values    
    },
  })
  return (
    <form onSubmit={formik.handleSubmit}>
      <input
        type="email"
        name="email"
        placeholder="Your email"
        onChange={formik.handleChange}
        value={formik.values.email}
      />
      {formik.errors.email ? (
        <span className="errorText">{formik.errors.email}</span>
      ) : null}
      <input type="submit" value="Subscribe" />
    </form>
  )
}
  • Add subscribeform.js component in the index page, index.js must look like this :

import React from "react"
import { Link } from "gatsby"

import Layout from "../components/layout"
import Image from "../components/image"
import SEO from "../components/seo"
import SubscribeForm from "../components/subscribeform"

const IndexPage = () => (
  <Layout>
    <SEO title="Home" />
    <h1>Hi people</h1>
    <p>Welcome to your new Gatsby site.</p>
    <p>Now go build something great.</p>
    <div style={{ maxWidth: `300px`, marginBottom: `1.45rem` }}>
      <Image />
    </div>
    <div style={{ maxWidth: `300px`, marginBottom: `1.45rem` }}>
      <SubscribeForm />
    </div>
    <Link to="/page-2/">Go to page 2</Link> <br />
    <Link to="/using-typescript/">Go to "Using TypeScript"</Link>
  </Layout>
)

export default IndexPage
  • Our webpage should have this look : note the email input and the subscribe button

image.png

Add subscription method

So far, everything works well as expected, but if you clic on subscribe button, nothing happens 🤣, yes, because we haven't done anything so great, everbody who've gone through Gatsby tutorials could have done what we did! Let's add some codes to our subscribeform.js.

  • Add a config.json file in the root for AWS cridentials, it should look like this:

{ 
    "accessKeyId": "secret", 
    "secretAccessKey": "secret", 
    "region": "secret" 
}

Nota bene : You must replace "secret" with the corresponding accessKeyId , secretAccessKey and region values you've got in the Create a AWS programmatic user for aws-sdk section.

Warning : It is not a best practice to put app cridentials in a project, I'll have a post for how to do that, but for this subscription purpose, we'll not follow this best practice 🤦‍♂️. Let's move on!

  • In the subscribeform.js , under the last import instruction, add the following lines:
import AWS from "aws-sdk"

const AWSConf = require('../../config.json');
AWS.config.update(AWSConf);
  • In the onSubmit() method add the following instructions after const {email}=values line :
var params = {
        Protocol: "EMAIL" /* required */,
        TopicArn: "yourArn" /* required */,
        Endpoint: email,
      }

      var subscribePromise = new AWS.SNS({ apiVersion: "2010-03-31" })
        .subscribe(params)
        .promise()

      subscribePromise
        .then(function (data) {
          resetForm() //reset the form
        })
        .catch(function (err) {
          console.error(err, err.stack)
        })

Nota bene : In the TopicArn: "yourArn" instruction, replace yourArn by the ARN generated through Configure Amazon SNS section. Voilà! You've done the great thing 👍.

  • The subscribeform.js code should look like this :
import React from "react"
import { useFormik } from "formik"
import * as Yup from "yup"
import AWS from "aws-sdk"

const AWSConf = require('../../config.json');
AWS.config.update(AWSConf);

export default function SubscribeForm() {
    const formik = useFormik({
    initialValues: {
      email: "",
    },
    validationSchema: Yup.object({
      email: Yup.string().email().required(),
    }),

    onSubmit(values, { resetForm }) {
      const { email } = values
      var params = {
        Protocol: "EMAIL" /* required */,
        TopicArn: "yourArn" /* required */,
        Endpoint: email,
      }

      var subscribePromise = new AWS.SNS({ apiVersion: "2010-03-31" })
        .subscribe(params)
        .promise()

      subscribePromise
        .then(function (data) {
          resetForm()  //reset the form
        })
        .catch(function (err) {
          console.error(err, err.stack)
        })

    },
  })

  return (
    <form onSubmit={formik.handleSubmit}>
      <input
        type="email"
        name="email"
        placeholder="Your email"
        onChange={formik.handleChange}
        value={formik.values.email}
      />
      {formik.errors.email ? (
        <span className="errorText">{formik.errors.email}</span>
      ) : null}
      <input type="submit" value="Subscribe" />
    </form>
  )
}
  • Refresh the browser and put a valid email address then submit. The input field will be automatically reset on success, and a Subscription Confirmation email will be sent to the provided email address.

emailconfirmation.png

Conclusion

Well done! You have implemented an Amazon SNS email newsletter subscription in your Gatsby website.

You can find the source code here .

Comments (2)

J_cloudofthrones's photo

Hey fantastic Wilson! I will sure try this out. Congrats on the blog. I'm following!

Wilson KOMLAN's photo

Thank you Jose! Waiting for your suggestion if possible! Have a nice weekend!