Simple Analytics Plugin
Want to integrate Simple Analytics into your Docusaurus site and effectively track user navigation in a Single Page Application (SPA) context?
This guide explains how to create a local plugin for Docusaurus that handles the injection of the tracking script and tracks page changes.
It manages the injection of the main script as well as tracking page changes in the context of a Single Page Application (SPA), which is essential for Docusaurus.
This plugin is a local plugin. There's no need to install it via npm or yarn. Simply ensure that the simpleAnalytics
folder is located in the plugins
directory at the root of your project.
Plugin Structure
The plugin separates logic into two distinct files, as they run in different environments and at different times.
File Tree
plugins/
└── simpleAnalytics/
├── index.js # Main Docusaurus plugin file
└── sa-client.js # Client module for SPA navigation tracking
simpleAnalytics/index.js (Server Side / Build)
This file is the core of the plugin and runs in a Node.js environment during development server startup or site compilation.
function simpleAnalyticsPlugin(context, options) {
return {
name: "docusaurus-plugin-simple-analytics",
injectHtmlTags() {
return {
headTags: [
{
tagName: 'script',
attributes: {
src: 'https://scripts.simpleanalyticscdn.com/latest.js',
async: true,
'data-hostname': 'docuxlab.com', // Configuration for localhost
},
},
{
tagName: 'noscript',
innerHTML: '<img src="https://queue.simpleanalyticscdn.com/noscript.gif" alt="" referrerpolicy="no-referrer-when-downgrade" style="position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none;" />',
},
],
};
},
};
}
module.exports = simpleAnalyticsPlugin;
Its role is to integrate into the Docusaurus build process:
-
injectHtmlTags()
: This function injects the main Simple Analytics script and the<noscript>
tag directly into the final HTML file. This is what allows tracking the first visit of a user to the site. -
getClientModules()
: This function tells Docusaurus that it should include another JavaScript file,sa-client.js
, in the code that will be sent and executed by the user's browser.
In summary, index.js
handles the initial and static configuration.
sa-client.js (Client Side / Browser)
This file executes only in the user's browser. Its existence is crucial because Docusaurus functions as a Single Page Application (SPA).
export function loadSimpleAnalytics() {
if (typeof window === "undefined") return;
if (document.querySelector("script[src*='simpleanalyticscdn.com']")) return;
const script = document.createElement("script");
script.src = "https://scripts.simpleanalyticscdn.com/latest.js";
script.async = true;
document.body.appendChild(script);
const noscript = document.createElement("noscript");
noscript.innerHTML =
'<img src="https://queue.simpleanalyticscdn.com/noscript.gif" alt="" referrerpolicy="no-referrer-when-downgrade" />';
document.body.appendChild(noscript);
return () => {
script.remove();
noscript.remove();
};
}
// Auto-execution of the script
if (typeof window !== "undefined") {
// Wait for the DOM to be ready
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", loadSimpleAnalytics);
} else {
loadSimpleAnalytics();
}
}
Its role is to manage navigation tracking after the initial page load:
-
Listening to route changes: In an SPA, changing pages doesn't fully reload the HTML. This script therefore listens to Docusaurus internal navigation events.
-
Triggering page views: When a user navigates to a new page (for example, from
/home
to/blog/my-article
), this script calls the Simple Analytics tracking function (e.g.,window.sa_pageview()
) to manually signal that a new "page view" has occurred.
Without
sa-client.js
, only the first site access would be counted, and all subsequent navigations within the site would be ignored by Simple Analytics.
Why two different tracking lines?
In the Simple Analytics plugin code, these two lines serve different but complementary purposes for tracking:
The main script
https://scripts.simpleanalyticscdn.com/latest.js
This URL loads the main Simple Analytics JavaScript script which:
- Collects navigation data (pages visited, time spent, etc.)
- Manages user events (clicks, scrolling, etc.)
- Sends data to the Simple Analytics server
- Only works if JavaScript is enabled in the browser
The fallback image
<img src="https://queue.simpleanalyticscdn.com/noscript.gif" alt="" referrerpolicy="no-referrer-when-downgrade" />
This GIF image (1x1 pixel, invisible) serves as a fallback solution when:
- JavaScript is disabled in the browser
- The main script cannot load (ad blocker, network issue)
- Very old browsers that don't support modern JavaScript
Why two different domains?
Simple Analytics uses a distributed architecture:
https://scripts.simpleanalyticscdn.com/latest.js
: CDN optimized for serving JavaScript files
https://queue.simpleanalyticscdn.com/noscript.gif
: Specialized server for receiving tracking data
This separation allows:
- Better performance (CDN optimized for each content type)
- Redundancy (if one server goes down, the other can continue)
- Blocker bypass (some block scripts but not images)
- The
<noscript>
tag ensures that at least a basic visit is recorded, even in the most restrictive environments.
Alternative: Why not modify the Layout
component?
Another method for tracking navigation in a Single Page Application (SPA) like Docusaurus is to customize (swizzle) the Layout
component and insert a React useEffect
that listens to URL changes.
However, this approach has drawbacks:
- Tight coupling: It mixes analytics tracking logic with your theme's presentation logic.
- Less robustness: Any major modification to your theme or the
Layout
component could break tracking.
This plugin's approach, using getClientModules
, is the method recommended by Docusaurus. It's cleaner and more robust because it completely decouples the tracking functionality from the theme and React components. Your tracking continues to work even if you radically change your site's appearance.
Configuration
To activate the plugin, add its path to the plugins
array in your docusaurus.config.js
file.
import simpleAnalytics from "./plugins/simpleAnalytics/index.js"
// ...existing code...
const config = {
// ...
plugins: [
// ... other plugins
[simpleAnalytics, {}],
],
// ...
};
// ...existing code...
You can go further by adding different options such as a notrack option to avoid tracking certain pages. And surely much more, however I wanted to keep it simple for this example.
Useful Resources
This article is part of the SEO & Performance series:
- Simple Analytics Plugin
No related posts.