Skip to content

Load HubSpot and Reo on demos.handsontable.com behind Cookiebot consent - #476

Merged
GreenFlux merged 2 commits into
masterfrom
feature/runner-marketing-tags
Oct 29, 2026
Merged

GreenFlux merged 2 commits into
masterfrom
feature/runner-marketing-tags

Conversation

@GreenFlux

@GreenFlux GreenFlux commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Context

DevRel posts link to demos.handsontable.com, but the runner loads no marketing tag. A visitor who arrives from a utm_campaign link leaves no pageview, no campaign attribution and no account match in HubSpot or Reo, so the campaign can't be connected to pipeline.

The authoring SPA now loads the Cookiebot banner, using the account handsontable.com uses. Once marketing consent is recorded, it loads the HubSpot tracking code and the Reo tag.

  • Where: /, /share/:id, the guide and the editor only. /d, /embed and Tier-2 previews are user code and never carry the tags.
  • Who: production host only, never under webdriver, never for a signed-in staff session.
  • How it's built: the decision is the import-free marketingGate.ts, tested in pipeline/marketing-gate.test.mjs. The DOM side is marketingTags.ts, started from main.tsx under safeInit.
  • Recorded in: ADR-0044. AGENTS.md now scopes the "no cookies" rule to the runner's own telemetry.

Errors thrown by the third-party scripts are already dropped by Sentry's cross-origin gate (isForeignUnhandled), so eventGate.ts is unchanged.

Before or after merge (admin, outside the repo):

  • Add demos.handsontable.com to the Cookiebot domain group. Until then the banner reports an unauthorised domain, no consent is recorded, and the tags stay off. It fails closed.
  • Check that HubSpot's own cookie banner isn't set to show on demos.handsontable.com.
  • Confirm that Reo accepts the subdomain.

Types of changes

  • New example
  • Update to an existing example
  • README / documentation change
  • Demo runner (runner/) change
  • CI / tooling change

How was this verified?

  • Locally: pnpm test (2765 pass), pnpm build, pnpm typecheck, the authoring build, check-compiler-chunk, check:telemetry-leak, check-test-presence.

  • Ran the production build in Chromium under the demos.handsontable.com hostname, with Cookiebot stubbed and third-party requests recorded:

    Scenario Requests
    accept (/, /share/abc) Cookiebot, js-eu1.hs-scripts.com, static.reo.dev
    decline Cookiebot only
    no answer yet Cookiebot only
    signed-in staff, accept none
    navigator.webdriver true none
  • After deploy, still to check: a clean browser through a /share/<id>?utm_campaign=DevRel link, with accept and with decline; a signed-in tab; a docs page with an /embed iframe.

Checklist

  • New/renamed example: added to runner/config/frameworks.json (see CONTRIBUTING.md); otherwise it won't appear on demos.handsontable.com
  • New example: added a row to the tables in README.md
  • Ran pnpm build (and pnpm dev) in the affected example/server-example locally

Related issue(s):

  1. ClickUp: Add consent-gated HubSpot + Reo tags to demos.handsontable.com (https://app.clickup.com/t/123kvxeg21x)

🤖 Generated with Claude Code


Note

Medium Risk
Introduces third-party marketing scripts and cross-subdomain cookies on production for signed-out visitors; mitigated by consent gating, narrow surface, and automated gate tests, but requires correct Cookiebot domain configuration to fail closed.

Overview
Adds ADR-0044 and wires the authoring SPA to load Cookiebot, then HubSpot and Reo only after Cookiebot.consent.marketing is true—so DevRel traffic on demos.handsontable.com can be attributed without touching the runner’s anonymous telemetry.

Scope: Tags run only on SPA routes (/, /share/:id, guide, editor) via initMarketingTags in main.tsx (same safeInit pattern as telemetry). /d, /embed, and Tier-2 previews stay tag-free. marketingGate.ts mirrors reportingGate: strict production hostname, no navigator.webdriver, no staff session (sync token / #token=). Consent changes use consentAction so revoking marketing (including via CookiebotOnAccept when only marketing is unticked) clears cookies, notifies HubSpot, and reloads. pipeline/marketing-gate.test.mjs locks the gate; AGENTS.md notes marketing as the exception to the “no cookies” rule for runner telemetry.

Reviewed by Cursor Bugbot for commit 4a97564. Bugbot is set up for automated code reviews on this repo. Configure here.

Links from DevRel posts land on demos.handsontable.com, but the runner loaded
no marketing tag, so a visit from a campaign link left no pageview, campaign
attribution or account match in HubSpot or Reo.

The authoring SPA now loads the Cookiebot banner (the account handsontable.com
uses) and, only once marketing consent is recorded, the HubSpot tracking code
and the Reo tag. The decision lives in the import-free marketingGate.ts:
production host only, never under webdriver, never for a signed-in staff
session. /d, /embed and Tier-2 previews are user code and never carry the
tags. ADR-0044 records the decision; AGENTS.md scopes the "no cookies" rule to
the runner's own telemetry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@GreenFlux
GreenFlux requested a review from demtario October 29, 2026 09:45
Comment thread runner/apps/authoring/src/marketingTags.ts Outdated
Unticking only marketing in the Cookiebot banner fires CookiebotOnAccept,
not CookiebotOnDecline, so the loader never revoked anything, and on a full
decline only HubSpot was told while Reo kept running.

Every Cookiebot event now re-reads the consent and compares it with what is
loaded (consentAction, tested). A withdrawal clears both tags' cookies,
tells HubSpot, and reloads the page without the scripts: Reo has no stop
call. Only signed-out pages carry the tags, and their edits are never
persisted, so the reload loses nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@GreenFlux
GreenFlux requested a review from demtario October 29, 2026 10:09
@GreenFlux
GreenFlux merged commit 04c6ec3 into master Oct 29, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants