Reducing the Impact of Third-Party Tags Andy Davies · Oct 2022 · #PerfNow @AndyDavies https://www.flickr.com/photos/digitizedchaos/3964206549

@AndyDavies https://www.flickr.com/photos/dharmabum1964/3108166405

Compete for the Network @AndyDavies

Compete for the Network @AndyDavies

Make us wait for new connections @AndyDavies

Fight for the Main Thread @AndyDavies

Fight for the Main Thread Before After @AndyDavies

They may provide important features too: Advertising Analytics Content Error Reporting Experimentation and Testing Personalisation Real User Monitoring Revenue Attribution Reviews Session Replay User Generated Content @AndyDavies and much, much more…

How do we find the balance between… …their benefits and their challenges? @AndyDavies https://unsplash.com/photos/rBLTWS3WsQ8

What’s on your page and where is it from? @AndyDavies https://requestmap.herokuapp.com

Some key questions… Are we still paying for it? Does anyone still use it? Are there any duplicates? For static content, can we replace it with a locally hosted version? What’s the tag’s impact on the visitor’s experience? When should we load it? Where should it be executed? @AndyDavies

May not be easy for Ad funded sites @AndyDavies https://requestmap.herokuapp.com

If page load is a journey… @AndyDavies

If page load is a journey… ??? ??? ??? ??? ??? ??? …where do our third-parties fit in? @AndyDavies

Early tags can have a Critical Impact Often parser or render blocking Compete for main thread even when loaded async Typical tags Tag Managers Experimentation Personalisation @AndyDavies

Avoid Render Blocking 3rd-Parties

<link rel=”stylesheet” href=”some-3rd-party.example.com/styles.css” /> <script src=”some-3rd-party.example.com/script.js”></script> @AndyDavies

Often focus on blocking requests failing… @AndyDavies

Often focus on blocking requests failing… @AndyDavies

But what happens when they succeed? @AndyDavies

Preconnect won’t save us… (And neither will early hints in this example) @AndyDavies

Might not be able to use it anyway…

<link rel=”preconnect” href=”third-party-origin.example.com”> @AndyDavies

Might not be able to use it anyway…

<link rel=”preconnect” href=”third-party-origin.example.com”> Discloses a visitor’s IP address to 3rd-party Did you ask for their consent first? @AndyDavies

https://www.theregister.com/2022/01/31/website_fine_google_fonts_gdpr/

If Google Fonts isn’t considered ‘legitimate usage’ Then surely static content from other third-party hosts isn’t either* * and I think that’s a good thing @AndyDavies

https://csswizardry.com/2019/05/self-host-your-static-assets/

I Am Not a Lawyer nor a Data Protection Officer @AndyDavies

I Am Not a Lawyer You nor should a talk to yours Data Protection Officer @AndyDavies

CMPs Need Consent before loading 3rd-Parties @AndyDavies https://www.flickr.com/photos/88709139@N08/21134399326

And some CMPs are faster than others @AndyDavies

An ideal candidate for edge compute? @AndyDavies https://www.flickr.com/photos/kewl/8475764430

Or should consent management be built into browsers? @AndyDavies

Consent brings other challenges too @AndyDavies

https://www.fastly.com/blog/taming-third-parties-with-a-single-origin-website

Cookies and Headers need to be filtered @AndyDavies https://www.flickr.com/photos/neuski/1486170673

There may still be difficult choices to make @AndyDavies https://www.flickr.com/photos/dno1967b/8347363864

Is a render blocking AB testing script worse than an anti-flicker snippet? @AndyDavies

Is a render blocking AB testing script worse than an anti-flicker snippet? And how does consent fit into the puzzle? @AndyDavies

Self Hosting may help but requires work https://man.gl/casper-self-host-optimizely

Other tags can wait until page is ‘complete’ What’s the point in loading interactive elements such as ▪︎ Chat ▪︎ Session Replay ▪︎ User feedback if our visitor is still waiting for the page to load? @AndyDavies

Watch for TTI / firstCPUIdle changes Delaying scripts will also delay any long tasks they generate Connection Setup Script Fetch Long Task Load @AndyDavies

Watch for TTI / firstCPUIdle changes Delaying scripts can also bring load forward and compensate Connection Setup Script Fetch Long Task Load @AndyDavies

Injecting preconnects can help For example inject a preconnect at DCL for a late loaded script Connection Setup DCL @AndyDavies Script Fetch Long Task Load

Tag Managers can help schedule loading @AndyDavies

Could the tag be loaded on interaction? @AndyDavies https://www.flickr.com/photos/joeyz51/50226695988

https://calibreapp.com/blog/fast-live-chat

https://github.com/paulirish/lite-youtube-embed

https://antonioufano.com/articles/improve-web-performance-lazy-loading-recaptcha/

@AndyDavies https://www.flickr.com/photos/pherk/4492973614

The ‘Messy Middle’ This is a fuzzy area… Does the tag provide user content? How much data loss are you willing allow? Try not to block the browser Server-Side Tagging helps @AndyDavies

Example From a newspaper I worked with in early 2021 @AndyDavies

Prioritise by Importance and Urgency Delaying less important content stops it competing for network and device resources with more important content Start of Page Load End of Page Load Prioritise important and urgent content (from both visitor and commercial perspectives) Less important and less urgent content should be loaded later Time @AndyDavies

Categorise into strategic buckets Start of Page Load Core Content End of Page Load Consent Management Primary Partners Secondary Partners Time (not to scale) @AndyDavies Secondary Content Leftovers

How existing content fits this strategy There will be some blurring of the boundaries between the buckets, and some challenges e.g. JW Player waits for Permutive, it’s also possible to defer some content until visitor scrolls. Shrinking content size (both core and partner) is still important too. Start of Page Load Newspaper End of Page Load GPT Taboola AMP Prebid PolarMedia JW Player Permutive Core Content Quantcast Consent Management Primary Partners Recaptcha SailThru Airship Secondary Partners Time (not to scale) @AndyDavies ViaFoura Secondary Content Leftovers

Where should a tag be executed? @AndyDavies https://www.flickr.com/photos/hugosimmelink/2673580935

Generally, tags execute on the main thread But there are some interesting alternatives @AndyDavies

Server-Side Tagging = Less Tags & Beacons Own Hosting GTM Container @AndyDavies Server-Side Container

What about executing on the Edge? @AndyDavies https://www.flickr.com/photos/johann-in-london/92533884

https://github.com/WICG/proposals/issues/54

We can execute tags in workers too https://partytown.builder.io/ @AndyDavies

A multitude of options to consider! Server Side Edge Worker Main Thread @AndyDavies Response Start FCP CMP Load Tag Manager Load DCL Page Load Interaction

@AndyDavies https://www.flickr.com/photos/nikkvalentine/16077068743

Monitor third-party performance @AndyDavies

Measure with and without Consent Requests Size (KB) @AndyDavies 41 + 55 589 + 1280 41 + 128 589 + 1750

And maybe even without 3rd-Parties? Requests Size (KB) @AndyDavies 41 + 11 589 + 246 41 + 55 589 + 1280 41 + 128 589 + 1750

Track Tag Container Releases @AndyDavies

Track Tag Container Releases GTM only supports email notifications ! @AndyDavies

https://github.com/andydavies/gtm-watcher

V https://www.flickr.com/photos/shoesmiths/5427623567 https://www.flickr.com/photos/wwarby/7109538317

How long is an anti-flicker snippet active? (function (node, selector, name) { performance.mark(name + ‘-start’); const callback = function (mutationsList, observer) { // Use traditional ‘for loops’ for IE 11 support for (const mutation of mutationsList) { if (mutation.attributeName === ‘class’ && !mutation.target.classList.contains(selector) && mutation.oldValue.includes(selector)) { performance.mark(name + ‘-end’); performance.measure(name + ‘-duration’, name + ‘-start’, name + ‘-end’); observer.disconnect(); break; } } } const observer = new MutationObserver(callback); observer.observe(node, { attributes: true, attributeOldValue: true }); @AndyDavies })(document.documentElement, ‘async-hide’, ‘anti-flicker’);

When is an IAB EU CMP Ready? // Creates User Timing marks for cmpuishown, useractioncomplete & tcloaded if (typeof window.__tcfapi === ‘function’) { window.__tcfapi(‘addEventListener’, 2, (tcdata, success) => { if(success) { performance.mark(‘tcf-’ + tcdata.eventStatus); // Stop listening after TCF loaded, or user action complete to prevent generation // of extra cpuishown & useractioncomplete marks if visitor reopens CMP UI if(tcdata.eventStatus === ‘useractioncomplete’ || tcdata.eventStatus === ‘tcloaded’) { window.__tcfapi(‘removeEventListener’, 2, (success) => { }, tcdata.tcfListenerId); } } }); } @AndyDavies

When did a GPT creative load? var googletag = googletag || {}; googletag.cmd = googletag.cmd || []; googletag.cmd.push(function() { // This listener will be called when the creative’s iframe onload event fires googletag.pubads().addEventListener(‘slotOnload’, function(event) { performance.mark(‘adslot-’ + event.slot.getSlotElementId() + ‘-loaded’); }); }); @AndyDavies

https://github.com/andydavies/tag-timing-snippets

@AndyDavies https://www.flickr.com/photos/brisbanecitycouncil

Let’s return to our 3rd-Party Puzzle @AndyDavies https://www.flickr.com/photos/mattyp/4173076669

Before After @AndyDavies

Profile the page @AndyDavies

Read the Source… @AndyDavies

@AndyDavies

https://github.com/krux/postscribe/

https://github.com/krux/postscribe/

Postscribe is only included if this box is checked @AndyDavies

And only needed if the tag uses document.write* Postscribe is only included if this box is checked @AndyDavies

  • not needed if page uses document.open, document.write, document.close sequence

Find “vtp_supportDocumentWrite”:\s?true, @AndyDavies

Find “vtp_supportDocumentWrite”:\s?true, @AndyDavies

Find “vtp_supportDocumentWrite”:\s?true, @AndyDavies

Find “vtp_supportDocumentWrite”:\s?true, @AndyDavies

Postscribe removed from George Clothing @AndyDavies https://mobile.twitter.com/rnebhwani/status/1376514746107752452

What other secrets does GTM hold? @AndyDavies https://www.flickr.com/photos/david44149/49811626782

Add log points for DOM operations @AndyDavies

Add log points for DOM operations @AndyDavies

@AndyDavies

@AndyDavies

@AndyDavies

@AndyDavies

Some other things we discovered… ▪︎ When Google Optimize is enabled it adds another copy of Analytics (even if you don’t actively use Optimize) ▪︎ Custom Google Analytics dimensions can be expensive when set from GTM (we removed unused ones) ▪︎ Other miscellaneous cleanups I suspect we just ‘scratched the surface and there was other gains to find @AndyDavies

Before After @AndyDavies

3rd Party Tags can make or break your visitor experience Make friends with the team that manages your tags Audit tags - remove the ones that aren’t needed Don’t accept the defaults - choreograph tag loading Push the boundaries beyond the browsers main thread Chase 3rd-Parties to fix their issues @AndyDavies

https://www.tunetheweb.com/blog/adding-controls-to-google-tag-manager/

https://man.gl/telegraph-3rd-party-performance

Taming Tags improves user experience @AndyDavies

It can also deliver financial benefits Median Page Load Time (s) 14 Android iOS 26% increase in revenue from Android visitors 12 10 8 6 4 2 0 ee W ee W ee W ee W ee W ee W k k k k k k 5 5 3 2 1 0 @AndyDavies

Thanks! @AndyDavies hello@andydavies.me