Skip to content

Conversation

petecheslock
Copy link
Collaborator

@petecheslock petecheslock commented Aug 5, 2025

Here’s how the global analytics.js client module tracks pageviews and anchors reliably across the site.
NOTE: An SPA (Single Page Application) loads once and swaps content with JavaScript, so URL changes don’t reload the page. Because there are no full reloads, analytics won’t auto-record pageviews or anchor jumps—you must send them manually. Our client module does exactly that for route changes and same-page anchors, and dedupes them so each action counts once.

1. Registration in Docusaurus config

// docusaurus.config.js
clientModules: [require.resolve('./src/clientModules/analytics.js')],
  • What this does: Loads the client module on every page, one time, across the entire SPA.

2. Client-side only

import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
// ...
if (!ExecutionEnvironment.canUseDOM) return;
  • Why it matters: SSR (Server-Side Rendering) renders pages on the server and ships HTML to the browser; there’s no window/document during SSR. Analytics must not run server-side (it would crash or send bogus hits), so it should initialize only in the browser after the DOM exists. That’s why we guard with ExecutionEnvironment.canUseDOM before starting Matomo.

3. Environment-aware site selection

  • resolveMatomoSiteId(hostname):
    • localhost / Netlify → siteId 6
    • *llm-d.ai / .llm-d.ai → siteId 7
    • unknown hosts → analytics disabled

4. One-time Matomo initialization

  • Privacy & delivery:
    • disableCookies
    • alwaysUseSendBeacon
    • enableLinkTracking
  • Tracker:
    • setTrackerUrl('//analytics.ossupstream.org/matomo.php')
    • setSiteId(siteId)
    • Loads matomo.js asynchronously

5. SPA navigation tracking (Docusaurus lifecycle)

  • Uses onRouteDidUpdate({ location, previousLocation }) to track:
    • setReferrerUrl (when available)
    • setCustomUrl (includes hash if present)
    • setDocumentTitle (anchor-enhanced title)
    • trackPageView
  • Re-attaches anchor listeners after each route change to catch late-rendered anchors.

6. Same-page anchor tracking (virtual pageviews)

  • Clicks on anchors within the same pathname:
    • Virtual pageview with pathname#hash
    • Title enhanced to Base Title - anchor
  • De-duplication:
    • Remembers last virtual pageview (URL + timestamp)
    • Skips the immediate route-update track for same-page hash changes within 1.5s
    • Prevents double counting for hash navigations

7. Title stability

  • getBaseTitle() trims a single trailing " - section" to avoid compounding titles across multiple anchor clicks.

8. Robustness

  • Gracefully no-ops if analytics is unavailable or host is unrecognized.
  • Anchor listener rebind protects against late DOM updates.
  • Malformed URLs and odd edge cases do not throw or corrupt metrics.

9. Tests (Jest + jsdom)

  • Cross-page navigation (no hash) tracks once with correct referrer.
  • Direct load to hashed URLs enhances title and tracks once.
  • Same-page anchor clicks create one virtual pageview per click.
  • Cross-page anchors are handled by route update, not the same-page handler.
  • Title does not compound over multiple anchor navigations.
  • Late-rendered anchors receive listeners after route updates.
  • Full URL anchors (absolute) resolve correctly.
  • Rapid sequential clicks on different anchors aren’t double-counted.
  • Malformed URLs and unavailable analytics do not crash or emit bad calls.

Copy link

netlify bot commented Aug 5, 2025

Deploy Preview for elaborate-kangaroo-25e1ee ready!

Name Link
🔨 Latest commit de6bcc4
🔍 Latest deploy log https://app.netlify.com/projects/elaborate-kangaroo-25e1ee/deploys/689a48685adb4f00084558ce
😎 Deploy Preview https://deploy-preview-78--elaborate-kangaroo-25e1ee.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@petecheslock petecheslock marked this pull request as draft August 6, 2025 15:12
jessicachitas and others added 4 commits August 8, 2025 11:59
- Replace page-specific Matomo component with global client module
- Analytics runs on all pages automatically via clientModules
- Restrict analytics to localhost and Netlify preview deployments only
- Use site ID 6 for all environments
- Support SPA navigation tracking for page views

Signed-off-by: Pete Cheslock <[email protected]>
- Simplified the analytics initialization process by consolidating logic into `resolveMatomoSiteId` and `ensureMatomoInitialized` functions.
- Updated site ID resolution to support different environments (localhost, Netlify, production).
- Enhanced SPA navigation tracking by ensuring page views are tracked on route updates.
- Removed unnecessary checks and streamlined the code for better readability and maintainability.

Signed-off-by: Pete Cheslock <[email protected]>
Signed-off-by: Pete Cheslock <[email protected]>
@petecheslock petecheslock marked this pull request as ready for review August 8, 2025 18:30
…ance analytics tracking

- Enhanced analytics tracking for same-page anchor clicks to improve user interaction insights.
- Updated footer social links to use a new structure with improved accessibility and styling.
- Move footer image links to existing images in repo
- Cleaned up unused code and comments in the configuration file.

Signed-off-by: Pete Cheslock <[email protected]>
- Enhanced analytics tracking for same-page anchor clicks to prevent double-counting.
- Improved the initialization of analytics and anchor tracking on page load.
- Added new dependencies for Babel and Jest to improve testing and build processes.

Signed-off-by: Pete Cheslock <[email protected]>
@petecheslock
Copy link
Collaborator Author

While i was testing this feature out, I made two other changes to clean up the footer for the social links, and added a github fork button with star count, docusaurus didn't seem to have this feature natively.

Screenshot 2025-08-11 at 3 46 46 PM Screenshot 2025-08-11 at 3 46 41 PM

@petecheslock
Copy link
Collaborator Author

This one looks a little complex, but mostly its the challenge of capturing analytics from "single page sites". Hopefully the AI assisted PR description explains why this is, and how the code works. I've confirmed on the Matomo instance that we are only capturing anonymous page views counts, and most importantly we can see links to the anchor pages which is helpful to know where on a page folks are being directed to.

Screenshot 2025-08-11 at 4 18 52 PM

@petecheslock petecheslock mentioned this pull request Aug 11, 2025
Copy link
Collaborator

@jessicachitas jessicachitas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

@jessicachitas jessicachitas merged commit fc97034 into llm-d:main Aug 13, 2025
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants