Installing the beacon

No dependencies, no cookies by default, and about 12 KB over the wire if your server compresses it.

One line on your site. It sets no cookies, reads nothing out of the page, and if the collector is unreachable the host page is completely unaffected.

<script src="https://loghound.example.com/b.js?v=1" defer></script>

Put it anywhere — <head> is earliest, before </body> works too. That is the whole installation, and it is the snippet the panel’s settings page hands you with your own URL already in it.

defer, and the collector URL looks after itself

defer never blocks rendering and starts the clocks at parse time rather than after the last image has loaded. async works too and is marginally earlier, at the cost of a non-deterministic start point. The collector URL is derived from the script’s own src, so there is no second URL to keep in sync.

01 · What it is for

The beacon is plane 3, and it does two things and refuses to do anything else:

  • It measures how long a visitor was actually there. Not “the page was open” — three separate clocks, never conflated.
  • It is the execution plane. Whether JavaScript ran at all, whether the engine matches the version the User-Agent claims, and whether a human plausibly drove the pointer. The signal codes are the full list.
Without it, plane 3 is blind

Loghound still works — it still does everything on the transport and behavioural planes — but headless automation is inferred rather than proven, and time on site falls back to the weak log-derived number every other log analyser reports. The two things this project exists to do both need the beacon.

b.jsin the visitor tabcollect.phppublic, rate limitedstaged rowslocal file, never Solrmerged out of band, every 60 secondsloghound-scoreclaims the staged rows by client key and folds them insession doc

Figure 1 — the beacon path. The collector never touches Solr. Two reasons: a Solr write per beacon would put an indexing round trip in front of every visitor on every page, several times per pageview; and the Solr credentials never enter the request path of the most exposed file in the project.

02 · Check that your server compresses it

b.js ships as commented source, because there is no build step anywhere in this project: roughly 33 KB on disk and about 12 KB over the wire once it is gzipped. Readable source that a site owner can audit before embedding it is the deliberate trade.

The shipped vhost examples set the beacon’s cache and CORS headers but deliberately do not touch compression, because on both Debian-family Apache and stock nginx it is a global setting and a per-vhost override surprises people. So confirm it rather than assume it:

curl -sI -H 'Accept-Encoding: gzip' https://loghound.example.com/b.js | grep -i content-encoding

No Content-Encoding: gzip in that output means every visitor is downloading 33 KB instead of 12 KB. Turn compression on for application/javascript in your server’s global configuration.

03 · The ?v= matters

b.js is served with max-age=604800, immutable, so the only thing that reaches a returning visitor after an upgrade is a new URL. The panel’s settings page builds the snippet with the beacon file’s own modification time in that slot, which means there is nothing to remember to bump. If you hand-write the tag instead, bump the number yourself when you upgrade.

The shipped vhosts also set Access-Control-Allow-Origin: * and Timing-Allow-Origin: * on it, because the beacon is embedded on other origins by design.

04 · Where to go from here

Loghound is open source and MIT licensed. Questions about the Opensolr half — the account, the indexes, the plan — go to opensolr.com/contact; questions about the software itself belong on GitHub.

Loghound Documentation