Logo Blog Newsletters

From SPA to SSR on AWS: Boost Your Website’s SEO

Published on October 3, 2023
~ 7 min read
SSR
Serverless
AWS
SvelteKit
Plausibile
Article cover

Introduction

We have one of the fastest serverless websites out there! However, having a fast website alone doesn't guarantee traffic, views, and engagements. That's where SEO and analytics come into play. In this article, I will guide you through the most efficient practices to help you achieve your goals without the need to read hundreds of articles. Let's get started so you can hit the ground running!🏃

The problem with SPA

Yes, you are right! Why does there always have to be a problem? Let's put it this way: you're reading an exceptional article, one of the best, and you decide to share it with your friends. You click the share button and choose your favorite social media platform. A new window or tab pops up, and you write a captivating caption like, "Look, guys, this article is lit 🔥" and click "Publish." How disappointing it is when the article doesn't have a title or a preview image? Believe me, a lot! Alright, the lack of article previews may be a minor issue that you can overlook. However, let's look 2 more related problems.

Lack of Meta Tags

You know when you search on Google for something like "optimizing content delivery: S3 caching and CloudFront" and the article you're referring to appears right after the search query?

Figure 1: Google search results.

Well, with SPA, this doesn't happen. Since you have a Single Page, search engines only have access to a single set of meta tags, resulting in only one title and one description. If you're running a blog, it's like running a full marathon with a huge rock on your back 🥉.

Slower Load Times

Although our cache helps mitigate this issue, SPA still needs to load all JavaScript files before the website can run. It's not as critical as the lack of meta tags because caching can fix it, but it's still a factor to consider.

The solution is SSR

Server-Side Rendering (SSR) provides the solution to the problems faced by SPA. SSR involves rendering the website on the server and sending back a fully-rendered HTML to the client. This approach allows search crawlers to easily access and understand the content. Moreover, SSR enables customization of each page's meta tags and significantly improves initial page load times, resulting in better performance. Nowadays, there are numerous frameworks to choose from. If you have been following my series, I opted for SvelteKit, which fortunately supports both SSR and SPA. This compatibility should make the transition relatively smooth and painless 👌.

Converting SPA to SSR on AWS

Figure 2: Quick and easy meme!

As it turned out, the process was quite the opposite of painless, a blood bath 🩸. In the case of SSR with SvelteKit on AWS, there weren't many readily available libraries. While there was one existing library, it was not actively maintained and didn't provide the level of customization I needed. Therefore, I took the initiative and forked the library to create my own solution.

You can find the original library here: https://github.com/MikeBild/sveltekit-adapter-aws. You can see the author knows it's stuff.

Armed with a lot of patience, I dug deep into the project and identified numerous areas for improvement and updates. The existing infrastructure was well-built and impressive. Here's an overview of the initial architecture:

Figure 3: SvelteKit Adapter Architecture.

And this is how I managed to make it more complicated then it should be:

Figure 4: Updated SvelteKit Adapter Architecture.

However, I needed to integrate it with our existing CloudFront distribution, which added complexity to the process. I had to create a custom resource to preserve all the new origins and cache behaviors within the existing distribution.

⚠️ If you don't know what I'm talking about, you are missing out on a really good post! You can find it here 👇 https://depascalematteo.medium.com/building-a-lightning-fast-serverless-blog-on-aws-with-sveltekit-part-4-5ca74d6dfa4a

You can find the updated npm package here: https://www.npmjs.com/package/@mdepascale/sveltekit-aws-adapter While the documentation may not be extensive at the moment, I'll make sure to document it at my best. Additionally, I welcome any contributions to make pull requests to enhance the library.

SSR Results

The journey of converting from SPA to SSR was an enjoyable one, but now it's time to evaluate if it was truly worth it. To determine the impact of SSR, I used https://www.linkedin.com/post-inspector/ to check if crawlers can preview images and titles.

Figure 5: SSR Results.

The results were positive, as crawlers were able to preview the images and titles. This is a significant victory ✅. Next, I assessed the performance of our website using Lighthouse scores 🚀.

Figure 6: Lighthouse score results.

The migration to SSR yielded excellent results, with our website achieving the desired scores.  Now we are fully prepared for the next phase 🏆!

Top SEO Best Practices for Bloggers

Now, let's delve into some of the top SEO best practices for bloggers.

Title

Ensure that the title is between 50–60 characters in length and includes our primary keywords.

Description

Keep the description within the range of 150–160 characters and incorporate our primary keywords once or even twice.

Content

The sweet spot tends to be around 1500 words. If the content exceeds this limit, consider splitting it up. However, it's important to note that there may be some exceptions to this guideline, as it can vary based on the subject matter and context.

Header tags

Utilize header tags (H2, H3, H4) effectively throughout the content. Remember to maintain proper order, and reserve H1 for page titles.

Sitemap.xml

Creating a sitemap.xml file helps list all the pages on our website, enabling search engine bots to crawl our website more efficiently.

Include links to reputable sources within our content. This not only enhances the credibility of our website but also earns bonus points when other websites reference our content.

Content freshness

Search engines prioritize fresh and up-to-date content. Therefore, updating our content ensure it stays relevant. Moreover it will help us study consistently 🤓.

Privacy-Friendly Analytics

Without analytics it's like walking in the dark without any light. We need to track visits, visits duration, users behavior and so on so forth. Nowadays, before reading something online, you need to give access (deny if they let you) to cookies, privacy policies, TOS, newsletter signups…. I just want to read a few interesting paragraphs, I don't want to buy a car! That's where Plausible comes in. Let's explore why it rocks:

  • Really easy to use;
  • Privacy friendly;
  • Lightweight library;
  • Open source;
  • Open source (Yeah, I really like this part).

Let's look at some of the things we can do with Plausible.

Starting with Plausible

Using Plausible is straightforward. Simply copy and paste the following script in your app.html file:

<script defer data-domain="yourdomain.com" src="https://plausible.io/js/script.js"></script>

And just like that, it starts recording analytics data right away!

Proxy though CloudFront

Sometimes adblockers block analytics (thanks bad analytics!). To overcome this issue we can set up a proxy from our domain to the analytics domain. Here's an example: if your domain is my.domain.com, you can proxy every request to my.domain.com/api/event to analytics.com. With CloudFront, this process becomes easy. You'll need to create a new origin and two custom behaviors. Here's the guide, if you are looking for it: https://plausible.io/docs/proxy/guides/cloudfront

Tracking outbound links can provide valuable information, from monitoring link clicks, to assessing the effectiveness of affiliate marketing campaigns. Here's an example script to add outbound links tracking:

<script
   defer
   data-domain="yourdomain.com"
   src="https://plausible.io/js/script.outbound-links.js"
></script>

As you can see, adding ".outbound-link" in the script's URL was enough!

Find out how many 404s

Plausible natively supports tracking 404 errors. To set it up, create a goal named "404" and add the following two scripts. The first one goes inside app.html:

<script>
    window.plausible = window.plausible || function() { 
      (window.plausible.q = window.plausible.q || []).push(arguments) 
    }
</script>

And the second one goes inside your 404 page:

<script>
    plausible("404", { 
      props: { 
        path: document.location.pathname
      } 
    });
</script>

What about custom events?

Implementing custom events with Plausible is simple. We can modify our HTML classes as follows:


<button class="some-existing-class">Click Me</button>

<button class="some-existing-class plausible-event-name=Button+Click">Click Me</button>

Just make sure to create a custom event goal named "Button Click" (without the "+"). Plausible provides an easy-to-use, privacy-friendly, lightweight, and open-source analytics solution. By following these steps, you can gather valuable data while respecting user privacy.

You can find all the code here: https://github.com/Depaa/sveltekit-blog-template 😉. I'll update this repository with every new version, if you like it drop a star ⭐.

Conclusion

In this blog post, we've highlighted the issues with SPAs and provided a guide on converting to SSR on AWS. One key advantage of SSR is improved SEO, driving traffic to our website. However, SEO is incomplete without analytics. That's why we delve into Plausible, a privacy-friendly analytics solution. With Plausible, we can gather valuable data and gain insights to make sense of our SEO efforts. By combining SSR, SEO best practices, and privacy-friendly analytics, we create a powerful recipe for growth and success 💯.

Shout out to Gianmarco Pettenuzzo who's helping me developing the website✨

This series is a journey to production, and we have many more blog posts planned, here the list I'll try to keep updated:

Thank you so much for reading! 🙏 I will keep posting different AWS architecture from time to time so follow me on LinkedIn 👉 https://www.linkedin.com/in/matteo-depascale/.