Usage
Once a Site ID is configured there is nothing you have to do — every front-end page carries the tracking code. Everything below is for when you want more than that.
Twig
Everything here is safe to call on a page that is not being tracked. snippet returns an empty
string, event() returns an empty string, enabled returns false. A template never has to ask
whether Jarhead is running before it can use Jarhead.
{# Place the tracking code yourself. This stands automatic injection down for
the page, so you can leave the setting on. #}
{{ craft.jarhead.snippet }}
{# Is this page tracked, and if not, why not? #}
{{ craft.jarhead.enabled }}
{{ craft.jarhead.explain.reason }} {# 'preview', 'uri-excluded', 'environment', … #}
{{ craft.jarhead.explain.message }} {# a sentence you can put in a staging footer #}
{# The Hotjar Site ID in play, or null #}
{{ craft.jarhead.siteId }}
{# The attributes this page sends #}
{{ craft.jarhead.attributes|json_encode }}
explain is worth knowing about. Dropping this into a footer during a staging pass answers "why
is there no recording of this page" faster than any log will:
{% if currentUser and currentUser.admin %}
<p>Hotjar: {{ craft.jarhead.explain.message }}</p>
{% endif %}
Events and attributes from a template
{{ craft.jarhead.event('Newsletter signup') }}
{{ craft.jarhead.identify(null, { plan: 'pro', trial: 'no' }) }}
{{ craft.jarhead.tag(['checkout', 'guest']) }}
Each writes a small <script> that calls the browser API. Calls made while a consent gate is
still shut are queued, not lost — an event written into a template is earlier than the
visitor's decision by definition.
The raw snippet
{{ craft.jarhead.trackingCode() }}
Hotjar's tracking code as Hotjar publishes it, for pasting into a tag manager or comparing against what Hotjar's own installer writes. Note what it is not: no consent gate, no exclusions, no attributes. If you are using this you are opting out of everything else on the settings screen.
JavaScript
window.jarhead.consent(); // grant consent (the only way in under `manual`)
window.jarhead.event('Added to cart');
window.jarhead.identify('user-123', { plan: 'pro' });
window.jarhead.tag(['checkout']);
window.jarhead.stateChange('/checkout/step-2'); // a route change Jarhead did not see
window.jarhead.ready(function () { /* Hotjar is loaded */ });
window.jarhead.status(); // why it has or has not booted
status() is the first thing to type into a console when a page is not recording:
{ booted: false, blockedBy: 'gpc', consentMode: 'cookie', hotjarSiteId: 1234567, queued: 2 }
blockedBy is null, 'dnt', 'gpc', 'automated' or 'consent-timeout'.
Wiring up a consent banner
// Your banner's "accept" handler
acceptButton.addEventListener('click', function () {
window.jarhead.consent(); // consentMode: 'manual'
});
Or with a cookie-based consent manager, set consentMode to cookie and let Jarhead watch for
the cookie — no code at all.
Single-page apps
Turn on spaSupport and Jarhead calls hj('stateChange', …) when history.pushState,
history.replaceState or the back button changes the path. Without it Hotjar sees one long page
view, and every heatmap after the first route change lands on the wrong page.
The same path twice is reported once. For a route change Jarhead cannot see — a hash router, say — call it yourself:
window.jarhead.stateChange('/checkout/step-2');
The Hotjar utility
Utilities → Hotjar in the control panel.
Sites. Every Craft site, its resolved Site ID, whether that came from an environment variable, and the verdict for its homepage right now.
Verify. Asks Hotjar's CDN for the tracking script belonging to your Site ID. This is the only
outbound request Jarhead ever makes, it happens only when you press the button, and it goes to
static.hotjar.com and nowhere else.
It reads the response body, not the status code — Hotjar answers 200 application/javascript
for every numeric ID ever asked for, and an ID that does not exist gets 200 with an empty body. It
also reports the two things that actually explain an empty Hotjar account:
- recording switched off for the site in your Hotjar settings
- sampling below 100%
Neither is an installation problem, and both look exactly like one.
Why is it not on that page? Type a URI, optionally a user ID and a preview flag, and get back the first rule that applied — through the same code path a real request takes.
Content Security Policy. The directives Hotjar needs, ready to copy.
Console
php craft jarhead/status # what each site would do right now
php craft jarhead/status --strict # non-zero exit if a site is not sending — for CI
php craft jarhead/verify # ask Hotjar whether the Site IDs exist
php craft jarhead/explain checkout/cart # why that URI would or would not be tracked
php craft jarhead/explain blog --user=14 # …as a specific user
php craft jarhead/snippet --site=default # the raw tracking code
jarhead/status --strict in a post-deploy step is the useful one. It tells you the tracking code
is live on production before a stakeholder tells you it is not.