Reduce the Impact of Third-Party Code (With/Without Plugins)

Last updated on Oct 7th, 2021 | 22 min

Third-party scripts are a necessity in the modern web. They allow website owners to embed videos and social sharing buttons, analyze their website’s performance, and much more.

Often, these scripts are crucial for one’s website functionality and revenue streams. However, third-party resources come with many hidden risks that may hinder your site’s overall performance.

PSI Suggestion

That’s why it’s important to minimize their negative impact while still utilizing their valuable features.

And in the following lines, you’ll learn how to do that. 

Let’s dive in! 
 

How Third-Party Scripts Impact Web Performance

Nowadays, running a website without a single third-party script seems not only impossible but rather impractical. 

Regardless of your site’s type, there are certain functionalities that you and your visitors need to have access to.

For instance, you run a personal blog, and want your content to reach as many people as possible. One solution is to add social sharing buttons. 

Furthermore, you want to deeply analyze your visitors’ behavior on your website. For that, you’ll need tools like Hotjar and Google Analytics. At some point, you’d like to monetize your work, and a great way to do that is by adding advertising iframes.

In short: 

To get the most out of your site, you need to rely on 3rd party scripts. And there’s nothing wrong with that, at least in most cases. 

Unfortunately, embedding third-party resources means you rely on them to be fast in order to avoid slowing down your site. Hence, it’s normal for them to be the predominant cause of performance slowdowns as they’re outside your control. 

Here are some of the issues that you might face when integrating third-party scripts into your website:
 

#1: Firing too many network requests to multiple servers

Sending too many network requests to multiple servers causes slowdowns. That time is even longer for secure connections, which may involve DNS lookups, redirects, and several round trips to the final server that handles the user's request. 


#2: Blocking the Main Thread due to excessive JavaScript usage

The Main Thread is where the browser does most of the work needed to display a page. That’s why it’s crucial to minimize Main Thread work as much as possible. 

JavaScript runs on the Main Thread by default. When the Main Thread is busy with JavaScript, it can't perform vital tasks like rendering the page or respond to user input. That's why JavaScript is a render-blocking resource. As a result, you’ll end up with a slow loading, non-interactive website - the best formula to lose customers immediately.

Main Thread Work

#3: Insufficient HTTP Caching

Having insufficient HTTP caching forces resources to be fetched from the network more often. And this is both slow and expensive (in both speed and server resources), especially when those network requests are sent to multiple servers. 

As a consequence, your page will load slowly.  Even worse, when visitors access your site with a limited mobile data plan, every unnecessary network request is a waste of their money.
 

#4: Some Scripts Don’t Let Themselves Load Asynchronously

Loading third-party scripts asynchronously is one of the solutions when it comes to optimizing their work. However, some scripts cannot be loaded asynchronously because they use document.write()

The bigger issue, however, is the use of document.write() inside pages, specifically those uses that inject scripts. If the script dynamically injects another script, the parser is forced to wait even longer for the resource to download, which can incur one or more network round trips and delay the time to first render of the page:

document.write()

document.write() can delay the display of page content by tens of seconds and is particularly problematic for users on slow connections (e.g., 2G). While 2G has reached its sunset date in many countries, there are still users around the world that heavily rely on it to browse the web. 

That’s why Chrome intervenes against document.write(), meaning you can't rely on it.

 

#5: Some Third-Party Scripts Can Block window’s load event

The window.onload event says to fire a function only once the window and all its HTML tags, fonts, and images are loaded. Basically, it’s a way for the browser to notify the code that it has completed loading the initial resources of a page.

Oftentimes, the interactive elements on a page become interactive after this event. If it gets delayed, the page will take more time to respond to user input.

And in some cases, third-party scripts use techniques that can block the window.onload event if their server responds slowly. Resulting in a bad user experience.

The truth is that context is important when it comes to optimizing the work of third-party scripts. It all depends on your site and your ability to identify the resources that cause the problems and then configure them to load more efficiently.

Thankfully, there are a number of free resources that you can use to identify and measure costly third-party scripts. 

Let’s take a look at some of them.


How to Identify and Measure Third-Party Scripts on Your Page

The first step to solving the third-party resource problem is to identify and measure the most impactful ones.

Tools like Google’s PageSpeed Insights, WebPageTest, and Chrome DevTools will highlight all third-party scripts that your website is loading and show which ones take the most time.

Google’s PageSpeed Insights

Google’s PageSpeed Insights is the easiest way to identify and measure third-party scripts on your website. The “Reduce the impact of third-party code” audit is a good starting point:

PSI Audit


It lets you instantly see how impactful the third-party scripts on your site are. In the example above, you can see that they blocked the Main Thread for 2,490 ms

You can dig deeper by going through the list of all third-party code that is executed on your site. The great thing is that PSI sorts it by Main-Thread Blocking Time. This evaluation allows you to focus on the most impactful ones and start working on them.  

PSI results

Another audit you might benefit from is the Treemap:

PSI treemap

It shows all JavaScript files executed on your website, sorted by their size:

treemap

And next to the Resource Bytes column, you have the Unused Bytes one, showing what % of the JS remains unused. 


WebPageTest

WebPageTest’s content breakdown by domain is another valuable tool for debugging third-party issues. Going to the Domain section, you will see a thorough breakdown by the number of requests and bytes for each domain:

WebPageTest domain breakdown

WebPageTest also has a waterfall chart where you can see all the render-blocking resources and allocate all third-party scripts and their execution time:

webpagetest waterfall chart

Once you find third-party resources that might be causing issues, it’s time to test if they are really the culprit. Go back to WebPageTest’s home page, open the Advanced settings, and click on the Block feature:

Then you can specify the domains you would like to block by entering them in the forms below. Test again and see if there is any improvement. 

webpagetest block resources


Chrome’s DevTools

Another great way to analyze possible issues even deeper is using Chrome’s DevTools. Just open a web page, right-click and select “Inspect”. Then, capture the page load and go to the “Performance” panel.

Clicking the record button and re-loading your page presents you with a waterfall (similar to the one in WebPageTest):

devtools inspect

At the bottom of the Performance panel, you will see the “Bottom-up” tab:

devtools bottomup

Click on the drop-down menu and select “Group by Domain.” In the example above, we can see how moatads.com contributes 22.7% of the work that happens when loading the page. 

Using this knowledge, you can more accurately pinpoint problem areas and begin investigating with some evidence behind you. Once you’re done identifying the culprit, you can block the specific third-party script to see how impactful it really is.

Go to the “Network” panel, right-click on the resource and select “Block request URL”:

block request

This is a great way to see what the absence of a particular asset would have on the current page.

Now, let’s see how to deal with third-party resources.

Load Third-Party Scripts Efficiently

There are several optimization techniques that you might want to try when working with third-party scripts:

  • Use lazy-loading to load embedded resources only when necessary;
  • Implement async and defer attributes;
  • Avoid third-party scripts that use document.write();
  • Self-host resources to gain more control over them;
  • Establish early connections via preconnect and dns-prefetch resource hints;
  • Consider removing scripts that don’t add value.

Let’s take a closer look at each of them.


Lazy Load Third-Party Resources 

A single web page is constructed of different resources. However, not all of them are critical for providing the best user experience right from the start.

Users want to see content being painted quickly and experience a website that becomes interactive immediately. That’s why it’s good to keep an eye on these several metrics: 

  • First Paint measures how long it takes for the browser to render anything on the page, not just DOM content. This could be a background change, for example;
  • First Contentful Paint is the time it takes for the browser to visualize the first piece of DOM content (e.g., image, non-blank canvas element) on a page;
  • Largest Contentful Paint measures the time it takes for the largest above-the-fold content element to load;
  • First Input Delay (FID) measures the delay between a user’s first interaction and the moment the browser can respond.

In short:

To retain your visitors longer, your site needs to be fast and interactive. Or at least it needs to give that impression

This is where lazy loading comes into play. Typically used in the context of images, you can lazy load (defer) third-party resources as well, making them load only when necessary. This way, you can focus on serving the most critical content (above the fold) first, and load everything else once the visitor scrolls down.

above the fold


Going back to our example of a person running their own blog, they might be serving an ad in their website’s footer. If they lazy load it, it will be served only when a visitor scrolls down to it.

NitroPack offers a JavaScript lazy loading feature that works based on user interaction and it is enabled by default with our Ludicrous mode. It prioritizes HTML and CSS files, while deferring JS files, resulting in faster content painting and a better user experience. 

On top of that, you can fine-tune the JavaScript feature by listing scripts that you want to exclude from optimizations and scripts that must be delayed: 

exclude js

delayed scripts


Use async and defer Attributes

Synchronously loaded scripts delay DOM construction and block rendering. That’s why you should load third-party scripts asynchronously (unless the script has to run before the page is rendered).

The async and defer attributes allow the browser to parse the HTML while loading the render-blocking scripts in the background. This way, script downloads don't block DOM construction and page rendering, resulting in faster loading and happier visitors.

While both attributes make scripts non-blocking, they also have some differences:

  • Scripts with the defer attribute keep their relative order. Let’s say we have two scripts - script 1 and script 2 in that order. If we defer both, the browser will always execute script 1 first, even if script 2 was downloaded first. Deferred scripts are also executed before the DOMContentLoaded event. In other words, they run only after the HTML has been loaded and parsed but before the window’s load event.
     
  • Scripts with the async attribute are completely independent. Whichever is downloaded first is executed first. They also run independently of the DOMContentLoaded event, i.e., they can be executed even if the document hasn’t been fully downloaded. This means they can interrupt DOM building if they finish downloading while the parser is still at work.

Put simply, scripts that need the DOM or whose order is important should use the defer attribute. Conversely, ad, analytics, and other independent scripts should generally use async.


Avoid Third-Party Scripts That Use document.write()

Speaking of the async attribute, some third-party resources can’t be loaded asynchronously because they use document.write().

document.write() is particularly used for older services that haven’t been updated recently. However, third-party scripts using it can delay the page rendering by seconds, which is particularly problematic for users on slow connections (e.g., 2G).

In fact, it has such a negative impact on performance that Chrome decided to intervene:

“Chrome, starting with version 55, intervenes on behalf of all users when we detect this known-bad pattern by changing how document.write() is handled in Chrome.”


The fix for document.write() is to simply not inject scripts using it. As of Chrome 53, Chrome DevTools logs warnings to the console for problematic use of document.write():

document.write warning

Self-Host Third-Party Resources

We started this article by saying that 3rd party scripts are resources outside of your control which makes them harder to manage.

Well, self-hosting them is an option that will give you more control over a scripts’ loading process. Furthermore, it also lets you:

  • Reduce DNS lookup and round-trip times as everything will be stored on your server;
  • Improve HTTP caching headers;
  • Take advantage of HTTP/2 server push which reduces latency by enabling full request and response multiplexing and minimizing protocol overhead.


Although it might sound like it, self-hosting isn’t the perfect solution and there are some caveats you need to consider:

  • Self-hosting a script means that you have to manually update it so that it has all the latest security fixes;
  • Your self-hosted scripts won’t be automatically updated via API changes. This may result in a script malfunctioning or not working;
  • Some scripts don’t even work when they are being self-hosted;
  • There can also be legal implications on some resources - mostly fonts.

An alternative to self-hosting scripts where you still have more control would be using Service Workers.  We won’t dig deeper into the topic right now, but if you’re interested, check Matt Gaunt’s article on Service Workers.

Apart from heavy JavaScript files, you might want to self-host third-party fonts as well. According to Ilya Grigorik:

“A "full" WebFont that includes all stylistic variants, which you may not need, plus all the glyphs, which may go unused, can easily result in a multi-megabyte download.”


As opposed to many third-party scripts, font resources are typically static and not updated frequently. Put simply, they offer easier maintenance compared to self-hosted third-party scripts.

However, you should make sure that the font’s license allows self-hosting. Otherwise, you might be breaking the law. A popular service that allows self-hosting their fonts is Google Fonts.


Establish Early Connections

Browsers go through three stages to establish a connection with a server  - turning the domain name into an IP address, setting up a connection to the server, encrypting the connection for maximum security. 

In each of these steps, a piece of data is sent by the browser and the server sends back a response. This is called a round trip. 

Depending on the network conditions, a single round trip might take a significant amount of time. That’s why implementing resource hints like <link rel=preconnect> and <link rel=dns-prefetch> can optimize the work of the browser, making your website/application load faster.

  • Adding <link rel=preconnect> informs the browser of your page’s intent to establish a connection to another domain, and that you'd like the process to start as soon as possible. Resources will load more quickly because the setup process has already been completed by the time the browser requests them. According to Google, you can speed up the load time by 100–500 ms by establishing early connections to the most critical third-party resources.
     
  • The <link rel=preconnect> works best for the most critical resource. For the rest, use <link rel=dns-prefetch> to reduce DNS lookup time, which usually takes around 20–120 ms.


Remove Unused 3rd Party Scripts 

It’s far easier to remove a script than to optimize it. Or is it? 

You should regularly check for unused third-party scripts and remove them entirely. 

You can check if you have unused JavaScript in Chrome’s DevTools. Use the “Coverage” tab to find these code snippets:

unused js

This is a really good practice for CMS websites, where third-party code is regularly inserted via plugins and might be left over after the plugin is no longer used. Running a simple audit like the one shown above can lead to an easy performance boost. 


Recap 

We covered a lot of ground with this article, so let’s end with a quick recap of the most important points:

  • Third-party scripts are necessary in the modern web as they allow you to build an interactive and interconnected website and expand your revenue streams;
  • However, embedding third-party resources means you rely on them to be fast in order to avoid slowing down your pages;
  • You can identify third-party scripts and measure their contribution to your site’s performance by using free tools like PSI, Chrome’s DevTools, and WebPageTest;
  • Lazy loading is a technique that  allows you to load third-party code only when necessary;
  • Using the async and defer attributes ensure  script downloads won't block DOM construction and page rendering;
  • Avoid scripts that use document.write() because they cannot be loaded asynchronously;
  • You can self-host some of the third-party scripts you’re using, just make sure to update them regularly. Otherwise, they might malfunction, stop working, or make your site vulnerable to security breaches;
  • Establish early connections by implementing resource hints like and . Use the former for the most critical resources, and the latter for everything else;
  • If a third-party script adds no value to your website, remove it. Then, check if you’ve completely removed it, using Chrome’s DevTools.

After every optimization, don’t forget to test your website in the real world. Focus on real-user metrics (like the Core Web Vitals’ field values) to make sure your work has a positive impact on your visitors. 

Niko Kaleev
Content Writer

Niko is one of the NitroPack storytellers. He is passionate about writing quality content and turning complex optimization concepts into engaging articles.