Ofer For You (1)

Monday, 30 October 2023



Google Tag Manager can influence your overall website performance just as any other external 3rd party script. Luckily, there are a couple of things that you can do in that regard.

We love good website performance, not just because it is a big piece of the puzzle of great user experience, but also because it is one of the key factors for page ranking, and it can cut your AdWords prices. Our long list of blog posts on the subject is a testament to that, check out Frontend performance measuring and KPIs, Frontend performance: fast web fonts, or Speeding Up Next JS Websites By Removing JavaScript, as just a few examples on the matter.

External scripts, many of them provided by Google Tag Manager, are often blamed as the reason why a website performs poorly. Let’s investigate why and how we can turn things around and get that sweet high-performance score back while keeping Google Tag Manager.


What is Google Tag Manager?

Google Tag Manager, or just GTM, is one of the most popular services for managing external scripts on websites. It allows you to register all kinds of scripts or tags, as GTM calls it, and it will execute those scripts alongside the rest of your application scripts when the web page loads.


This only works after your alter the source code of the website, and insert a couple of lines of code on the frontend of the website, which looks something in the lines of this:


<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXX');</script>
<!-- End Google Tag Manager -->


These lines of code will download the GTM handler, as well as register a global object, defaulted to “dataLayer”, which you use to talk to GTM. GTM will now load all the scripts that you have defined in our GTM account that should run when the page loads.

Google Tag Manager Slowing Down Site


Picture this: you and the rest of your team have been working hard on building a fast website site, and the launch date is getting close. Your speed tests show great numbers, and everyone involved is stoked about the website. Here is an example site I made for this blog post:



Now, not long before the site's launch, your team is told to add GTM, pointing to the already existing (and working) set of external scripts. This is done, and immediately the performance scores take a massive hit. Going from top-notch scores to something that no one would ever brag about.




Does this sound familiar?

It certainly does to me. I’ve seen countless sites, often larger enterprise ones, being slowed down by a plethora of scripts that are not managed by the application itself but by GTM.


Why are these scripts bad for performance? Truth be told, not all of them are. Some are just forwarding user behavior, sending tiny payloads to an external service. Others are not so kind.


Take an externally managed cookie disclaimer, for instance. For many websites, it is loaded using GTM and has a negative impact on the LCP Core Web Vital metric, as it tends to be the biggest element on the page and renders very late. Not a good experience for the user, as they often experience a slight period where they can browse the site before a large banner covers the bottom part of their screen.


Another example is A/B testing scripts that change the elements on the page after the script has been downloaded. First off, this is not a good experience for the user, who might see parts of the page that their reading suddenly moves, or disappear, causing a great negative impact on the CLS core web vital metric.


These are just two examples amongst tons of other scripts that impact performance in one way or another. What they all have in common is that none of them are controlled by the team that carefully crafted the website, making them difficult to control, causing both performance issues as well as issues with navigation and layout, because any script can perform any kind of action on the page.


Load GTM Fast by Loading Less Scripts


The best solution of them all is to simply load fewer external scripts. Move things in GTM scripts into the application code, the cookie banner, for instance, and reclaim control over the initial layout. If you’re doing A/B testing using GTM scripts, then you should absolutely move them into the application code as well, as it will be better for both user experience and page performance.

Load GTM Fast by Lazy Loading Scripts


Regardless if you can move external scripts into the application code, you should look into claiming more control over what and when GTM scripts are being fired. Very often GTM will execute a script when the page loads, but not all scripts need to be executed simultaneously. You can achieve better script orchestration by defining your custom GTM triggers for the scripts.

A custom trigger is something you set up in GTM and then call from the application code at the appropriate time. It can look like this:dataLayer.push({ 'event': 'pageIsIdle' });


Here is an example of two simple custom triggers that you can use in your setup:

blockUser

This is essentially the same as the “pageLoad” event and will execute the scripts as soon as the GTM container is ready. This is where you’ll find most scripts in GTM fire today, and it will, as the name suggests, block the user journey. So only the very most critical scripts go here.

doNotBlockUser

This is the game-changer trigger. Scripts that are bad for the performance go here. You need to define a good point in time when this trigger will be active, and I suggest you look into the requestIdleCallback API, which indicates that the client device is not busy with other things to avoid conflict with the application runtime activities.

The naming of these triggers is important. They convey a message beyond when they will trigger, and anyone who wants to put a script in the “blockUser” trigger will then know that adding this script will block the user journey, potentially negatively impacting the conversion rate and user satisfaction.

Load GTM Fast with Partytown


If you don’t have an existing GTM setup to worry about, then using Partytown to manage GTM might be a good idea. It works by moving all the script execution to its web worker, thus freeing up the main browser thread to only deal with application code. In theory, it will solve most of the performance issues mentioned above, but there is a chance that not all scripts will work out of the box as the scripts are not running in their usual context.

Load GTM Fast with Server Side Tracking


An often overlooked opportunity, but it is possible to track certain things on the server. This works by only executing the simple GTM shell on the client, then forwarding all of the events to your cloud server where you would handle the events.

Segment is another popular player in this space, which can offload client-side work onto its infrastructure.

Performance Testing as Part of the Development Process


You want to stay on top of things and ensure that the performance of your website never drops. Check out our advice on Frontend Performance Measuring & KPIs or deep dive with the frontend performance checklist we at H2K tend to use.

Performance audits should be part of our automated CI setup and provide appropriate alerts when the performance drops below the desired level. The tests on the CI should target an environment similar to the actual production environment so that you catch all of those tags that might not execute in a development setup.

You should also set up these tests to run at a recurring intervals since changes to the GTM container are not connected to the application code and deployments.

Conclusion


Remember the example above? After seeing the drop in performance, I implemented a custom trigger setup similar to what I suggest here. The results measured after these were added speak for themselves.



How’s that for performance scores?

Friday, 24 July 2020

TDD Changed My Life

TDD Changed My Life

It’s 7:15 am and customer support is swamped. We just got featured on Good Morning India, and a whole bunch of first time customers are bumping into bugs.
 
It’s all-hands-on-deck. We’re going to ship a hot fix NOW before the opportunity to convert more new users is gone. One of the developers has implemented a change he thinks will fix the issue. We paste the staging link in company chat and ask everybody to go test the fix before we push it live to production. It works!
Our ops superhero fires up his deploy scripts, and minutes later, the change is live. Suddenly, customer support call volume doubles. Our hot-fix broke something else, and the developers erupt in synchronized git blame while the ops hero reverts the change.

 

Why TDD?

It’s been a while since I’ve had to deal with that situation. Not because developers stopped making mistakes, but because for years now, every team I’ve led and worked on has had a policy of using TDD. Bugs still happen, of course, but the release of show-stopping bugs to production has dropped to near zero, even though the rate of software change and upgrade maintenance burden has increased exponentially since then.

Whenever somebody asks me why they should bother with TDD, I’m reminded of this story — and dozens more like it. One of the primary reasons I switched to TDD is for improved test coverage, which leads to 40%-80% fewer bugs in production. This is my favorite benefit of TDD. It’s like a giant weight lifting off your shoulders.

On my projects, our suites of automated unit and functional tests prevent disastrous breaking changes from happening on a near-daily basis. For example, I’m currently looking at 10 automated library upgrades from the past week that I used to be paranoid about merging because what if it broke something?

 

What is TDD?

TDD stands for Test Driven Development. The process is simple:

1.    Before you write implementation code, write some code that proves that the implementation works or fails. Watch the test fail before moving to the next step (this is how we know that a passing test is not a false positive — how we test our tests).

2.   Write the implementation code and watch the test pass.

3.   Refactor if needed. You should feel confident refactoring your code now that you have a test to tell you if you’ve broken something.

 

On the surface, it may seem that writing all those tests is a lot of extra code, and all that extra code takes extra time. At first, this was true for me, as I struggled to understand how to write testable code in the first place, and struggled to understand how to add tests to code that was already written.

TDD has a learning curve, and while you’re climbing that learning curve, it can and frequently does add 15% — 35% to implementation times. But somewhere around the 2-years in mark, something magical started to happen: I started coding faster with unit tests than I ever did without them.

 

 

How TDD Saves Whole Teams Time

I mentioned before that testing first leads to improved test coverage. The reason for that is that we don’t start writing the implementation code until we’ve written a test to ensure that it works. First, write the test. Then watch it fail. Then write the implementation code. Fail, pass, refactor, repeat.

That process builds a safety net that few bugs will slip through, and that safety net has a magical impact on the whole team. It eliminates fear of the merge button.

That reassuring coverage number gives your whole team the confidence to stop gatekeeping every little change to the codebase and let changes thrive.

Removing fear of change is like oiling a machine. If you don’t do it, the machine grinds to a halt until you clean it up and crank it, squeaking and grinding back into motion.

Without that fear, the development cadence runs a lot smoother. Pull requests stop backing up. Your CI/CD is running your tests — it will halt if your tests fail. It will fail loudly, and point out what went wrong when it does.

And that has made all the difference.