UsherStats Docs Contents usherstats.com Start free

Installing

There are three ways to install UsherStats, plus proxy mode, and they build on each other.

WayWhat you getWhat you change
SnippetHuman analytics, goals, journeys, A/B testsOne tag in your pages
First-party pathThe same, served from your own domain, so blockers aimed at third parties leave it aloneA route on your server
Worker SDKAll of the above, plus crawler and AI-bot analytics and bot protectionYour Cloudflare Worker
Proxy modeThe same as the Worker SDK, with no codeA DNS record

Your site's public key (pk_…) and server secret (sk_live_…) are on its Install page in the dashboard. The public key is public by design. Keep the server secret on your server: it is what lets UsherStats believe what your server says about its visitors.

The snippet

<script defer src="https://collect.usherstats.com/t.js" data-site="pk_…"></script>

Put it in the <head> of every page. Optional attributes:

  • data-page-type="article": a short label for the kind of page, for the dashboard's page-type views.
  • data-journeys="off": send pageviews and events only, not journeys.

If your site sends a Content Security Policy, allow https://collect.usherstats.com in script-src and connect-src.

A first-party path

Served from your own domain, the script and its reports are first-party: nothing for a blocker to drop as a third party. Your server forwards /_us/ to https://collect.usherstats.com/, and the snippet says so:

<script defer src="/_us/t.js" data-site="pk_…" data-api="/_us"></script>

Your server must tell UsherStats who the visitor is. Behind your proxy, UsherStats sees your server, not the visitor, and a server's network is a hosting network, which UsherStats counts as automated. So every forwarded request carries your server secret and the visitor's details:

HeaderValue
x-usher-proxyyour server secret, sk_live_…
x-usher-client-ipthe visitor's IP address
x-usher-client-countrythe visitor's two-letter country code
x-usher-client-asnthe visitor's network number (AS number)
x-usher-client-as-orgthe visitor's network name, such as Comcast Cable Communications, LLC

UsherStats uses these only with a valid secret for that site. If your server cannot supply the visitor's network (AS number and name), use the snippet directly instead: otherwise your readers will be counted as hosting-network traffic. On Cloudflare, the Worker SDK fills all of them for you. Elsewhere, a GeoIP database with network data (for example MaxMind's GeoLite2 ASN and Country) provides them.

Cloudflare Workers

Use the Worker SDK: it serves /_us/ and adds the snippet to your pages for you.

Next.js

Most Next.js hosts do not tell your code the visitor's network, so for Next.js the simplest correct install is the direct snippet, in your root layout:

import Script from 'next/script';

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <head>
        <Script src="https://collect.usherstats.com/t.js" data-site="pk_…" strategy="afterInteractive" />
      </head>
      <body>{children}</body>
    </html>
  );
}

If your Next.js site runs behind Cloudflare, put a Worker with the Worker SDK in front of it for a first-party path. If your host gives you the visitor's network in request headers, you can forward /_us/ with a route handler that sets the headers above, as in the Nginx example.

Nginx

With the GeoIP2 module and the GeoLite2 ASN and Country databases loaded as $geoip2_asn, $geoip2_as_org and $geoip2_country:

location /_us/ {
    proxy_pass https://collect.usherstats.com/;
    proxy_ssl_server_name on;
    proxy_set_header Host collect.usherstats.com;
    proxy_set_header Cookie "";
    proxy_set_header x-usher-proxy "sk_live_…";
    proxy_set_header x-usher-client-ip $remote_addr;
    proxy_set_header x-usher-client-country $geoip2_country;
    proxy_set_header x-usher-client-asn $geoip2_asn;
    proxy_set_header x-usher-client-as-org $geoip2_as_org;
}

If Nginx is itself behind a proxy or load balancer, use the visitor's address it forwards (for example with the realip module) rather than the load balancer's.

Caddy

With a GeoIP plugin that sets the visitor's country and network as placeholders (named here {geoip.country}, {geoip.asn} and {geoip.as_org}; use your plugin's names):

handle_path /_us/* {
    reverse_proxy https://collect.usherstats.com {
        header_up Host collect.usherstats.com
        header_up -Cookie
        header_up x-usher-proxy {env.USHERSTATS_SECRET}
        header_up x-usher-client-ip {remote_host}
        header_up x-usher-client-country {geoip.country}
        header_up x-usher-client-asn {geoip.asn}
        header_up x-usher-client-as-org {geoip.as_org}
    }
}

Both examples drop your site's cookies on the way: UsherStats needs none of them. (The one exception is the cookie that marks your own team's browsers as internal; see Concepts. The Worker SDK forwards that one alone.)

The Worker SDK

For a site served by a Cloudflare Worker, wrap your handler:

import { withUsherStats } from '@usherstats/worker';

const site = async (request) => new Response('<!doctype html><html><head><title>Home</title></head><body>Hello</body></html>', {
  headers: { 'content-type': 'text/html; charset=utf-8' },
});

export default {
  fetch: withUsherStats(site, { pageType: (path) => (path.startsWith('/blog/') ? 'article' : 'page') }),
};

Put the server secret in the Worker secret USHERSTATS_SECRET and the public key in USHERSTATS_SITE_KEY. The SDK:

  • serves the snippet and its reports from /_us/ on your hostname, with the visitor's network details, and adds the snippet to your HTML pages;
  • records every request your Worker answers, people and crawlers alike, and sends the records in batches after the response, so no page waits for UsherStats;
  • runs your site's bot protection before your code.

If UsherStats is slow or unreachable, your site is served as if it were not there. The options, and how bot protection decides, are on the Bot protection page.

Proxy mode

If your site is not on Cloudflare Workers, or you would rather not change it, point a hostname at UsherStats and it sits in front of your server, with analytics and bot protection and no code. See Proxy mode.

Checking the install

The site's Install page shows when the last pageview and the last server record arrived. Requests your server or proxy records count towards your plan's server requests; pageviews count towards its human pageviews (see Billing and plans).

View this page as Markdown