These docs are a work in progress: some pages may still be incomplete or contain inaccuracies.
fastmon Docs
Implementation

Install the tracking code

Add fastmon to your site with a single script tag. Five minutes from sign-up to first data point.

One <script> tag in your <head> is the whole setup. It works on anything you can inject a script into: static HTML, a React or Vue app, Hugo, Next.js, WordPress, a tag manager.

Time to first data: about five minutes. You'll need: access to your site's HTML and a fastmon account.

Your snippet

Opened from the app, these are filled in with your application's real values. Otherwise, paste them here and every snippet on this page updates.

Find both hashes in the app under Applications → ··· → IDs & hashes.

Applications and sites

If you opened this page from an application's Set up button, it already exists and the hashes above are filled in. Skip to step 1.

Otherwise, create one first. An application is one tracking snippet. It owns the collection settings and the two hashes below, and it can serve one domain or twenty.

In fastmon, open Applications and click Add. Give it a name and the domain you want to monitor (the bare hostname, no protocol: acme.com). Fastmon creates the application and its first site for that domain in one step, then hands you the snippet.

That gives the application two short hashes:

  • source_hash: goes into the script URL.
  • collector_hash: where the tracker posts data. It's baked into the script, so you normally never touch it by hand.

Both are on the application's card under ··· → IDs & hashes.

Running several domains off one snippet? Add them as further sites on the same application. Every site keeps its own dashboard and traffic, but they share one snippet and one set of collection settings. Only add a second application when a domain genuinely needs different settings.

1. Add the tracker tag

This one tag is the whole required setup. Drop it into the <head> of every page you want to monitor:

<script defer src="https://fastmon.site/s/{source_hash}.js"></script>

The tag uses defer: it loads in parallel with HTML parsing, never blocks the parser, and runs in source order once the DOM is parsed. async would also load without blocking, but it can interrupt parsing the moment the download finishes, and the order between multiple async scripts is whichever-finishes-first. For Web Vitals we want predictable timing, so defer wins.

(Attribute order inside the tag is irrelevant to the browser: <script defer src="…"> and <script src="…" defer> behave identically. We write defer first so it matches what the app hands you.)

Placement isn't critical, but <head> is the better spot: it lets the tracker catch the very first paint.

Where to put it

Site typePut the tag in…
Plain HTML / Hugo / Jekyll<head> of your base template.
WordPressA header-snippet plugin, or header.php.
Next.js / Nuxt / AstroThe framework's head/script primitive (Next.js: <Script strategy="afterInteractive"> in app/layout.tsx).
Single-page appsThe static index.html shell: once is enough.

2. Deploy and load a page

Push to the environment you want to monitor and open any page on the site.

The tracker registers PerformanceObserver for Web Vitals, buffers events in memory, and POSTs batched payloads over the page view's lifecycle: on load, on visibilitychange → hidden, on pagehide, and at periodic flushes. Expect a few requests per page view, not exactly one. Switching tabs or closing the page is the most reliable way to force a flush while testing.

Then check it arrived: see Verify it works.

If the domain isn't a site yet

Beacons are matched to a site by the page's hostname. If you added the domain when creating the application, you're done: data lands on that site.

If you didn't (you created an empty application, or you've just put the snippet on an additional domain), the first page view doesn't get thrown away silently: the hostname shows up on the application as a suggested domain, and you add it as a site in one click. Beacons from before you adopt it aren't kept, so the numbers start from the moment you add it.

Which of those happens is the application's Unknown domains setting:

SettingWhat happens on a beacon from an unregistered domain
Suggest (default)Listed as a suggested domain to adopt; the beacon itself is dropped.
Auto-createA site is created automatically on the first beacon.
IgnoreDropped silently: no suggestion, no site.

If your application stores a session id and the consent level is left at its default (off), the tracker does not write the session id until you tell it consent was granted. Call this from your cookie banner's accept handler, and on every page load while consent stands:

// In your cookie banner's "Accept" callback, and on every page load// while consent is granted (most consent managers do this for you):window.fastmon && window.fastmon.grantConsent && window.fastmon.grantConsent();

Without that call the tracker still measures Web Vitals and page views; it just doesn't stitch them into multi-page sessions. If your application doesn't store a session id at all, the served bundle never touches storage and there's nothing to gate.

See Privacy for what is and isn't collected.

Optional extras

Neither is needed to get data flowing. Add them once the tracker tag is in place and working.

Catch errors that fire before the tracker loads

A deferred script only starts once the DOM is parsed, so a JavaScript error thrown during early parsing happens before fastmon is listening. This tiny inline snippet queues those errors and hands them over when the tracker boots.

It only works above the tracker tag from step 1, so put it there, first thing in the <head>:

<script>  window.__fastmon = window.__fastmon || { q: [] };  (function (q) {    function h(k) {      return function (e) {        q.push([k, e, Date.now()]);      };    }    addEventListener("error", h("e"), true);    addEventListener("unhandledrejection", h("r"));  })(window.__fastmon.q);</script>

Skip it if you don't care about the first few hundred milliseconds of error coverage.

Count visitors without JavaScript

A <noscript> pixel records a page view for visitors with JavaScript disabled. It carries no Web Vitals (there's no JS to measure them), just the page view. Goes anywhere in the <head> after the tracker tag:

<noscript><img src="https://fastmon.site/c/{collector_hash}.gif" alt="" width="1" height="1" referrerpolicy="no-referrer-when-downgrade" /></noscript>

Where the beacons go

The collector setting on the application decides the host in the snippet above.

fastmon (default)

Script and beacons load from fastmon.site. Nothing to configure. It is third-party from your site's perspective, so a strict content blocker can block it.

Same-origin (relative)

Recommended, if you can put a reverse proxy in front of your site.

The snippet uses host-less paths (/s/…, /c/…), so script and beacons come from your domain. They're first-party and indistinguishable from your own resources, which means content blockers don't strip them and your visit counts stay complete. You proxy the two path prefixes to fastmon. For nginx:

location ~ ^/(s|c)/ {    proxy_pass https://fastmon.site;    proxy_set_header Host fastmon.site;    proxy_set_header X-Forwarded-For $remote_addr;}

Any reverse proxy or CDN works the same way: forward /s/ and /c/ to https://fastmon.site and preserve the client IP header.

Smoxy

If your site runs behind Smoxy, it's two steps in the dashboard, no config file.

  1. Add fastmon as an origin. Under Backends in your organization, click Origin hinzufügen and fill in: Name fastmon, Protokoll https, Adresse fastmon.site, Port 443.
  2. Route the two prefixes to it. Under Regeln, create a Conditional Rule whose condition is URI Entspricht ^/(s|c)/, then open the rule's Einstellungen tab and pick the fastmon origin under Routing.

Everything else on the zone keeps its normal origin; only /s/ and /c/ go to fastmon. Matching rules stack, so set stop only if you deliberately want to skip the rules after this one.

Custom domain

Same first-party benefit, but you point the snippet at a collector host you control (metrics.example.com) instead of relative paths. Useful when one application spans several domains and you want a single stable collector host.

What's next

On this page