Skip to content
Ready-made integrations Hotjar

Hotjar for JavaScript

Markdown
Loading…

Load Hotjar only after analytics consent, and delete its cookies when consent is withdrawn.

hotjar() loads Hotjar after the visitor grants the analytics category. Before that, nothing is loaded and nothing is stored, not even in memory. When consent is withdrawn, it deletes Hotjar's cookies, storage and widgets, and Hotjar stops on the next page load.

It loads the classic Hotjar tracking code, static.hotjar.com/c/hotjar-<siteId>.js. Hotjar accounts are moving to Contentsquare. If your account gives you a Contentsquare tag instead, this integration does not manage it.

Set it up

Install the integrations package and add hotjar() to the initCookieYes() call you already have. The site ID is the hjid value in the snippet Hotjar gives you:

npm install @cookieyes/scripts
src/consent.ts
import { initCookieYes } from "@cookieyes/core";
import { hotjar } from "@cookieyes/scripts";

initCookieYes({
  mode: "cookie-only",
  regulation: "GDPR",
  integrations: [hotjar({ siteId: 1234567, reloadOnRevoke: true })],
});
⚠

Recommended: set reloadOnRevoke: true

Hotjar has no stop command. After consent is withdrawn, it keeps recording until the page reloads. reloadOnRevoke: true reloads the page at once, so recording stops when the visitor says no.

To let the visitor choose when to reload instead, mark Hotjar as needing a reload before initCookieYes(). The SDK reads this list once, when it starts, so a line placed after it misses returning visitors:

src/consent.ts
import { initCookieYes, registerStopHandler } from "@cookieyes/core";
import { hotjar } from "@cookieyes/scripts";

registerStopHandler({ id: "hotjar", category: "analytics", needsReload: true });

const { consentManager } = initCookieYes({
  mode: "cookie-only",
  regulation: "GDPR",
  integrations: [hotjar({ siteId: 1234567 })],
});

Then show your own message while consentManager.reloadNotice.required is true.

Moving from builtInIntegrations: [{ vendor: "hotjar" }]? That showed the reload notice on withdrawal. Add the line above to keep it.

Remove the Hotjar snippet from your page. The integration adds the script itself.

Send events and user details through these functions. They do nothing before consent or after withdrawal, and never throw:

import { hotjarEvent, hotjarIdentify } from "@cookieyes/scripts";

hotjarEvent("signup");
hotjarIdentify("user_123", { plan: "pro" });

Calls made before consent are dropped, not kept for later. In development, the first dropped call logs one console message.

Options

OptionDefaultWhat it does
siteIdrequiredThe hjid value from your Hotjar snippet
reloadOnRevokefalseReload the page when consent is withdrawn, so recording stops at once
snippetVersion6The hjsv value from your Hotjar snippet
scriptUrlhttps://static.hotjar.com/c/hotjar-<siteId>.js?sv=<snippetVersion>Load Hotjar's script from another URL
category"analytics"The category the visitor must grant. Session recording is more sensitive than ordinary analytics, so consider a category of its own
id"hotjar"Only needed when you run more than one site

Good to know

  • Without reloadOnRevoke, withdrawal is not immediate. The cookies, storage and widgets go at once, but recording continues until the next page load. In a single-page app, Hotjar can also set its _hjSession_<siteId> cookie again on the next route change.
  • Accepting again on the same page continues the session in memory. No second copy is loaded. A new session starts on the next page load.
  • Tell visitors about recordings. "Analytics" sounds like page counts, but Hotjar records clicks, mouse movement and scrolling. Say so in your analytics category description.
  • Hide sensitive content. Add data-hj-suppress to any element whose text, images or video must stay out of recordings.
  • Global Privacy Control. For CCPA visitors whose browser sends it, every non-required category starts off, so Hotjar does not load until they opt in. That is the default; region.honorGpc: false turns it off. Hotjar honours Do Not Track by itself.
  • Contentsquare tag. If your Hotjar account has moved to Contentsquare, Hotjar's script can also load a Contentsquare tag. This integration does not manage that tag.

Check it works

Open your site in a private window and watch the Network tab and the cookies:

  1. Before a decision: no request to hotjar.com, and no cookie starting with _hj.
  2. Accept: Hotjar loads, and _hjSession_<siteId> and _hjSessionUser_<siteId> appear.
  3. Withdraw consent in the preferences dialog: the _hj cookies are gone. With reloadOnRevoke: true, the page reloads.
  4. After a reload: no request to hotjar.com.

Common mistakes

Hotjar loads before the visitor accepts. The Hotjar snippet is still in your page. Remove it.

hj is not defined in the console. Your code calls hj() before consent. Use hotjarEvent() and hotjarIdentify() instead.

Page views are counted twice in a single-page app. Hotjar tracks URL changes by itself. Call hotjarStateChange() only if you switched Hotjar's URL tracking to manual.

Next steps

On this page