Andrew Welch · Insights · #JavaScript #aws #frontend

Published , updated · 5 min read ·


Please consider 🎗 sponsoring me 🎗 to keep writing articles like this.

Creating a Reverse Proxy for Partytown with AWS Cloudfront

Learn how to quick­ly & eas­i­ly cre­ate a reverse proxy with AWS Cloud­front for Par­ty­town, so your third par­ty track­ing scripts can run per­for­mant­ly in a web worker

Creating a reverse proxy for partytown with aws cloudfront

Par­ty­town is a JavaScript library that allows you to run your third-par­ty track­ing scripts such as Google Tag Man­ag­er, Hot­jar, Google Ana­lyt­ics, Meta (Face­book) Pix­el, etc. in a sep­a­rate web work­er thread.

This allows you to run all of the track­ing scripts your mar­ket­ing team needs, with­out it impact­ing the per­for­mance & user expe­ri­ence that runs on the main thread.

Partytown infrographic

How Par­ty­town works

This can be an enor­mous ben­e­fit to your end-users, allow­ing the var­i­ous track­ing scripts to oper­ate with­out affect­ing the user expe­ri­ence and conversions.

With Partytown, you can have your cake and eat it, too!

If you want a more in-depth dis­cus­sion of Par­ty­town, check out the Life in the Fast Lane with Par­ty­town pod­cast or check out the Par­ty­town doc­u­men­ta­tion.

This arti­cle will show you how to set up a reverse proxy that is need­ed for some third-par­ty track­ing scripts to work prop­er­ly with Partytown.

Link Why a Reverse Proxy?

The Par­ty­town doc­u­men­ta­tion dis­cuss­es why some (but not all) third-par­ty track­ing scripts require a reverse proxy.

The TL;DR is CORS. It’s always CORS.

Essen­tial­ly, some ori­gins for track­ing scripts don’t add the Access-Control-Allow-Origin: * head­er. Nor­mal­ly this is fine if you’re link­ing to them via a <script> tag, but it is need­ed due to the way Par­ty­town fetch­es your scripts.

Creating a reverse proxy for partytown with aws cloudfront

Par­ty­town Reverse Proxy Diagram

Essen­tial­ly all the reverse proxy needs to do in our case is add that head­er to the script that Par­ty­town is fetch­ing for us.

Think of a reverse proxy as just a way to inter­cept the request for the script and add that header.

If a script does­n’t have the Access-Control-Allow-Origin: * head­er, you’ll end up with errors like this: 

Partytown cors errors console

CORS errors

Not all track­ing scripts have this issue; Google Ana­lyt­ics 4 for instance prop­er­ly sets that head­er. So if you can use track­ing scripts that set the head­er prop­er­ly, do so!

For ones that don’t, we’ll need to imple­ment a reverse proxy to add it.

Link Why Cloudfront?

The Par­ty­town doc­u­men­ta­tion shows many dif­fer­ent ways you can set up a reverse proxy.

If you have access to your Apache or Nginx serv­er con­fig, you can do it that way. If you’re already using Netli­fy or Ver­cel, you can do it that way.

You can even write your own reverse proxy in PHP or what­ev­er lan­guage you prefer.

There are many ways to set up a reverse proxy; use what works for you

For a client project, we’re host­ing it on servd.host which is Kuber­netes as a ser­vice, so we don’t have access to the Nginx config.

Addi­tion­al­ly, we’re already using AWS for S3 assets, as described in the Set­ting Up AWS S3 Buck­ets + Cloud­Front CDN for your Assets article.

So it makes sense for us to lever­age AWS Cloud­front CDN, and cre­ate our reverse proxy there.

As a bonus, doing it this way is quite easy to set up, and requires no code!

Cloud­front also is quite inex­pen­sive, with a very gen­er­ous free plan that many projects will nev­er exceed:

Cloudfront pricing

Cloud­front pricing

Link Setting Up a Cloudfront distribution

So let’s get start­ed set­ting up a Cloud­front dis­tri­b­u­tion that will act as our reverse proxy!

Log into your AWS Con­sole, then go to Cloudfront.

Click on Dis­tri­b­u­tions on the left side­bar if you aren’t there already, then click on Cre­ate Dis­tri­b­u­tion.

Cloudfront create distribution

Cre­ate a Cloud­front distribution

Then set the fol­low­ing under Ori­gin:

  • Ori­gin domain: This should be set to the script orig­in’s domain name, e.g. www.google-analytics.com
  • Pro­to­col: HTTPS only
Cloudfront origin settings

Cloud­front ori­gin settings

Then set the fol­low­ing under Default cache behav­ior:

  • Response head­ers pol­i­cy: Sim­pleCORS
Cloudfront default cache behavior

Cloud­front default cache behav­ior settings

Then set the fol­low­ing under Set­tings:

  • Descrip­tion: Add a descrip­tion here that is mean­ing­ful to you, such as: www​.google​-ana​lyt​ics​.com reverse proxy for Partytown
Cloudfront settings

Cloud­front settings

You can cus­tomize any­thing else to suit your needs, but the defaults are gen­er­al­ly fine for most purposes.

Then click on Cre­ate Dis­tri­b­u­tion.

Cloudfront created distribution

Cloud­front dis­tri­b­u­tion created

That’s it, you’re done with the Cloud­front dis­tri­b­u­tion cre­ation! Copy the Dis­tri­b­u­tion domain name to the clipboard.

This is the pub­lic URL we’ll use to access the Cloud­front dis­tri­b­u­tion; in our case, it is d3sg51zspgx44x.cloudfront.net

The way it works is any request for any­thing like:

https://d3sg51zspgx44x.cloudfront.net/analytics.js

…will be prox­ied to the Cloud­front dis­tri­b­u­tion Ori­gin domain that we set when cre­at­ing it, in this case www.google-analytics.com:

https://www.google-analytics.com/analytics.js

And then thanks to the SimpleCORS Response head­ers pol­i­cy we set when cre­at­ing it, the Access-Control-Allow-Origin: * head­er will be auto­mat­i­cal­ly added.

🎉

Link Partytown Configuration

Now that we have our Cloud­front reverse proxy set up, we just need to add a bit of con­fig­u­ra­tion to Par­ty­town via the resolveUrl hook.

This lets us spec­i­fy a func­tion that will take the URLs that our scripts try to load, and map them to use our proxy instead.

Here’s an example:

<script>
  window.partytown = {
    resolveUrl: function (url) {
      const proxyMap = {
        'www.google-analytics.com': 'd3sg51zspgx44x.cloudfront.net',
      }
      url.hostname = proxyMap[url.hostname] || url.hostname;
      return url;
    },
  };
  // Inline the partytown.js script here
</script>

This just looks at the URL that is being request­ed, and if it match­es one of the ori­gin host­names that we need to proxy, it swaps the proxy host­name in instead.

It’s set up using a key: value object proxyMap so that if we need to add more prox­ies in, it’s easy to do!

🥳

Link Additional Considerations

The only real down­side to using Cloud­front as your Par­ty­town reverse proxy is that you have to cre­ate an addi­tion­al Cloud­front dis­tri­b­u­tion for each track­ing script ori­gin that needs the Access-Control-Allow-Origin: * head­er set.

But since this is so easy to do with a few clicks, and no code… it’s not much of an issue typically.

Anoth­er thing you might con­sid­er is set­ting up an AWS Web Appli­ca­tion Fire­wall (WAF) if you want to lock down your dis­tri­b­u­tion so only requests com­ing from your server’s IP can access it.

Or as an alter­na­tive to that, you could set the Access-Control-Allow-Origin head­er to your spe­cif­ic domain to make it use­less for any­one else. 

Link Party down in Partytown!

Hope­ful­ly, this write­up has helped you get over the hur­dle of CORS for some scripts, and let your track­ing scripts par­ty down in Partytown!

Party down in partytown

Par­ty on! 

🎉