DocsInstalling the snippetAll pages

Installing the snippet

Add one tag to the layout that wraps every page, near the end of <body>, exactly once. Your board shows it with your key filled in.

The tag

Snippet

<script defer
  src="https://pagehum.com/pagehum.js"
  data-site="your-site-key"></script>
  • Keep defer and data-site as written. The key is public and belongs in your page source.
  • Put it in the shared layout, not on individual pages, so every page and route counts.
  • Load it once. Two copies count every pageview twice.
  • Don’t load it inside an iframe, or through a tag manager that drops data- attributes.

Where it goes in your stack

StackWhere
Next.js (App Router)in app/layout.tsx, inside <body>: import Script from "next/script" and render <Script src="https://pagehum.com/pagehum.js" data-site="your-site-key" strategy="afterInteractive" />.
Next.js (Pages Router)in pages/_app.tsx (or _document.tsx), the same <Script … strategy="afterInteractive" />.
React with Vite or Create React Appin index.html, just before </body>.
Vue / NuxtNuxt: app.head.script in nuxt.config with { src: "https://pagehum.com/pagehum.js", defer: true, "data-site": "your-site-key" }. Plain Vue: index.html.
SvelteKitin src/app.html, just before </body>.
Astroin the base layout every page uses, just before </body>.
Plain HTML or a static site generatorin the shared footer or base template, just before </body> (every page, not only the homepage).
Rails, Django, Laravel, and other server templatesin the base layout (application.html.erb, base.html, app.blade.php), just before </body>.
WordPressthe theme's footer.php just before wp_footer(), or a header-and-footer code plugin's footer section.
Shopifylayout/theme.liquid, just before </body>.
Webflow, Framer, Squarespace, Wixsite settings → custom code → footer (or "end of body"), applied site-wide.

Let an AI assistant install it

Each site’s board has a ready-to-copy prompt for Claude, ChatGPT, Cursor, or Copilot: it leads the board of a site that has heard nothing yet and sits under the snippet on live boards. It carries your key and the exact tag, says where it goes for your stack, how to mark success, what not to add, and how to check it worked.

Single-page apps

Nothing extra. The snippet counts a pageview whenever the URL changes through history.pushState or the back and forward buttons, so Next.js, React Router, Vue Router, and SvelteKit routes count on their own.

Content Security Policy

If your site sends a Content-Security-Policy header, allow PageHum in two places: script-src https://pagehum.com to load the snippet, and connect-src https://pagehum.com so it can send counts to https://pagehum.com/api/ingest.

More than one domain

A site key counts beacons from wherever the tag runs. The checked host, the address PageHum checks every five minutes for uptime, is set from the first public host that sends a beacon, and later beacons from other hosts don’t move it. Change it on the board next to the site’s name. For two separate sites, make two site keys.

Check it worked

Open the live site and visit a few pages. In your browser’s network tab, requests to /api/ingest on pagehum.com should succeed, and the console should show no message starting with “PageHum:”. The board fills in within a few minutes. The board’s Send a test beacon button fires counts from PageHum itself, if you want to see the board move before your site is live. More in Troubleshooting.