Gatsby Script API
Support for the Gatsby Script API was added in
Gatsby includes a built-in
<Script> component that aids in loading scripts performantly.
It offers a convenient way to declare different loading strategies, and a default loading strategy that gives Gatsby users strong performance out of the box. It supports both scripts with sources and inline scripts.
Whether you want to leave the heavy lifting of managing scripts to Gatsby or you want maxiumum flexibility and control, the Gatsby
<Script> component is a great tool for the job.
Using Gatsby Script in your site
Here is an example of how you can import and use the
<Script> component in your site’s JSX or TSX source files:
If you have existing scripts, using the Gatsby
<Script> component is as simple as importing
Script and changing lowercase
script tag names to capitalized
Script tag names in most cases:
By default, the
<Script> component will load your script after hydration. For more information on declaring loading strategies, see the Strategies section.
Scripts with sources and inline scripts
There are two types of scripts that you can tell the
<Script> component to load:
- Scripts with sources
- Inline scripts
Scripts with sources
Scripts with sources provide a
src property like this:
<Script> component will use the value of
src to deduplicate loading, so if you include two scripts on the same page with the same
src, only one will load.
If for some reason you need to load two scripts with the same sources on the same page, you can provide an optional, unique
id property to each and the
<Script> component will attempt to load both:
Inline scripts must include a unique
id property and can be defined in two ways:
- Via React’s special
- Via a template literal
Here’s a look at both:
Functionally, both of these ways of defining inline scripts are equivalent.
You can declare a loading strategy by passing a
strategy property. These are the available loading strategies:
post-hydrate(default) - Loads after the page has hydrated
idle- Loads after the page has become idle
off-main-thread(experimental) - Loads off the main thread in a web worker via Partytown
Here’s how you can define these strategies in the
Additionally, Gatsby exports a
ScriptStrategy enum that you can use in TSX files if you prefer:
Post hydrate strategy (default)
post-hydrate strategy is the default loading strategy and will be used if you do not specificy a
The advantage of this strategy is that you have the ability to declare that your script should start loading after hydration. This is impactful because hydration is what makes your page interactive, and by using regular
<script> tags (even with
This can have negative implications for key web vital metrics like Total Blocking Time. By leveraging the
<Script> component with the
post-hydrate strategy, you ensure that your script avoids interfering with your page reaching an interactive state, resulting in a better experience for your users.
post-hydrate strategy is ideal for cases where you want to make sure a script loads early without impacting your site’s time to interactive.
idle strategy is similar to
post-hydrate in that it loads after hydration, with the difference being
idle will tell the browser to load the script when the main thread is free.
This means that if your page is doing other crucial work such as DOM manipulations or other calculations that occupy the main thread, your script will wait until after that work is complete to start loading.
idle strategy is ideal for cases where you want to ensure a script loads in a way that does not compete with other work being done on the main thread.
Off main thread strategy (experimental)
off-main-thread strategy, unlike
idle, loads your script in a web worker via Partytown.
This means that the burden of evaluation of your script is no longer the concern of the main thread, freeing it up to take care of other crucial tasks.
Note - Due to Partytown’s status as beta software, the
off-main-threadstrategy is considered experimental. It is subject to certain limitations and may require more configuration than other loading strategies depending on your use case.
Here is an example configuring the
<Script> component with the
off-main-thread strategy to load Google Analytics:
Gatsby will collect all
off-main-thread scripts on a page, and automatically merge any Partytown forwarded events defined via the
forward property into a single configuration for each page:
forward property is the only Partytown-specific property that is handled by the
All URLs provided to the Gatsby
<Script> component with the
off-main-thread strategy are proxied by Gatsby to
The reason for this is many third-party scripts require a proxy to work in Partytown, so Gatsby includes built-in proxy functionality to make this easier.
To keep the proxy secure, you must define the absolute URLs you want proxied in your Gatsby config with the
partytownProxiedURLs key. If you do not do this, the the request will 404.
Here’s how you would do that for the Google Analytics example above:
This works out of the box when running your site via
gatsby serve and Gatsby Cloud.
Hosting on other providers requires support for Gatsby’s
createRedirect action to rewrite requests from
YOUR_URL with a 200 status code. You may need to check with your hosting provider to see if this is supported.
You can leverage Partytown’s vanilla config to handle Partytown-specific behavior in your
off-main-thread scripts. One such option is
resolveUrl, which allows you to modify URLs handled by Partytown.
One example of a use case for
resolveUrl is when using tag manager scripts such as Google Tag Manager. These scripts are challenging to use with Partytown since they contain other scripts that make other requests that may or may not need to be proxied depending on the CORS setting. In this scenario you can use
resolveUrl to handle those child script URLs.
Here’s an example using Google Tag Manager to load Google Analytics (Universal Analytics in this case):
Note - This assumes you have set up Google Tag Manager to use Universal Analytics in the Google Tag Manager web application.
First you load your Google Tag Manager (GTM) script and send an initialization event:
Then you define
resolveUrl in Partytown’s vanilla config to handle the Google Analytics script loaded by Google Tag Manager:
Lastly, you need to add the Google Analytics URL to
partytownProxiedURLs so that Gatsby knows the URL is safe to proxy:
At this point both your Google Tag Manager and Google Analytics scripts should load successfully in your site.
You can also leverage Partytown’s vanilla config to enable debug mode for your off-main-thread scripts:
You may need to adjust your dev tools to the verbose log level in order to see the extra logs in your console.
By leveraging Partytown, scripts that use the
off-main-thread strategy must also be aware of the limitations mentioned in the Partytown documentation. While the strategy can be powerful, it may not be the best solution for all scenarios.
In addition, there are other limitations that require upstream changes from Partytown to enable:
onErrorcallbacks are not supported. See discussion #199 in the Partytown repo.
- Scripts load only on server-side rendering (SSR) navigation (e.g. regular
<a>tag navigation), and not on client-side rendering (CSR) navigation (e.g. Gatsby
<Link>navigation). See issue #74 in the Partytown repo.
Usage in Gatsby SSR and Browser APIs
<Script> component can also be used in the following Gatsby SSR and Gatsby Browser APIs:
Note - If you use one of these APIs, it is recommended that you implement it both in Gatsby SSR and Gatsby Browser. A common pattern is to define a single function that you import and use in both files.
Here’s an example using
wrapPageElement in both Gatsby SSR and Gatsby Browser without duplicating your code:
Scripts with sources loaded with the
idle strategies have access to two callbacks:
onLoad- Called once the script has loaded
onError- Called if the script failed to load
Note - Inline scripts and scripts using the
off-main-threadstrategy do not support the
Here is an example using the callbacks:
Duplicate scripts (scripts with the same
src attributes) will execute
onError callbacks despite not being injected into the DOM.
Loading scripts dependently
Access to the
onError callbacks also enables the ability to load scripts dependently. Here’s an example showing how to load the second script after the first: