@c15t/scripts 2.2.0 → 2.3.0
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 +3 -0
- package/dist/e2e-test-utils.cjs +1 -0
- package/dist/e2e-test-utils.js +1 -0
- package/dist/registry.cjs +30 -0
- package/dist/registry.js +30 -0
- package/dist/vendors/ads-and-pixels/pinterest-tag.cjs +167 -0
- package/dist/vendors/ads-and-pixels/pinterest-tag.js +123 -0
- package/dist/vendors/analytics/one-dollar-stats.cjs +72 -0
- package/dist/vendors/analytics/one-dollar-stats.js +28 -0
- package/dist/vendors/functional/front-chat.cjs +110 -0
- package/dist/vendors/functional/front-chat.js +66 -0
- package/dist-types/__tests__/helpers.d.ts +1 -1
- package/dist-types/engine/compile.d.ts +1 -1
- package/dist-types/engine/runtime.d.ts +1 -1
- package/dist-types/registry.d.ts +27 -0
- package/dist-types/resolve.d.ts +1 -1
- package/dist-types/vendors/_shared/install-builders.d.ts +1 -1
- package/dist-types/vendors/ads-and-pixels/pinterest-tag.d.ts +295 -0
- package/dist-types/vendors/analytics/adobe-analytics.d.ts +1 -1
- package/dist-types/vendors/analytics/matomo-analytics.d.ts +1 -1
- package/dist-types/vendors/analytics/one-dollar-stats.d.ts +38 -0
- package/dist-types/vendors/functional/front-chat.d.ts +61 -0
- package/docs/README.md +3 -0
- package/docs/integrations/front-chat.md +178 -0
- package/docs/integrations/one-dollar-stats.md +118 -0
- package/docs/integrations/overview.md +3 -0
- package/docs/integrations/pinterest-tag.md +236 -0
- package/package.json +18 -2
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Front Chat
|
|
3
|
+
description: Load Front Chat after functionality consent and initialize the
|
|
4
|
+
widget when its SDK is ready.
|
|
5
|
+
group: integrations
|
|
6
|
+
---
|
|
7
|
+
Front Chat adds a live chat widget connected to your Front inbox. c15t waits for
|
|
8
|
+
functionality consent before loading the widget's SDK and calling `FrontChat('init')`.
|
|
9
|
+
|
|
10
|
+
## Official Front documentation
|
|
11
|
+
|
|
12
|
+
* [Set up a Front Chat inbox and install the widget](https://help.front.com/en/articles/2049)
|
|
13
|
+
* [Chat Widget SDK reference](https://dev.frontapp.com/docs/chat-sdk-reference)
|
|
14
|
+
|
|
15
|
+
## Integrate with c15t
|
|
16
|
+
|
|
17
|
+
Copy the `chatId` from the widget code snippet in your Front Chat channel's
|
|
18
|
+
**Installation** tab. Pass that value to `frontChat()` instead of adding Front's
|
|
19
|
+
script snippet separately.
|
|
20
|
+
|
|
21
|
+
**React**
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
import { type ReactNode } from 'react';
|
|
25
|
+
import { ConsentManagerProvider } from '@c15t/react';
|
|
26
|
+
import { frontChat } from '@c15t/scripts/front-chat';
|
|
27
|
+
|
|
28
|
+
const scripts = [frontChat({ chatId: 'YOUR_FRONT_CHAT_ID' })];
|
|
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 { frontChat } from '@c15t/scripts/front-chat';
|
|
53
|
+
|
|
54
|
+
const scripts = [frontChat({ chatId: 'YOUR_FRONT_CHAT_ID' })];
|
|
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 { frontChat } from '@c15t/scripts/front-chat';
|
|
76
|
+
|
|
77
|
+
getOrCreateConsentRuntime({
|
|
78
|
+
mode: 'hosted',
|
|
79
|
+
backendURL: 'https://your-instance.c15t.dev',
|
|
80
|
+
scripts: [frontChat({ chatId: 'YOUR_FRONT_CHAT_ID' })],
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## How c15t loads it
|
|
85
|
+
|
|
86
|
+
* **Category:** `functionality` (Functional)
|
|
87
|
+
* **Loads when:** functionality consent is granted
|
|
88
|
+
* **Script:** `https://chat-assets.frontapp.com/v1/chat.bundle.js`
|
|
89
|
+
* **After load:** c15t calls `window.FrontChat('init', ...)` with your chat ID and launcher options
|
|
90
|
+
* **On revocation:** c15t reloads the page by default and leaves Front Chat unloaded while functionality consent is denied
|
|
91
|
+
|
|
92
|
+
Keep the default `reloadOnConsentRevoked: true` behavior. Removing a script tag
|
|
93
|
+
does not stop a widget that has already initialized, and this integration does
|
|
94
|
+
not provide automatic widget shutdown when you disable the reload.
|
|
95
|
+
|
|
96
|
+
## Configure the integration
|
|
97
|
+
|
|
98
|
+
`chatId` must be a non-empty string. The default launcher is enabled unless you
|
|
99
|
+
set `useDefaultLauncher` to `false`:
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
frontChat({
|
|
103
|
+
chatId: 'YOUR_FRONT_CHAT_ID',
|
|
104
|
+
useDefaultLauncher: false,
|
|
105
|
+
})
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
With the default launcher hidden, use Front's SDK to open the widget from your
|
|
109
|
+
own launcher after consent is granted and the widget has initialized. See the
|
|
110
|
+
[SDK reference](https://dev.frontapp.com/docs/chat-sdk-reference) for commands
|
|
111
|
+
and initialization requirements.
|
|
112
|
+
|
|
113
|
+
### Content Security Policy
|
|
114
|
+
|
|
115
|
+
If your Content Security Policy (CSP) uses nonces, pass the server-generated nonce
|
|
116
|
+
for the current response. c15t applies it to the loader script and forwards it
|
|
117
|
+
to Front's initialization call:
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
function createChatScripts(nonce: string) {
|
|
121
|
+
return [frontChat({ chatId: 'YOUR_FRONT_CHAT_ID', nonce })];
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Front creates additional resources for the widget. Follow Front's
|
|
126
|
+
[CSP setup instructions](https://help.front.com/en/articles/2049) for the
|
|
127
|
+
remaining policy requirements. You can override the loader URL with `scriptSrc`
|
|
128
|
+
if you serve the SDK through your own proxy; this does not proxy the widget's
|
|
129
|
+
other requests.
|
|
130
|
+
|
|
131
|
+
### Optional session cleanup
|
|
132
|
+
|
|
133
|
+
`frontChat()` does not automatically delete an existing Front session. You can
|
|
134
|
+
also request session cleanup before c15t's revocation reload using
|
|
135
|
+
`shutdownFrontChat()`:
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
import { getOrCreateConsentRuntime } from 'c15t';
|
|
139
|
+
import { frontChat, shutdownFrontChat } from '@c15t/scripts/front-chat';
|
|
140
|
+
|
|
141
|
+
getOrCreateConsentRuntime({
|
|
142
|
+
mode: 'hosted',
|
|
143
|
+
backendURL: 'https://your-instance.c15t.dev',
|
|
144
|
+
scripts: [frontChat({ chatId: 'YOUR_FRONT_CHAT_ID' })],
|
|
145
|
+
callbacks: {
|
|
146
|
+
onBeforeConsentRevocationReload: ({ preferences }) => {
|
|
147
|
+
if (!preferences.functionality) {
|
|
148
|
+
shutdownFrontChat();
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
The function calls Front's `shutdown` command with `clearSession: true` when
|
|
156
|
+
the SDK is available. This is a best-effort request: the reload does not wait
|
|
157
|
+
for Front to finish clearing its session. Keep reload on revocation enabled;
|
|
158
|
+
the cleanup call does not replace it.
|
|
159
|
+
|
|
160
|
+
## Types
|
|
161
|
+
|
|
162
|
+
### FrontChatOptions
|
|
163
|
+
|
|
164
|
+
|Property|Value|
|
|
165
|
+
|:--|:--|
|
|
166
|
+
|Type Name|\`FrontChatOptions\`|
|
|
167
|
+
|Source Path|\`./packages/scripts/src/vendors/functional/front-chat.ts\`|
|
|
168
|
+
|
|
169
|
+
\*ExtractedTypeTable: Could not extract "FrontChatOptions" from "./packages/scripts/src/vendors/functional/front-chat.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
170
|
+
|
|
171
|
+
### Script
|
|
172
|
+
|
|
173
|
+
|Property|Value|
|
|
174
|
+
|:--|:--|
|
|
175
|
+
|Type Name|\`Script\`|
|
|
176
|
+
|Source Path|\`./packages/core/src/libs/script-loader/types.ts\`|
|
|
177
|
+
|
|
178
|
+
\*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,118 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: OneDollarStats
|
|
3
|
+
description: Load OneDollarStats after measurement consent with optional tracker
|
|
4
|
+
data attributes.
|
|
5
|
+
group: integrations
|
|
6
|
+
---
|
|
7
|
+
[OneDollarStats](https://onedollarstats.com/) matches events to the domain registered in your dashboard, so no API key is needed. This helper loads its classic deferred script after measurement consent and forwards settings as `data-*` attributes.
|
|
8
|
+
|
|
9
|
+
## Integrate with c15t
|
|
10
|
+
|
|
11
|
+
**React**
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import { type ReactNode } from 'react';
|
|
15
|
+
import { ConsentManagerProvider } from '@c15t/react';
|
|
16
|
+
import { oneDollarStats } from '@c15t/scripts/one-dollar-stats';
|
|
17
|
+
|
|
18
|
+
const scripts = [oneDollarStats()];
|
|
19
|
+
|
|
20
|
+
export function ConsentProvider({ children }: { children: ReactNode }) {
|
|
21
|
+
return (
|
|
22
|
+
<ConsentManagerProvider
|
|
23
|
+
options={{
|
|
24
|
+
mode: 'hosted',
|
|
25
|
+
backendURL: 'https://your-instance.c15t.dev',
|
|
26
|
+
scripts,
|
|
27
|
+
}}
|
|
28
|
+
>
|
|
29
|
+
{children}
|
|
30
|
+
</ConsentManagerProvider>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Next.js**
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
'use client';
|
|
39
|
+
|
|
40
|
+
import { type ReactNode } from 'react';
|
|
41
|
+
import { ConsentManagerProvider } from '@c15t/nextjs';
|
|
42
|
+
import { oneDollarStats } from '@c15t/scripts/one-dollar-stats';
|
|
43
|
+
|
|
44
|
+
const scripts = [oneDollarStats()];
|
|
45
|
+
|
|
46
|
+
export function ConsentProvider({ children }: { children: ReactNode }) {
|
|
47
|
+
return (
|
|
48
|
+
<ConsentManagerProvider
|
|
49
|
+
options={{
|
|
50
|
+
mode: 'hosted',
|
|
51
|
+
backendURL: '/api/c15t',
|
|
52
|
+
scripts,
|
|
53
|
+
}}
|
|
54
|
+
>
|
|
55
|
+
{children}
|
|
56
|
+
</ConsentManagerProvider>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**JavaScript**
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
import { getOrCreateConsentRuntime } from 'c15t';
|
|
65
|
+
import { oneDollarStats } from '@c15t/scripts/one-dollar-stats';
|
|
66
|
+
|
|
67
|
+
getOrCreateConsentRuntime({
|
|
68
|
+
mode: 'hosted',
|
|
69
|
+
backendURL: 'https://your-instance.c15t.dev',
|
|
70
|
+
scripts: [oneDollarStats()],
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Tracker settings
|
|
75
|
+
|
|
76
|
+
All settings use strings and omit the `data-` prefix. Unknown settings are forwarded for compatibility with future tracker options.
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
oneDollarStats({
|
|
80
|
+
hostname: 'docs.example.com',
|
|
81
|
+
devmode: 'true',
|
|
82
|
+
autocollect: 'false',
|
|
83
|
+
'hash-routing': 'true',
|
|
84
|
+
url: 'https://analytics.example.com/events',
|
|
85
|
+
})
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
* `hostname` must be a bare hostname, optionally including a port. It overrides the event hostname on every host, including production.
|
|
89
|
+
* Local testing needs both `hostname` and `devmode: 'true'`.
|
|
90
|
+
* `autocollect: 'false'` disables automatic pageview and click collection.
|
|
91
|
+
* `'hash-routing': 'false'` omits the attribute entirely: the CDN tracker enables hash routing whenever the attribute is present, regardless of its value.
|
|
92
|
+
* `url` overrides the collection endpoint. Leave it unset to use the vendor default.
|
|
93
|
+
|
|
94
|
+
The tracker handles browser history navigation itself; no extra router hook is required. See the [vendor installation reference](https://docs.onedollarstats.com/installation) for its settings.
|
|
95
|
+
|
|
96
|
+
## Consent behaviour
|
|
97
|
+
|
|
98
|
+
The script uses the `measurement` category and loads only when that consent is granted. On revocation, c15t removes its script element. Removing a script does not undo code that already executed, including the tracker's history hooks and event listeners. Use c15t's reload-on-revocation behaviour to clear the running tracker, and check measurement consent before making manual tracking calls.
|
|
99
|
+
|
|
100
|
+
## Types
|
|
101
|
+
|
|
102
|
+
### OneDollarStatsOptions
|
|
103
|
+
|
|
104
|
+
|Property|Value|
|
|
105
|
+
|:--|:--|
|
|
106
|
+
|Type Name|\`OneDollarStatsOptions\`|
|
|
107
|
+
|Source Path|\`./packages/scripts/src/vendors/analytics/one-dollar-stats.ts\`|
|
|
108
|
+
|
|
109
|
+
\*ExtractedTypeTable: Could not extract "OneDollarStatsOptions" from "./packages/scripts/src/vendors/analytics/one-dollar-stats.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
110
|
+
|
|
111
|
+
### Script
|
|
112
|
+
|
|
113
|
+
|Property|Value|
|
|
114
|
+
|:--|:--|
|
|
115
|
+
|Type Name|\`Script\`|
|
|
116
|
+
|Source Path|\`./packages/core/src/libs/script-loader/types.ts\`|
|
|
117
|
+
|
|
118
|
+
\*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.\*
|
|
@@ -94,6 +94,7 @@ Analytics integrations usually require `measurement` consent. Some vendors can r
|
|
|
94
94
|
* [LogRocket](/docs/integrations/logrocket)
|
|
95
95
|
* [Matomo Analytics](/docs/integrations/matomo-analytics)
|
|
96
96
|
* [PostHog](/docs/integrations/posthog)
|
|
97
|
+
* [OneDollarStats](/docs/integrations/one-dollar-stats)
|
|
97
98
|
* [Promptwatch](/docs/integrations/promptwatch)
|
|
98
99
|
* [Pirsch](/docs/integrations/pirsch)
|
|
99
100
|
* [RudderStack](/docs/integrations/rudderstack)
|
|
@@ -107,6 +108,7 @@ Analytics integrations usually require `measurement` consent. Some vendors can r
|
|
|
107
108
|
Functional integrations usually require `functionality` consent. They add optional user-facing capabilities, such as chat widgets, that should only run after the user allows them.
|
|
108
109
|
|
|
109
110
|
* [Crisp](/docs/integrations/crisp)
|
|
111
|
+
* [Front Chat](/docs/integrations/front-chat)
|
|
110
112
|
* [Intercom](/docs/integrations/intercom)
|
|
111
113
|
|
|
112
114
|
## Ads & Pixels
|
|
@@ -120,6 +122,7 @@ Advertising pixels usually require `marketing` consent. Many of them need startu
|
|
|
120
122
|
* [LinkedIn Insight Tag](/docs/integrations/linkedin-insights)
|
|
121
123
|
* [Microsoft UET](/docs/integrations/microsoft-uet)
|
|
122
124
|
* [X (Twitter) Pixel](/docs/integrations/x-pixel)
|
|
125
|
+
* [Pinterest Tag](/docs/integrations/pinterest-tag)
|
|
123
126
|
|
|
124
127
|
## Tag Managers
|
|
125
128
|
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Pinterest Tag
|
|
3
|
+
description: Track conversions and build audiences for Pinterest advertising campaigns.
|
|
4
|
+
icon: pinterest
|
|
5
|
+
group: integrations
|
|
6
|
+
---
|
|
7
|
+
Pinterest Tag is Pinterest's conversion tracking and audience building tool. It measures the actions people take on your site after seeing your Pins, so you can attribute conversions and build retargeting audiences for Pinterest Ads.
|
|
8
|
+
|
|
9
|
+
## Official Pinterest documentation
|
|
10
|
+
|
|
11
|
+
* [Install the Pinterest Tag (Pinterest Business Help)](https://help.pinterest.com/en/business/article/install-the-pinterest-tag)
|
|
12
|
+
* [Pinterest Tag event codes](https://help.pinterest.com/en/business/article/add-event-codes)
|
|
13
|
+
|
|
14
|
+
## Integrate with c15t
|
|
15
|
+
|
|
16
|
+
**React**
|
|
17
|
+
|
|
18
|
+
```tsx
|
|
19
|
+
import { type ReactNode } from 'react';
|
|
20
|
+
import { ConsentManagerProvider } from '@c15t/react';
|
|
21
|
+
import { pinterestTag } from '@c15t/scripts/pinterest-tag';
|
|
22
|
+
|
|
23
|
+
const scripts = [pinterestTag({ tagId: '2613654212508' })];
|
|
24
|
+
|
|
25
|
+
export function ConsentProvider({ children }: { children: ReactNode }) {
|
|
26
|
+
return (
|
|
27
|
+
<ConsentManagerProvider
|
|
28
|
+
options={{
|
|
29
|
+
mode: 'hosted',
|
|
30
|
+
backendURL: 'https://your-instance.c15t.dev',
|
|
31
|
+
scripts,
|
|
32
|
+
}}
|
|
33
|
+
>
|
|
34
|
+
{children}
|
|
35
|
+
</ConsentManagerProvider>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**Next.js**
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
'use client';
|
|
44
|
+
|
|
45
|
+
import { type ReactNode } from 'react';
|
|
46
|
+
import { ConsentManagerProvider } from '@c15t/nextjs';
|
|
47
|
+
import { pinterestTag } from '@c15t/scripts/pinterest-tag';
|
|
48
|
+
|
|
49
|
+
const scripts = [pinterestTag({ tagId: '2613654212508' })];
|
|
50
|
+
|
|
51
|
+
export function ConsentProvider({ children }: { children: ReactNode }) {
|
|
52
|
+
return (
|
|
53
|
+
<ConsentManagerProvider
|
|
54
|
+
options={{
|
|
55
|
+
mode: 'hosted',
|
|
56
|
+
backendURL: '/api/c15t',
|
|
57
|
+
scripts,
|
|
58
|
+
}}
|
|
59
|
+
>
|
|
60
|
+
{children}
|
|
61
|
+
</ConsentManagerProvider>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**JavaScript**
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import { getOrCreateConsentRuntime } from 'c15t';
|
|
70
|
+
import { pinterestTag } from '@c15t/scripts/pinterest-tag';
|
|
71
|
+
|
|
72
|
+
getOrCreateConsentRuntime({
|
|
73
|
+
mode: 'hosted',
|
|
74
|
+
backendURL: 'https://your-instance.c15t.dev',
|
|
75
|
+
scripts: [pinterestTag({ tagId: '2613654212508' })],
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## How c15t loads it
|
|
80
|
+
|
|
81
|
+
* **Category:** `marketing` (Ads & Pixels)
|
|
82
|
+
* **Loads when:** marketing consent is granted
|
|
83
|
+
* **On revocation:** [persists](/docs/frameworks/react/script-loader#persist-after-revocation) — c15t calls `pintrk('setconsent', false)`, which stops Pinterest from sending events and clears its first-party cookies without removing the script
|
|
84
|
+
|
|
85
|
+
Before the loader runs, c15t recreates Pinterest's base code: it defines the `pintrk` queue stub with `version = "3.0"`, then queues `pintrk('load', tagId)`, `pintrk('setconsent', true)`, and `pintrk('page')`. Pinterest's `core.js` replays the queue once it loads.
|
|
86
|
+
|
|
87
|
+
## Configure the integration
|
|
88
|
+
|
|
89
|
+
You can pass extra load options and disable the default page-visit event when you need finer control:
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
pinterestTag({
|
|
93
|
+
tagId: '2613654212508',
|
|
94
|
+
loadOptions: {
|
|
95
|
+
em: 'hello@example.com',
|
|
96
|
+
},
|
|
97
|
+
trackPageVisit: false,
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
`loadOptions` is forwarded as the third argument to `pintrk('load', tagId, loadOptions)`. Pinterest uses `em` (email) and `external_id` for enhanced match, and hashes plain values before sending them.
|
|
102
|
+
|
|
103
|
+
> ⚠️ **Warning:**
|
|
104
|
+
> Enhanced match values are personal data. Only pass em or external\_id when your application has separately obtained consent to share them with Pinterest — marketing consent alone does not cover this.
|
|
105
|
+
|
|
106
|
+
## Tracking events in your app
|
|
107
|
+
|
|
108
|
+
c15t gates the Pinterest Tag from loading until `marketing` consent is granted. After consent is granted the script stays in the DOM, and c15t calls `pintrk('setconsent', false)` if consent is later revoked, so Pinterest itself suppresses events.
|
|
109
|
+
|
|
110
|
+
This means `window.pintrk` is only defined after the user has granted marketing consent at least once. Use `pinterestTagEvent()` for typed standard and custom events — it's a no-op until `pintrk` exists, so it's safe to call before consent, and it doesn't bypass consent afterwards. Guarding with `has('marketing')` is still good practice so you don't queue events Pinterest will drop:
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
import { useCallback } from 'react';
|
|
114
|
+
import { useConsentManager } from '@c15t/react';
|
|
115
|
+
import { pinterestTagEvent } from '@c15t/scripts/pinterest-tag';
|
|
116
|
+
|
|
117
|
+
function useTrackCheckout() {
|
|
118
|
+
const { has } = useConsentManager();
|
|
119
|
+
return useCallback(() => {
|
|
120
|
+
if (has('marketing')) {
|
|
121
|
+
pinterestTagEvent('checkout', {
|
|
122
|
+
event_id: 'eventId0001',
|
|
123
|
+
value: 99.99,
|
|
124
|
+
order_quantity: 1,
|
|
125
|
+
currency: 'USD',
|
|
126
|
+
order_id: 'X-15148',
|
|
127
|
+
line_items: [
|
|
128
|
+
{
|
|
129
|
+
product_name: 'Parker Boots',
|
|
130
|
+
product_id: '1414',
|
|
131
|
+
product_category: 'Shoes',
|
|
132
|
+
product_price: 99.99,
|
|
133
|
+
product_quantity: 1,
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}, [has]);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function CheckoutButton() {
|
|
142
|
+
const trackCheckout = useTrackCheckout();
|
|
143
|
+
return <button onClick={trackCheckout}>Complete checkout</button>;
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
From plain JavaScript:
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
import { getOrCreateConsentRuntime } from 'c15t';
|
|
151
|
+
import { pinterestTagEvent } from '@c15t/scripts/pinterest-tag';
|
|
152
|
+
|
|
153
|
+
const { consentStore } = getOrCreateConsentRuntime();
|
|
154
|
+
|
|
155
|
+
if (consentStore.getState().has('marketing')) {
|
|
156
|
+
pinterestTagEvent('lead', { lead_type: 'newsletter' });
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Pass `event_id` when you also send the same event through the Pinterest Conversions API so Pinterest can deduplicate the two. Product details (`product_name`, `product_id`, `product_price`, and so on) go inside `line_items`, one entry per product — Pinterest ignores them at the top level.
|
|
161
|
+
|
|
162
|
+
### Event names
|
|
163
|
+
|
|
164
|
+
Pinterest recognises 20 event types for conversion tracking: `checkout`, `addtocart`, `pagevisit`, `signup`, `watchvideo`, `lead`, `search`, `viewcategory`, `custom`, `addpaymentinfo`, `addtowishlist`, `initiatecheckout`, `subscribe`, `viewcontent`, `contact`, `schedule`, `findlocation`, `customizeproduct`, `submitapplication`, and `starttrial`. `pinterestTagEvent()` also accepts any other string as a user-defined event, which Pinterest uses for audience targeting only — it logs a console warning for these.
|
|
165
|
+
|
|
166
|
+
Which events you need depends on the campaign type. Conversions campaigns require at least one of `signup`, `lead`, `addtocart`, or `checkout`; catalog sales, conversion insights, dynamic retargeting, and the Verified Merchant Program all require `pagevisit`, `addtocart`, and `checkout` with `currency` set. See [Add event codes](https://help.pinterest.com/en/business/article/add-event-codes) for the full matrix.
|
|
167
|
+
|
|
168
|
+
### Debugging with a callback
|
|
169
|
+
|
|
170
|
+
Pinterest accepts an optional `(didInit, error)` callback after the event data. Pass it as the third argument to `pinterestTagEvent()` to surface tag errors during development:
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
import { pinterestTagEvent } from '@c15t/scripts/pinterest-tag';
|
|
174
|
+
|
|
175
|
+
pinterestTagEvent('lead', { lead_type: 'Newsletter' }, (didInit, error) => {
|
|
176
|
+
if (!didInit) {
|
|
177
|
+
console.error('Pinterest Tag error:', error);
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Types
|
|
183
|
+
|
|
184
|
+
### PinterestTagOptions
|
|
185
|
+
|
|
186
|
+
|Property|Value|
|
|
187
|
+
|:--|:--|
|
|
188
|
+
|Type Name|\`PinterestTagOptions\`|
|
|
189
|
+
|Source Path|\`./packages/scripts/src/vendors/ads-and-pixels/pinterest-tag.ts\`|
|
|
190
|
+
|
|
191
|
+
\*ExtractedTypeTable: Could not extract "PinterestTagOptions" from "./packages/scripts/src/vendors/ads-and-pixels/pinterest-tag.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
192
|
+
|
|
193
|
+
### PinterestTagLoadOptions
|
|
194
|
+
|
|
195
|
+
|Property|Value|
|
|
196
|
+
|:--|:--|
|
|
197
|
+
|Type Name|\`PinterestTagLoadOptions\`|
|
|
198
|
+
|Source Path|\`./packages/scripts/src/vendors/ads-and-pixels/pinterest-tag.ts\`|
|
|
199
|
+
|
|
200
|
+
\*ExtractedTypeTable: Could not extract "PinterestTagLoadOptions" from "./packages/scripts/src/vendors/ads-and-pixels/pinterest-tag.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
201
|
+
|
|
202
|
+
### PinterestTagEventData
|
|
203
|
+
|
|
204
|
+
|Property|Value|
|
|
205
|
+
|:--|:--|
|
|
206
|
+
|Type Name|\`PinterestTagEventData\`|
|
|
207
|
+
|Source Path|\`./packages/scripts/src/vendors/ads-and-pixels/pinterest-tag.ts\`|
|
|
208
|
+
|
|
209
|
+
\*ExtractedTypeTable: Could not extract "PinterestTagEventData" from "./packages/scripts/src/vendors/ads-and-pixels/pinterest-tag.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
210
|
+
|
|
211
|
+
### PinterestTagLineItem
|
|
212
|
+
|
|
213
|
+
|Property|Value|
|
|
214
|
+
|:--|:--|
|
|
215
|
+
|Type Name|\`PinterestTagLineItem\`|
|
|
216
|
+
|Source Path|\`./packages/scripts/src/vendors/ads-and-pixels/pinterest-tag.ts\`|
|
|
217
|
+
|
|
218
|
+
\*ExtractedTypeTable: Could not extract "PinterestTagLineItem" from "./packages/scripts/src/vendors/ads-and-pixels/pinterest-tag.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
219
|
+
|
|
220
|
+
### PinterestTagEventCallback
|
|
221
|
+
|
|
222
|
+
|Property|Value|
|
|
223
|
+
|:--|:--|
|
|
224
|
+
|Type Name|\`PinterestTagEventCallback\`|
|
|
225
|
+
|Source Path|\`./packages/scripts/src/vendors/ads-and-pixels/pinterest-tag.ts\`|
|
|
226
|
+
|
|
227
|
+
\*ExtractedTypeTable: Could not extract "PinterestTagEventCallback" from "./packages/scripts/src/vendors/ads-and-pixels/pinterest-tag.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
228
|
+
|
|
229
|
+
### Script
|
|
230
|
+
|
|
231
|
+
|Property|Value|
|
|
232
|
+
|:--|:--|
|
|
233
|
+
|Type Name|\`Script\`|
|
|
234
|
+
|Source Path|\`./packages/core/src/libs/script-loader/types.ts\`|
|
|
235
|
+
|
|
236
|
+
\*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.\*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@c15t/scripts",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "Consent-aware script integrations for Google Tag Manager, Google Consent Mode v2, GA4, Google Ads, Meta Pixel, and more.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"c15t",
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"linkedin-insights",
|
|
29
29
|
"microsoft-uet",
|
|
30
30
|
"x-pixel",
|
|
31
|
+
"pinterest-tag",
|
|
31
32
|
"analytics-consent",
|
|
32
33
|
"consent-mode",
|
|
33
34
|
"consent-mode-v2",
|
|
@@ -127,6 +128,11 @@
|
|
|
127
128
|
"import": "./dist/vendors/analytics/mixpanel-analytics.js",
|
|
128
129
|
"require": "./dist/vendors/analytics/mixpanel-analytics.cjs"
|
|
129
130
|
},
|
|
131
|
+
"./one-dollar-stats": {
|
|
132
|
+
"types": "./dist-types/vendors/analytics/one-dollar-stats.d.ts",
|
|
133
|
+
"import": "./dist/vendors/analytics/one-dollar-stats.js",
|
|
134
|
+
"require": "./dist/vendors/analytics/one-dollar-stats.cjs"
|
|
135
|
+
},
|
|
130
136
|
"./pirsch": {
|
|
131
137
|
"types": "./dist-types/vendors/analytics/pirsch.d.ts",
|
|
132
138
|
"import": "./dist/vendors/analytics/pirsch.js",
|
|
@@ -172,6 +178,11 @@
|
|
|
172
178
|
"import": "./dist/vendors/functional/crisp.js",
|
|
173
179
|
"require": "./dist/vendors/functional/crisp.cjs"
|
|
174
180
|
},
|
|
181
|
+
"./front-chat": {
|
|
182
|
+
"types": "./dist-types/vendors/functional/front-chat.d.ts",
|
|
183
|
+
"import": "./dist/vendors/functional/front-chat.js",
|
|
184
|
+
"require": "./dist/vendors/functional/front-chat.cjs"
|
|
185
|
+
},
|
|
175
186
|
"./intercom": {
|
|
176
187
|
"types": "./dist-types/vendors/functional/intercom.d.ts",
|
|
177
188
|
"import": "./dist/vendors/functional/intercom.js",
|
|
@@ -217,6 +228,11 @@
|
|
|
217
228
|
"import": "./dist/vendors/ads-and-pixels/x-pixel.js",
|
|
218
229
|
"require": "./dist/vendors/ads-and-pixels/x-pixel.cjs"
|
|
219
230
|
},
|
|
231
|
+
"./pinterest-tag": {
|
|
232
|
+
"types": "./dist-types/vendors/ads-and-pixels/pinterest-tag.d.ts",
|
|
233
|
+
"import": "./dist/vendors/ads-and-pixels/pinterest-tag.js",
|
|
234
|
+
"require": "./dist/vendors/ads-and-pixels/pinterest-tag.cjs"
|
|
235
|
+
},
|
|
220
236
|
"./registry": {
|
|
221
237
|
"types": "./dist-types/registry.d.ts",
|
|
222
238
|
"import": "./dist/registry.js",
|
|
@@ -253,7 +269,7 @@
|
|
|
253
269
|
"devDependencies": {
|
|
254
270
|
"@c15t/typescript-config": "0.0.1",
|
|
255
271
|
"@c15t/vitest-config": "1.0.0",
|
|
256
|
-
"c15t": "2.
|
|
272
|
+
"c15t": "2.3.0",
|
|
257
273
|
"playwright": "1.58.2"
|
|
258
274
|
},
|
|
259
275
|
"publishConfig": {
|