Working with Gatsby JS
Updated over a week ago

This article addresses concerns that users commonly have for using Webtrends Optimize on websites built using Gatsby JS, including why we doesn’t suffer from those issues and/or how we overcome them.

Gatsby JS is built on React

Single-page apps built using React, Vue, Angular etc. have generic ways you can hook into route changes (Mutation Observers). We follow this pattern for Gatsby.

One key challenge for all front-end experimentation tools is when the environment is highly dynamic. Single-page apps built using JavaScript frameworks like React, Vue and Angular fall into this bracket of “highly dynamic pages”.

For static (or relatively static) websites built using tools like Gatsby, the key challenge is being able to hook into route changes, i.e. knowing that a user navigates through the app from Page 1 to Page 2. And, with this knowledge, being able to re-render experiments without exhibiting [Content Flickering].

This is an even bigger challenge for Webtrends Optimize – unlike other tools like ours, we don’t keep all tests and locations in your tag – we only download the bits a user needs onto their machine when they need it. Between route changes, we therefore need to fetch any tests running on the new page too.

How we deal with Single Page Apps

There is one piece of customisation we do to make this happen: Mutation Observers to pick up on route change

React Apps (thankfully) rotate URLs just before updating the DOM, which is incredibly useful for us. It means that when we pick up on DOM changes using mutation observers, we can also lookup URL changes in that moment for location-matching.

For Gatsby apps, we create mutation observers to look for changes to the child nodes in two places: #gatsby-focus-wrapper and #gatsby-focus-wrapper > main. In our experience, route changes typically trigger an update to the childlist on at least one of the two of these elements.

What does this mean?

By setting mutations, we can capture the precise moment where your old page unloads, and where the new page loads in. Importantly, just before anything visual shows up for the user.

By being able to act in this precise moment, we can then:

  1. Check which tests need to run on the new page.

  2. If we find any, mask the page.

  3. Fetch and execute them.

  4. Unmask the page.

This process ensures there’s no content flickering.

What if my selectors happen to be different?

The process is solid, but if your selectors differ that’s fine – that’s why we call it a customisation. It’s simply a string that we define in your tag – something you have access to and can modify if you ever feel the need to. We’ll typically set this up for you though, so you don’t need to worry.

Classname Minification/Obfuscation

As your experience grows with running experiments, you'll find that clarity and ease are favoured over things like obscurity and fractional performance gains. The plugins discussed below are detractors to building experiences in 3rd party tools, but we'll discuss how we deal with the situations regardless.

Given the ease of Gatsby’s plugin architecture and popularity of plugins like gatsby-plugin-minify-classnames, it’s not surprising to see classnames which are either completely minified/obfuscated, such as:

Or adopt a pattern where classnames will be preserved, but are suffixed with these anonymous names:

Thankfully, we use relative paths that focus on node-names and their position amongst siblings (using :nth-child), so we don’t actually consider classnames. We do rely on IDs, which are not minified using plugins like the one mentioned.

Example of selector we build:

As you can see here, we don’t store a single classname despite ones being present on every element. It therefore doesn’t matter whether they’re minified or not.

As your experience grows with running front-end experiments, you’ll typically find that such tools are used less. As developers, you should be considering the full spectrum of how your website is used, and ensuring that activities such as experimentation are also made as easy as possible. What little you’ll gain from minified classnames may be offset by the time and effort for someone to work out how to run experiments on these anonymous elements.

Did this answer your question?