How to Add Newsletter Signup (Revue) to a Static Site (Gatsby)
This post covers how to add newsletter functionality to a static website. In this case I used the Revue newsletter service and added it using a form to this website which is built using Gatsby.
Newsletter Design Goals
A newsletter can be a great way to share content with readers and build an audience. Starting out, I wanted a good user experience flow:
- Provide a signup form (a react component) can can be embedded in pages, blog posts .. essentially anywhere on a Gatsby website.
- Allow the entire signup process to happen within the component (Async). No page refresh or redirection. This would involve making a call to the newsletter api to add the user's email address and showing an update for successful or fail attempts.
The main challenge with the above is that making api calls from a static website (e.g. using javascript Fetch) to a different newsletter api server introduces security issues and is generally not supported (see CORS[^2] errors discussion ). An alternative would be to write a backend api that makes this call and forwards the result to the frontend hosted on same server. However, I host my website on Github pages, so the possibility of writing a backend api just did not work.
Here is the workflow I settled on with Revue:
- Insert Revue form in component.
- Validate email on form submit.
- Submit form to revue "Add subscriber" page (this is done after a slight delay to give the illusion of some local processing being done). This is a redirect which I have to accomodate.
Why Revue?
There are multiple mail services (with comparable basic functionality) that you can use for a newsletter e.g. MailChimp, Substack and Revue [^1] [^3]. MailChimp [^4] has an excellent gatsby plugin which I tried out for the first version of my newsletter explorations. Some reasons I have decided to try Revue as at time of writing:
- They have been recently acquired by Twitter, it is likely the product will improve. Or not. 🤷
- They provide unlimited subscribers compared to MailChimp capped at 2k subscribers.
- They offer the configuration of a custom domain. For example I was able to map newsletter.victordibia.com to my Revue profile page. This helps with maintaining the illusion of a single victordibia.com experience.
Writing Some Code
Add a form
Add html form to component. Revue provides sample form integration code (go to your account settings -> integrations -> sign up forms). The form can contain additional details such as first name and last name etc. We will edit the default to just capture email address as shown below.
<div id={formID} className=" inline-block"><div id="revue-embed"><formaction="http://newsletter.victordibia.com/add_subscriber"method="post"id="revue-form"name="revue-form"target="_blank"><div className="revue-form-group"><inputplaceholder="email@example.com"type="email"name="member[email]"id="member_email"></input></div><div className="revue-form-actions"><buttontype="submit"onClick={subscribeClick}name="member[subscribe]"id="member_submit">Subscribe</button></div></form></div>
Add Some Javascript
Note that the submit button
above has an onClick
event which :
- prevents default submit behaviour
- validates the email address. This shows or hides an error message as needed
- submits the form if email validation checks out .. this triggers a redirect to the Revue profile page. The delays (setTimeout) are used to display a loading spinner for a short duration before the redirect. This communicates activity to the user and prepares them for the coming redirect.
Snippets for onClick
are shown below.
function subscribeClick(e) {e.preventDefault();const email = currentForm.querySelector("#member_email").value;const isEmailValid = validateEmail(email);const emailError = currentForm.querySelector("#email_error");const subSuccess = currentForm.querySelector("#subscribe_success");const subLoading = currentForm.querySelector("#subscribe_loading");const revueForm = currentForm.querySelector("#revue-form");if (isEmailValid) {subLoading.classList.remove("hidden");emailError.classList.add("hidden");setTimeout(() => {subLoading.classList.add("hidden");subSuccess.classList.remove("hidden");revueForm.submit();}, loadDuration);} else {subLoading.classList.remove("hidden");setTimeout(() => {resetViews();emailError.classList.remove("hidden");}, loadDuration);}}
And really, thats it!
References
[^1]: Substack Vs Mailchimp Vs Pateron Vs Revue: Which Platform Is The Best To Make Money Writing. https://medium.com/menlo-office/substack-vs-mailchimp-vs-pateron-vs-revue-which-platform-is-the-best-to-make-money-writing-5ca31dde6506 [^2]: Cross-Origin Resource Sharing (CORS) https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS [^3]: Newsletter Crew | Substack vs. Revue https://newslettercrew.com/substack-vs-revue/ [^4]: Mailchimp Gatsby Plugin https://www.gatsbyjs.com/plugins/gatsby-plugin-mailchimp/