@c15t/scripts 2.1.0 → 2.2.0-canary-20260804162155
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +62 -0
- package/README.md +32 -20
- package/dist/e2e-test-utils.cjs +51 -10
- package/dist/e2e-test-utils.js +37 -3
- package/dist/engine/compile.cjs +9 -5
- package/dist/engine/runtime.cjs +103 -17
- package/dist/engine/runtime.js +94 -12
- package/dist/registry.cjs +97 -12
- package/dist/registry.js +80 -0
- package/dist/resolve.cjs +9 -5
- package/dist/types.cjs +17 -13
- package/dist/vendors/_shared/attributes.cjs +13 -9
- package/dist/vendors/_shared/google-consent.cjs +14 -9
- package/dist/vendors/_shared/install-builders.cjs +12 -8
- package/dist/vendors/_shared/script-url.cjs +16 -12
- package/dist/vendors/ads-and-pixels/linkedin-insights.cjs +9 -5
- package/dist/vendors/ads-and-pixels/meta-pixel.cjs +13 -9
- package/dist/vendors/ads-and-pixels/microsoft-uet.cjs +11 -7
- package/dist/vendors/ads-and-pixels/reddit-pixel.cjs +9 -5
- package/dist/vendors/ads-and-pixels/snapchat-pixel.cjs +11 -7
- package/dist/vendors/ads-and-pixels/tiktok-pixel.cjs +9 -5
- package/dist/vendors/ads-and-pixels/x-pixel.cjs +9 -5
- package/dist/vendors/analytics/adobe-analytics.cjs +90 -0
- package/dist/vendors/analytics/adobe-analytics.js +49 -0
- package/dist/vendors/analytics/ahrefs-analytics.cjs +11 -7
- package/dist/vendors/analytics/amplitude.cjs +193 -0
- package/dist/vendors/analytics/amplitude.js +134 -0
- package/dist/vendors/analytics/clearbit.cjs +69 -0
- package/dist/vendors/analytics/clearbit.js +28 -0
- package/dist/vendors/analytics/cloudflare-web-analytics.cjs +11 -7
- package/dist/vendors/analytics/databuddy.cjs +11 -7
- package/dist/vendors/analytics/fathom-analytics.cjs +11 -7
- package/dist/vendors/analytics/google-tag.cjs +11 -7
- package/dist/vendors/analytics/heap.cjs +181 -0
- package/dist/vendors/analytics/heap.js +134 -0
- package/dist/vendors/analytics/hightouch.cjs +153 -0
- package/dist/vendors/analytics/hightouch.js +109 -0
- package/dist/vendors/analytics/hotjar.cjs +11 -7
- package/dist/vendors/analytics/logrocket.cjs +99 -0
- package/dist/vendors/analytics/logrocket.js +58 -0
- package/dist/vendors/analytics/matomo-analytics.cjs +9 -5
- package/dist/vendors/analytics/microsoft-clarity.cjs +75 -47
- package/dist/vendors/analytics/microsoft-clarity.js +64 -40
- package/dist/vendors/analytics/mixpanel-analytics.cjs +31 -16
- package/dist/vendors/analytics/mixpanel-analytics.js +22 -11
- package/dist/vendors/analytics/pirsch.cjs +108 -0
- package/dist/vendors/analytics/pirsch.js +67 -0
- package/dist/vendors/analytics/plausible-analytics.cjs +9 -5
- package/dist/vendors/analytics/posthog.cjs +63 -27
- package/dist/vendors/analytics/posthog.js +52 -20
- package/dist/vendors/analytics/promptwatch.cjs +11 -7
- package/dist/vendors/analytics/rudderstack.cjs +227 -0
- package/dist/vendors/analytics/rudderstack.js +183 -0
- package/dist/vendors/analytics/rybbit-analytics.cjs +9 -5
- package/dist/vendors/analytics/segment.cjs +9 -5
- package/dist/vendors/analytics/umami-analytics.cjs +9 -5
- package/dist/vendors/analytics/vercel-analytics.cjs +11 -7
- package/dist/vendors/functional/crisp.cjs +9 -5
- package/dist/vendors/functional/intercom.cjs +11 -7
- package/dist/vendors/tag-managers/google-tag-manager.cjs +11 -7
- package/dist-types/registry.d.ts +313 -241
- package/dist-types/types.d.ts +46 -4
- package/dist-types/vendors/ads-and-pixels/linkedin-insights.d.ts +18 -18
- package/dist-types/vendors/ads-and-pixels/meta-pixel.d.ts +21 -21
- package/dist-types/vendors/ads-and-pixels/microsoft-uet.d.ts +32 -32
- package/dist-types/vendors/ads-and-pixels/reddit-pixel.d.ts +19 -19
- package/dist-types/vendors/ads-and-pixels/snapchat-pixel.d.ts +16 -16
- package/dist-types/vendors/ads-and-pixels/tiktok-pixel.d.ts +28 -28
- package/dist-types/vendors/ads-and-pixels/x-pixel.d.ts +13 -13
- package/dist-types/vendors/analytics/adobe-analytics.d.ts +75 -0
- package/dist-types/vendors/analytics/ahrefs-analytics.d.ts +7 -7
- package/dist-types/vendors/analytics/amplitude.d.ts +234 -0
- package/dist-types/vendors/analytics/clearbit.d.ts +60 -0
- package/dist-types/vendors/analytics/cloudflare-web-analytics.d.ts +7 -7
- package/dist-types/vendors/analytics/databuddy.d.ts +25 -25
- package/dist-types/vendors/analytics/fathom-analytics.d.ts +11 -11
- package/dist-types/vendors/analytics/google-tag.d.ts +17 -17
- package/dist-types/vendors/analytics/heap.d.ts +316 -0
- package/dist-types/vendors/analytics/hightouch.d.ts +285 -0
- package/dist-types/vendors/analytics/hotjar.d.ts +14 -14
- package/dist-types/vendors/analytics/logrocket.d.ts +101 -0
- package/dist-types/vendors/analytics/microsoft-clarity.d.ts +42 -30
- package/dist-types/vendors/analytics/mixpanel-analytics.d.ts +40 -28
- package/dist-types/vendors/analytics/pirsch.d.ts +96 -0
- package/dist-types/vendors/analytics/plausible-analytics.d.ts +13 -13
- package/dist-types/vendors/analytics/posthog.d.ts +63 -45
- package/dist-types/vendors/analytics/promptwatch.d.ts +7 -7
- package/dist-types/vendors/analytics/rudderstack.d.ts +330 -0
- package/dist-types/vendors/analytics/rybbit-analytics.d.ts +18 -18
- package/dist-types/vendors/analytics/segment.d.ts +13 -13
- package/dist-types/vendors/analytics/umami-analytics.d.ts +12 -12
- package/dist-types/vendors/analytics/vercel-analytics.d.ts +16 -16
- package/dist-types/vendors/functional/crisp.d.ts +11 -11
- package/dist-types/vendors/functional/intercom.d.ts +16 -16
- package/dist-types/vendors/tag-managers/google-tag-manager.d.ts +18 -18
- package/docs/README.md +62 -0
- package/docs/frameworks/javascript/script-loader.md +356 -0
- package/docs/frameworks/next/script-loader.md +501 -0
- package/docs/frameworks/react/script-loader.md +555 -0
- package/docs/integrations/adobe-analytics.md +160 -0
- package/docs/integrations/ahrefs-analytics.md +157 -0
- package/docs/integrations/amplitude.md +230 -0
- package/docs/integrations/building-integrations.md +239 -0
- package/docs/integrations/clearbit.md +130 -0
- package/docs/integrations/cloudflare-web-analytics.md +126 -0
- package/docs/integrations/crisp.md +140 -0
- package/docs/integrations/databuddy.md +205 -0
- package/docs/integrations/fathom-analytics.md +150 -0
- package/docs/integrations/google-maps.md +263 -0
- package/docs/integrations/google-tag-manager.md +154 -0
- package/docs/integrations/google-tag.md +134 -0
- package/docs/integrations/heap.md +219 -0
- package/docs/integrations/hightouch.md +199 -0
- package/docs/integrations/hotjar.md +143 -0
- package/docs/integrations/intercom.md +144 -0
- package/docs/integrations/linkedin-insights.md +161 -0
- package/docs/integrations/logrocket.md +175 -0
- package/docs/integrations/matomo-analytics.md +171 -0
- package/docs/integrations/meta-pixel.md +412 -0
- package/docs/integrations/microsoft-clarity.md +173 -0
- package/docs/integrations/microsoft-uet.md +156 -0
- package/docs/integrations/mixpanel-analytics.md +130 -0
- package/docs/integrations/overview.md +149 -0
- package/docs/integrations/pirsch.md +142 -0
- package/docs/integrations/plausible-analytics.md +154 -0
- package/docs/integrations/posthog.md +258 -0
- package/docs/integrations/promptwatch.md +121 -0
- package/docs/integrations/reddit-pixel.md +241 -0
- package/docs/integrations/rudderstack.md +271 -0
- package/docs/integrations/rybbit-analytics.md +143 -0
- package/docs/integrations/segment.md +146 -0
- package/docs/integrations/snapchat-pixel.md +163 -0
- package/docs/integrations/tiktok-pixel.md +123 -0
- package/docs/integrations/umami-analytics.md +148 -0
- package/docs/integrations/vercel-analytics.md +141 -0
- package/docs/integrations/x-pixel.md +157 -0
- package/docs/integrations/youtube.md +193 -0
- package/docs/shared/react/guides/script-loader.md +311 -0
- package/package.json +61 -7
- package/readme.json +8 -4
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Google Tag Manager
|
|
3
|
+
description: Deploy and manage marketing tags centrally with automatic consent
|
|
4
|
+
state synchronization.
|
|
5
|
+
icon: google-tag-manager
|
|
6
|
+
group: integrations
|
|
7
|
+
---
|
|
8
|
+
Google Tag Manager (GTM) is Google's tag management system that lets you deploy and manage marketing tags, analytics scripts, and conversion pixels without modifying your codebase. Instead of hardcoding multiple scripts, you configure them through GTM's web interface.
|
|
9
|
+
|
|
10
|
+
c15t automatically injects the GTM script into your page and syncs consent state with GTM using Consent Mode v2. GTM manages its own internal consent state and only fires tags when appropriate consent is granted, which means it can safely load before consent is collected.
|
|
11
|
+
|
|
12
|
+
This prevents GTM-managed scripts from loading without proper consent while giving you centralized control over your marketing stack.
|
|
13
|
+
|
|
14
|
+
> ℹ️ **Info:**
|
|
15
|
+
> Use GTM if your team manages many tags centrally in the GTM UI. Use gtag.js if you only need GA4/Google Ads directly in code. Don't run both for the same destination unless intentional, or you may duplicate events.
|
|
16
|
+
|
|
17
|
+
## Integrate with c15t
|
|
18
|
+
|
|
19
|
+
Use your GTM container ID, which begins with `GTM-`.
|
|
20
|
+
|
|
21
|
+
**React**
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
import { type ReactNode } from 'react';
|
|
25
|
+
import { ConsentManagerProvider } from '@c15t/react';
|
|
26
|
+
import { googleTagManager } from '@c15t/scripts/google-tag-manager';
|
|
27
|
+
|
|
28
|
+
const scripts = [googleTagManager({ id: 'GTM-XXXXXXX' })];
|
|
29
|
+
|
|
30
|
+
export function ConsentProvider({ children }: { children: ReactNode }) {
|
|
31
|
+
return (
|
|
32
|
+
<ConsentManagerProvider
|
|
33
|
+
options={{
|
|
34
|
+
mode: 'hosted',
|
|
35
|
+
backendURL: 'https://your-instance.c15t.dev',
|
|
36
|
+
scripts,
|
|
37
|
+
}}
|
|
38
|
+
>
|
|
39
|
+
{children}
|
|
40
|
+
</ConsentManagerProvider>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Next.js**
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
'use client';
|
|
49
|
+
|
|
50
|
+
import { type ReactNode } from 'react';
|
|
51
|
+
import { ConsentManagerProvider } from '@c15t/nextjs';
|
|
52
|
+
import { googleTagManager } from '@c15t/scripts/google-tag-manager';
|
|
53
|
+
|
|
54
|
+
const scripts = [googleTagManager({ id: 'GTM-XXXXXXX' })];
|
|
55
|
+
|
|
56
|
+
export function ConsentProvider({ children }: { children: ReactNode }) {
|
|
57
|
+
return (
|
|
58
|
+
<ConsentManagerProvider
|
|
59
|
+
options={{
|
|
60
|
+
mode: 'hosted',
|
|
61
|
+
backendURL: '/api/c15t',
|
|
62
|
+
scripts,
|
|
63
|
+
}}
|
|
64
|
+
>
|
|
65
|
+
{children}
|
|
66
|
+
</ConsentManagerProvider>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**JavaScript**
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
import { getOrCreateConsentRuntime } from 'c15t';
|
|
75
|
+
import { googleTagManager } from '@c15t/scripts/google-tag-manager';
|
|
76
|
+
|
|
77
|
+
getOrCreateConsentRuntime({
|
|
78
|
+
mode: 'hosted',
|
|
79
|
+
backendURL: 'https://your-instance.c15t.dev',
|
|
80
|
+
scripts: [googleTagManager({ id: 'GTM-XXXXXXX' })],
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## How c15t loads it
|
|
85
|
+
|
|
86
|
+
* **Category:** `necessary` (Tag Managers)
|
|
87
|
+
* **Loads when:** [`alwaysLoad`](/docs/frameworks/react/script-loader#always-load) — runs on page start with Consent Mode v2 defaults set to denied
|
|
88
|
+
* **On consent change:** c15t pushes a Consent Mode v2 `update` to the data layer; GTM-managed tags re-evaluate against the new state
|
|
89
|
+
|
|
90
|
+
## Configure the integration
|
|
91
|
+
|
|
92
|
+
1. **Creating a Tag Manager Container**
|
|
93
|
+
|
|
94
|
+
> 📝 Note:
|
|
95
|
+
> This step is optional if you already have a Tag Manager container. Ensure your container has consent overview enabled.
|
|
96
|
+
|
|
97
|
+
After signing into Google Tag Manager, you can create a new container.
|
|
98
|
+
Continue to Google Tag Manager
|
|
99
|
+
|
|
100
|
+
1. In Tag Manager, click Admin > Container Settings.
|
|
101
|
+
2. Under Additional Settings, select "Enable consent overview".
|
|
102
|
+
|
|
103
|
+
Enable consent overview
|
|
104
|
+
|
|
105
|
+
2. **Custom Update Trigger** We now need to create a custom trigger in GTM to trigger the update event, this is the trigger that is fired when the consent state is updated, e.g. user gives consent to a specific purpose.
|
|
106
|
+
|
|
107
|
+
In GTM, you can create a new trigger by clicking on the "Triggers" tab and then clicking on "New".
|
|
108
|
+
|
|
109
|
+
For the event name, you can use the default "consent-update", this is customizable later so you can change it if you want.
|
|
110
|
+
|
|
111
|
+
Create trigger
|
|
112
|
+
|
|
113
|
+
3. **Update tags** Now for your existing tags, you can add the "consent-update" trigger to the tag, this will fire the update event when the consent state is updated & it has the appropriate consent state.
|
|
114
|
+
|
|
115
|
+
Update tags
|
|
116
|
+
|
|
117
|
+
## Tracking events in your app
|
|
118
|
+
|
|
119
|
+
GTM is `alwaysLoad: true`, so the GTM container and `window.dataLayer` are present from page start regardless of consent. Calls like `dataLayer.push({ event: 'signup' })` are **safe at any time** — Consent Mode v2 defaults are set to denied before the user makes a choice, and GTM-managed tags only fire when the matching consent has been granted.
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
window.dataLayer = window.dataLayer || [];
|
|
123
|
+
window.dataLayer.push({ event: 'signup' });
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
You do not need to wrap `dataLayer.push(...)` in a `useConsentManager().has(...)` check — the consent gate happens inside GTM, not inside c15t.
|
|
127
|
+
|
|
128
|
+
## Verify setup
|
|
129
|
+
|
|
130
|
+
1. Open GTM Preview mode and confirm your container (`GTM-...`) loads on page load.
|
|
131
|
+
2. Before giving consent, confirm non-essential tags do not fire in GTM Preview.
|
|
132
|
+
3. Accept consent in the c15t banner/dialog and confirm a `consent-update` event appears in the GTM event timeline.
|
|
133
|
+
4. Confirm measurement/marketing tags fire only after the matching consent is granted.
|
|
134
|
+
5. Revoke consent and confirm a new `consent-update` event appears and affected tags stop firing.
|
|
135
|
+
|
|
136
|
+
## Types
|
|
137
|
+
|
|
138
|
+
### GoogleTagManagerOptions
|
|
139
|
+
|
|
140
|
+
|Property|Value|
|
|
141
|
+
|:--|:--|
|
|
142
|
+
|Type Name|\`GoogleTagManagerOptions\`|
|
|
143
|
+
|Source Path|\`./packages/scripts/src/vendors/tag-managers/google-tag-manager.ts\`|
|
|
144
|
+
|
|
145
|
+
\*ExtractedTypeTable: Could not extract "GoogleTagManagerOptions" from "./packages/scripts/src/vendors/tag-managers/google-tag-manager.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
146
|
+
|
|
147
|
+
### Script
|
|
148
|
+
|
|
149
|
+
|Property|Value|
|
|
150
|
+
|:--|:--|
|
|
151
|
+
|Type Name|\`Script\`|
|
|
152
|
+
|Source Path|\`./packages/core/src/libs/script-loader/types.ts\`|
|
|
153
|
+
|
|
154
|
+
\*ExtractedTypeTable: Could not extract "Script" from "./packages/core/src/libs/script-loader/types.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: GA4 + Google Ads (gtag.js)
|
|
3
|
+
description: Send data to Google Analytics 4 and Google Ads with automatic
|
|
4
|
+
Consent Mode v2 support.
|
|
5
|
+
icon: google-analytics
|
|
6
|
+
group: integrations
|
|
7
|
+
---
|
|
8
|
+
Google Tag (`gtag.js`) is Google's unified tracking script for sending data to Google Analytics 4 (GA4), Google Ads, and Floodlight. It measures user behavior, tracks conversions, and powers Google's advertising ecosystem.
|
|
9
|
+
|
|
10
|
+
c15t initializes Google Tag with Consent Mode v2 defaults set to denied and automatically updates the consent state when users make choices. You don't need to configure Google Consent Mode yourself.
|
|
11
|
+
|
|
12
|
+
> ℹ️ **Info:**
|
|
13
|
+
> Use GTM if your team needs centralized tag management in the GTM UI. Use gtag.js if you only need GA4/Google Ads directly in code. Don't run both for the same destination unless intentional, or you may duplicate events.
|
|
14
|
+
|
|
15
|
+
**Choosing the right category:**
|
|
16
|
+
|
|
17
|
+
* Use `category: 'measurement'` for analytics-only tracking (GA4 events)
|
|
18
|
+
* Use `category: 'marketing'` for advertising and conversion tracking (Google Ads)
|
|
19
|
+
|
|
20
|
+
## Integrate with c15t
|
|
21
|
+
|
|
22
|
+
**React**
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
import { type ReactNode } from 'react';
|
|
26
|
+
import { ConsentManagerProvider } from '@c15t/react';
|
|
27
|
+
import { gtag } from '@c15t/scripts/google-tag';
|
|
28
|
+
|
|
29
|
+
const scripts = [
|
|
30
|
+
gtag({
|
|
31
|
+
id: 'G-XXXXXXXXXX',
|
|
32
|
+
category: 'measurement', // or 'marketing'
|
|
33
|
+
}),
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
export function ConsentProvider({ children }: { children: ReactNode }) {
|
|
37
|
+
return (
|
|
38
|
+
<ConsentManagerProvider
|
|
39
|
+
options={{
|
|
40
|
+
mode: 'hosted',
|
|
41
|
+
backendURL: 'https://your-instance.c15t.dev',
|
|
42
|
+
scripts,
|
|
43
|
+
}}
|
|
44
|
+
>
|
|
45
|
+
{children}
|
|
46
|
+
</ConsentManagerProvider>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Next.js**
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
'use client';
|
|
55
|
+
|
|
56
|
+
import { type ReactNode } from 'react';
|
|
57
|
+
import { ConsentManagerProvider } from '@c15t/nextjs';
|
|
58
|
+
import { gtag } from '@c15t/scripts/google-tag';
|
|
59
|
+
|
|
60
|
+
const scripts = [
|
|
61
|
+
gtag({
|
|
62
|
+
id: 'G-XXXXXXXXXX',
|
|
63
|
+
category: 'measurement', // or 'marketing'
|
|
64
|
+
}),
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
export function ConsentProvider({ children }: { children: ReactNode }) {
|
|
68
|
+
return (
|
|
69
|
+
<ConsentManagerProvider
|
|
70
|
+
options={{
|
|
71
|
+
mode: 'hosted',
|
|
72
|
+
backendURL: '/api/c15t',
|
|
73
|
+
scripts,
|
|
74
|
+
}}
|
|
75
|
+
>
|
|
76
|
+
{children}
|
|
77
|
+
</ConsentManagerProvider>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**JavaScript**
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
import { getOrCreateConsentRuntime } from 'c15t';
|
|
86
|
+
import { gtag } from '@c15t/scripts/google-tag';
|
|
87
|
+
|
|
88
|
+
getOrCreateConsentRuntime({
|
|
89
|
+
mode: 'hosted',
|
|
90
|
+
backendURL: 'https://your-instance.c15t.dev',
|
|
91
|
+
scripts: [
|
|
92
|
+
gtag({
|
|
93
|
+
id: 'G-XXXXXXXXXX',
|
|
94
|
+
category: 'measurement', // or 'marketing'
|
|
95
|
+
}),
|
|
96
|
+
],
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## How c15t loads it
|
|
101
|
+
|
|
102
|
+
* **Category:** configurable — `measurement` (default, Analytics) or `marketing`
|
|
103
|
+
* **Loads when:** [`alwaysLoad`](/docs/frameworks/react/script-loader#always-load) — runs on page start regardless of consent state, with Consent Mode v2 defaults set to denied
|
|
104
|
+
* **On consent change:** [persists](/docs/frameworks/react/script-loader#persist-after-revocation) — c15t pushes a Consent Mode v2 `update` to gtag instead of removing the script
|
|
105
|
+
|
|
106
|
+
## Tracking events in your app
|
|
107
|
+
|
|
108
|
+
`gtag.js` is `alwaysLoad: true`, so `window.gtag` is present from page start regardless of consent. Calls like `gtag('event', 'sign_up')` are **safe at any time** — c15t sets Consent Mode v2 defaults to denied before the user makes a choice, and Google's SDK suppresses transmission of events while the relevant consent is denied. When consent later changes, c15t emits a Consent Mode v2 `update` so events fire correctly going forward.
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
window.gtag?.('event', 'sign_up', { method: 'email' });
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
You do not need to wrap `gtag(...)` calls in a `useConsentManager().has(...)` check — Consent Mode handles the suppression for you.
|
|
115
|
+
|
|
116
|
+
## Types
|
|
117
|
+
|
|
118
|
+
### GtagOptions
|
|
119
|
+
|
|
120
|
+
|Property|Value|
|
|
121
|
+
|:--|:--|
|
|
122
|
+
|Type Name|\`GtagOptions\`|
|
|
123
|
+
|Source Path|\`./packages/scripts/src/vendors/analytics/google-tag.ts\`|
|
|
124
|
+
|
|
125
|
+
\*ExtractedTypeTable: Could not extract "GtagOptions" from "./packages/scripts/src/vendors/analytics/google-tag.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
126
|
+
|
|
127
|
+
### Script
|
|
128
|
+
|
|
129
|
+
|Property|Value|
|
|
130
|
+
|:--|:--|
|
|
131
|
+
|Type Name|\`Script\`|
|
|
132
|
+
|Source Path|\`./packages/core/src/libs/script-loader/types.ts\`|
|
|
133
|
+
|
|
134
|
+
\*ExtractedTypeTable: Could not extract "Script" from "./packages/core/src/libs/script-loader/types.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Heap
|
|
3
|
+
description: Load Heap with c15t and gate autocapture product analytics behind
|
|
4
|
+
measurement consent.
|
|
5
|
+
group: integrations
|
|
6
|
+
icon: heap
|
|
7
|
+
---
|
|
8
|
+
[Heap](https://www.heap.io/) provides product analytics with automatic interaction capture, identity APIs, event properties, and pageview tracking. The `heap()` helper creates Heap's current heap.js v5 callback queue, records your environment ID and optional client configuration, and loads Heap only when `measurement` consent is available.
|
|
9
|
+
|
|
10
|
+
## Integrate with c15t
|
|
11
|
+
|
|
12
|
+
**React**
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
import { type ReactNode } from 'react';
|
|
16
|
+
import { ConsentManagerProvider } from '@c15t/react';
|
|
17
|
+
import { heap } from '@c15t/scripts/heap';
|
|
18
|
+
|
|
19
|
+
const scripts = [
|
|
20
|
+
heap({
|
|
21
|
+
envId: 'YOUR_APP_ID',
|
|
22
|
+
clientConfig: {
|
|
23
|
+
disableTextCapture: true,
|
|
24
|
+
},
|
|
25
|
+
}),
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
export function ConsentProvider({ children }: { children: ReactNode }) {
|
|
29
|
+
return (
|
|
30
|
+
<ConsentManagerProvider
|
|
31
|
+
options={{
|
|
32
|
+
mode: 'hosted',
|
|
33
|
+
backendURL: 'https://your-instance.c15t.dev',
|
|
34
|
+
scripts,
|
|
35
|
+
}}
|
|
36
|
+
>
|
|
37
|
+
{children}
|
|
38
|
+
</ConsentManagerProvider>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Next.js**
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
'use client';
|
|
47
|
+
|
|
48
|
+
import { type ReactNode } from 'react';
|
|
49
|
+
import { ConsentManagerProvider } from '@c15t/nextjs';
|
|
50
|
+
import { heap } from '@c15t/scripts/heap';
|
|
51
|
+
|
|
52
|
+
const scripts = [
|
|
53
|
+
heap({
|
|
54
|
+
envId: 'YOUR_APP_ID',
|
|
55
|
+
clientConfig: {
|
|
56
|
+
disableTextCapture: true,
|
|
57
|
+
},
|
|
58
|
+
}),
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
export function ConsentProvider({ children }: { children: ReactNode }) {
|
|
62
|
+
return (
|
|
63
|
+
<ConsentManagerProvider
|
|
64
|
+
options={{
|
|
65
|
+
mode: 'hosted',
|
|
66
|
+
backendURL: '/api/c15t',
|
|
67
|
+
scripts,
|
|
68
|
+
}}
|
|
69
|
+
>
|
|
70
|
+
{children}
|
|
71
|
+
</ConsentManagerProvider>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**JavaScript**
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import { getOrCreateConsentRuntime } from 'c15t';
|
|
80
|
+
import { heap } from '@c15t/scripts/heap';
|
|
81
|
+
|
|
82
|
+
getOrCreateConsentRuntime({
|
|
83
|
+
mode: 'hosted',
|
|
84
|
+
backendURL: 'https://your-instance.c15t.dev',
|
|
85
|
+
scripts: [
|
|
86
|
+
heap({
|
|
87
|
+
envId: 'YOUR_APP_ID',
|
|
88
|
+
clientConfig: {
|
|
89
|
+
disableTextCapture: true,
|
|
90
|
+
},
|
|
91
|
+
}),
|
|
92
|
+
],
|
|
93
|
+
});
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## How c15t loads it
|
|
97
|
+
|
|
98
|
+
* **Category:** `measurement` (Analytics)
|
|
99
|
+
* **Loads when:** measurement consent is granted
|
|
100
|
+
* **On revocation:** unloaded - c15t removes the script element it created. `window.heap` and `window.heapReadyCb` remain until the next page load (c15t reloads the page on revocation by default), and Heap has no documented browser opt-out API — treat the load gate as the consent boundary.
|
|
101
|
+
|
|
102
|
+
The helper maps Heap's current web installation snippet into the manifest engine:
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
heap({
|
|
106
|
+
envId: 'YOUR_APP_ID',
|
|
107
|
+
clientConfig: {
|
|
108
|
+
disableTextCapture: true,
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
It creates `window.heapReadyCb` and `window.heap`, records:
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
window.heap.envId = 'YOUR_APP_ID';
|
|
117
|
+
window.heap.appid = 'YOUR_APP_ID';
|
|
118
|
+
window.heap.clientConfig = {
|
|
119
|
+
disableTextCapture: true,
|
|
120
|
+
shouldFetchServerConfig: false,
|
|
121
|
+
};
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
and loads:
|
|
125
|
+
|
|
126
|
+
```txt
|
|
127
|
+
https://cdn.us.heap-api.com/config/YOUR_APP_ID/heap_config.js
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Heap's config script then chain-loads the versioned heap.js runtime for that environment. The official snippet stores queued calls as `{ name, fn }` records in `window.heapReadyCb`; c15t reproduces that callback queue instead of using tuple queues such as `['track', ...args]`.
|
|
131
|
+
|
|
132
|
+
`envId` is required and must be a non-empty string after trimming. Heap app IDs are commonly numeric strings, but Heap's public install docs describe the value as your app ID, so c15t does not enforce a numeric-only format.
|
|
133
|
+
|
|
134
|
+
## Configure heap.js
|
|
135
|
+
|
|
136
|
+
Pass `clientConfig` as the second Heap load argument. Values must be JSON-serializable: plain objects, arrays, strings, finite numbers, booleans, and `null`.
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
import { heap } from '@c15t/scripts/heap';
|
|
140
|
+
|
|
141
|
+
heap({
|
|
142
|
+
envId: 'YOUR_APP_ID',
|
|
143
|
+
clientConfig: {
|
|
144
|
+
disableTextCapture: true,
|
|
145
|
+
disableSessionReplay: true,
|
|
146
|
+
metadataStorage: 'localstorage',
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
c15t always adds `shouldFetchServerConfig: false`, matching Heap's current installation snippet. Do not pass functions, Dates, Maps, Sets, class instances, symbols, `undefined`, `NaN`, or infinite numbers in `clientConfig`.
|
|
152
|
+
|
|
153
|
+
To proxy or self-host the config loader, pass a custom URL:
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
heap({
|
|
157
|
+
envId: 'YOUR_APP_ID',
|
|
158
|
+
scriptUrl: 'https://analytics.example.com/heap_config.js',
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Consent behavior
|
|
163
|
+
|
|
164
|
+
c15t blocks Heap from loading until `measurement` consent is granted and unloads it on revocation. Heap autocaptures interactions when heap.js runs, and its web installation docs do not document a consent-mode-style runtime opt-out API that c15t can call to make an already-loaded SDK inert after consent is withdrawn.
|
|
165
|
+
|
|
166
|
+
That makes the consent gate on load the consent boundary: no Heap config loader, heap.js runtime, cookies, localStorage, automatic page tracking, or interaction capture should start before the user grants `measurement` consent. See the [RudderStack consent notes](/docs/integrations/rudderstack#consent-behavior) for the broader reasoning behind blocking SDK load when a vendor API cannot guarantee denied-by-default collection semantics.
|
|
167
|
+
|
|
168
|
+
## Tracking events in your app
|
|
169
|
+
|
|
170
|
+
c15t gates Heap from loading until `measurement` consent is granted. Your application code that calls Heap's runtime API (`window.heap.track`, `identify`, etc.) is **not** automatically gated - `window.heap` does not exist until the script is loaded, so unguarded calls before consent throw.
|
|
171
|
+
|
|
172
|
+
Guard event calls by checking consent state. From React:
|
|
173
|
+
|
|
174
|
+
```tsx
|
|
175
|
+
import { useCallback } from 'react';
|
|
176
|
+
import { useConsentManager } from '@c15t/react';
|
|
177
|
+
|
|
178
|
+
function SignupExample() {
|
|
179
|
+
const { has } = useConsentManager();
|
|
180
|
+
|
|
181
|
+
const trackSignup = useCallback(() => {
|
|
182
|
+
if (has('measurement')) {
|
|
183
|
+
window.heap?.track('Signup Completed', { plan: 'pro' });
|
|
184
|
+
}
|
|
185
|
+
}, [has]);
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
From plain JavaScript:
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
import { getOrCreateConsentRuntime } from 'c15t';
|
|
193
|
+
|
|
194
|
+
const { consentStore } = getOrCreateConsentRuntime();
|
|
195
|
+
|
|
196
|
+
if (consentStore.getState().has('measurement')) {
|
|
197
|
+
window.heap?.track('Signup Completed', { plan: 'pro' });
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Types
|
|
202
|
+
|
|
203
|
+
### HeapOptions
|
|
204
|
+
|
|
205
|
+
|Property|Value|
|
|
206
|
+
|:--|:--|
|
|
207
|
+
|Type Name|\`HeapOptions\`|
|
|
208
|
+
|Source Path|\`./packages/scripts/src/vendors/analytics/heap.ts\`|
|
|
209
|
+
|
|
210
|
+
\*ExtractedTypeTable: Could not extract "HeapOptions" from "./packages/scripts/src/vendors/analytics/heap.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
211
|
+
|
|
212
|
+
### Script
|
|
213
|
+
|
|
214
|
+
|Property|Value|
|
|
215
|
+
|:--|:--|
|
|
216
|
+
|Type Name|\`Script\`|
|
|
217
|
+
|Source Path|\`./packages/core/src/libs/script-loader/types.ts\`|
|
|
218
|
+
|
|
219
|
+
\*ExtractedTypeTable: Could not extract "Script" from "./packages/core/src/libs/script-loader/types.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Hightouch
|
|
3
|
+
description: Load Hightouch Events with c15t and gate the browser SDK behind
|
|
4
|
+
measurement consent.
|
|
5
|
+
group: integrations
|
|
6
|
+
icon: hightouch
|
|
7
|
+
---
|
|
8
|
+
[Hightouch Events](https://hightouch.com/docs/events/overview) collects customer behavior from websites and sends it into Hightouch for warehouse-backed analytics, activation, and real-time workflows. The `hightouch()` helper creates Hightouch's `window.htevents` queue, records the write key and optional API host for the standalone loader, optionally queues the initial `page()` call, and loads the browser SDK when `measurement` consent is available.
|
|
9
|
+
|
|
10
|
+
## Integrate with c15t
|
|
11
|
+
|
|
12
|
+
**React**
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
import { type ReactNode } from 'react';
|
|
16
|
+
import { ConsentManagerProvider } from '@c15t/react';
|
|
17
|
+
import { hightouch } from '@c15t/scripts/hightouch';
|
|
18
|
+
|
|
19
|
+
const scripts = [
|
|
20
|
+
hightouch({
|
|
21
|
+
writeKey: 'WRITE_KEY',
|
|
22
|
+
apiHost: 'us-east-1.hightouch-events.com',
|
|
23
|
+
}),
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
export function ConsentProvider({ children }: { children: ReactNode }) {
|
|
27
|
+
return (
|
|
28
|
+
<ConsentManagerProvider
|
|
29
|
+
options={{
|
|
30
|
+
mode: 'hosted',
|
|
31
|
+
backendURL: 'https://your-instance.c15t.dev',
|
|
32
|
+
scripts,
|
|
33
|
+
}}
|
|
34
|
+
>
|
|
35
|
+
{children}
|
|
36
|
+
</ConsentManagerProvider>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Next.js**
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
'use client';
|
|
45
|
+
|
|
46
|
+
import { type ReactNode } from 'react';
|
|
47
|
+
import { ConsentManagerProvider } from '@c15t/nextjs';
|
|
48
|
+
import { hightouch } from '@c15t/scripts/hightouch';
|
|
49
|
+
|
|
50
|
+
const scripts = [
|
|
51
|
+
hightouch({
|
|
52
|
+
writeKey: 'WRITE_KEY',
|
|
53
|
+
apiHost: 'us-east-1.hightouch-events.com',
|
|
54
|
+
}),
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
export function ConsentProvider({ children }: { children: ReactNode }) {
|
|
58
|
+
return (
|
|
59
|
+
<ConsentManagerProvider
|
|
60
|
+
options={{
|
|
61
|
+
mode: 'hosted',
|
|
62
|
+
backendURL: '/api/c15t',
|
|
63
|
+
scripts,
|
|
64
|
+
}}
|
|
65
|
+
>
|
|
66
|
+
{children}
|
|
67
|
+
</ConsentManagerProvider>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**JavaScript**
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
import { getOrCreateConsentRuntime } from 'c15t';
|
|
76
|
+
import { hightouch } from '@c15t/scripts/hightouch';
|
|
77
|
+
|
|
78
|
+
getOrCreateConsentRuntime({
|
|
79
|
+
mode: 'hosted',
|
|
80
|
+
backendURL: 'https://your-instance.c15t.dev',
|
|
81
|
+
scripts: [
|
|
82
|
+
hightouch({
|
|
83
|
+
writeKey: 'WRITE_KEY',
|
|
84
|
+
apiHost: 'us-east-1.hightouch-events.com',
|
|
85
|
+
}),
|
|
86
|
+
],
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## How c15t loads it
|
|
91
|
+
|
|
92
|
+
* **Category:** `measurement` (Analytics)
|
|
93
|
+
* **Loads when:** measurement consent is granted
|
|
94
|
+
* **On revocation:** unloaded - c15t removes the script element it created. The `window.htevents` runtime object is left in place until the next page load (c15t reloads the page on revocation by default), so treat the load gate as the consent boundary.
|
|
95
|
+
|
|
96
|
+
The helper maps Hightouch's browser snippet into the manifest engine:
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
hightouch({
|
|
100
|
+
writeKey: 'WRITE_KEY',
|
|
101
|
+
apiHost: 'us-east-1.hightouch-events.com',
|
|
102
|
+
});
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
It creates `window.htevents`, defines the official queue methods, queues:
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
window.htevents.load('WRITE_KEY', {
|
|
109
|
+
apiHost: 'us-east-1.hightouch-events.com',
|
|
110
|
+
});
|
|
111
|
+
window.htevents.page();
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
and loads:
|
|
115
|
+
|
|
116
|
+
```txt
|
|
117
|
+
https://cdn.hightouch-events.com/browser/release/v1-latest/events.min.js
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
`writeKey` is required and must be a non-empty string after trimming. `apiHost` is optional; Hightouch's SDK defaults to `us-east-1.hightouch-events.com`, so pass it only when your Event Source uses another region or a first-party tracking host.
|
|
121
|
+
|
|
122
|
+
## Configure page tracking
|
|
123
|
+
|
|
124
|
+
By default the helper queues `htevents.page()` before the vendor bundle loads. If you want to handle page views yourself, set `trackPageView` to `false`.
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
import { hightouch } from '@c15t/scripts/hightouch';
|
|
128
|
+
|
|
129
|
+
hightouch({
|
|
130
|
+
writeKey: 'WRITE_KEY',
|
|
131
|
+
trackPageView: false,
|
|
132
|
+
});
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
To proxy or self-host the loader, pass a custom URL:
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
hightouch({
|
|
139
|
+
writeKey: 'WRITE_KEY',
|
|
140
|
+
scriptUrl: 'https://analytics.example.com/events.min.js',
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Consent behavior
|
|
145
|
+
|
|
146
|
+
c15t blocks the Hightouch SDK from loading until `measurement` consent is granted and unloads it on revocation. Hightouch does not expose a browser API that prevents collection while loaded — the SDK writes identifiers and delivers events to Hightouch as soon as it runs — so gating the load is the only default that reliably honors missing or denied consent. See the [RudderStack consent notes](/docs/integrations/rudderstack#consent-behavior) for the full reasoning behind this model versus vendor consent-API mapping (as used for Google Tag Manager).
|
|
147
|
+
|
|
148
|
+
## Tracking events in your app
|
|
149
|
+
|
|
150
|
+
c15t gates the Hightouch browser SDK from loading until `measurement` consent is granted. Your application code that calls Hightouch's runtime API (`window.htevents.track`, `identify`, etc.) is **not** automatically gated - `window.htevents` does not exist until c15t initializes the integration, so unguarded calls made before that (or while consent is denied) throw. Once the integration is initialized with consent, early calls queue normally until the SDK finishes loading.
|
|
151
|
+
|
|
152
|
+
Guard event calls by checking consent state. From React:
|
|
153
|
+
|
|
154
|
+
```tsx
|
|
155
|
+
import { useCallback } from 'react';
|
|
156
|
+
import { useConsentManager } from '@c15t/react';
|
|
157
|
+
|
|
158
|
+
function SignupExample() {
|
|
159
|
+
const { has } = useConsentManager();
|
|
160
|
+
|
|
161
|
+
const trackSignup = useCallback(() => {
|
|
162
|
+
if (has('measurement')) {
|
|
163
|
+
window.htevents?.track('Signup Completed', { plan: 'pro' });
|
|
164
|
+
}
|
|
165
|
+
}, [has]);
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
From plain JavaScript:
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
import { getOrCreateConsentRuntime } from 'c15t';
|
|
173
|
+
|
|
174
|
+
const { consentStore } = getOrCreateConsentRuntime();
|
|
175
|
+
|
|
176
|
+
if (consentStore.getState().has('measurement')) {
|
|
177
|
+
window.htevents?.track('Signup Completed', { plan: 'pro' });
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Types
|
|
182
|
+
|
|
183
|
+
### HightouchOptions
|
|
184
|
+
|
|
185
|
+
|Property|Value|
|
|
186
|
+
|:--|:--|
|
|
187
|
+
|Type Name|\`HightouchOptions\`|
|
|
188
|
+
|Source Path|\`./packages/scripts/src/vendors/analytics/hightouch.ts\`|
|
|
189
|
+
|
|
190
|
+
\*ExtractedTypeTable: Could not extract "HightouchOptions" from "./packages/scripts/src/vendors/analytics/hightouch.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
191
|
+
|
|
192
|
+
### Script
|
|
193
|
+
|
|
194
|
+
|Property|Value|
|
|
195
|
+
|:--|:--|
|
|
196
|
+
|Type Name|\`Script\`|
|
|
197
|
+
|Source Path|\`./packages/core/src/libs/script-loader/types.ts\`|
|
|
198
|
+
|
|
199
|
+
\*ExtractedTypeTable: Could not extract "Script" from "./packages/core/src/libs/script-loader/types.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|