@g2crowd/buyer-intent-provider-sdk 0.3.0 → 0.4.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/README.md +168 -197
- package/package.json +9 -14
- package/{browser → src/browser}/components/index.js +7 -2
- package/src/browser/components/tracker.js +105 -0
- package/src/browser/dom.js +184 -0
- package/{browser → src/browser}/elements/base.js +26 -1
- package/src/browser/elements/index.js +6 -0
- package/{browser → src/browser}/index.js +2 -0
- package/{browser → src/browser}/sdk.js +104 -30
- package/{index.d.ts → src/index.d.ts} +34 -5
- package/{index.js → src/index.js} +2 -0
- package/{react → src/react}/index.d.ts +23 -1
- package/{react → src/react}/index.js +8 -0
- package/browser/components/tracker.js +0 -40
- package/browser/dom.js +0 -98
- package/browser/elements/index.js +0 -1
- /package/{browser → src/browser}/core.js +0 -0
- /package/{browser → src/browser}/identity.js +0 -0
- /package/{browser → src/browser}/transport.js +0 -0
- /package/{server → src/server}/handlers.js +0 -0
- /package/{server → src/server}/index.js +0 -0
- /package/{server.js → src/server.js} +0 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
function parseJson(value) {
|
|
2
|
+
if (!value) {
|
|
3
|
+
return undefined;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
try {
|
|
7
|
+
return JSON.parse(value);
|
|
8
|
+
} catch (_error) {
|
|
9
|
+
return undefined;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function parseArray(value) {
|
|
14
|
+
if (!value) {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const parsed = parseJson(value);
|
|
19
|
+
if (Array.isArray(parsed)) {
|
|
20
|
+
return parsed;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (typeof value === 'string') {
|
|
24
|
+
return value
|
|
25
|
+
.split(',')
|
|
26
|
+
.map((entry) => entry.trim())
|
|
27
|
+
.filter(Boolean);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function readTagElement(element) {
|
|
34
|
+
if (!element) {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (element.tagName === 'SCRIPT') {
|
|
39
|
+
const parsed =
|
|
40
|
+
parseJson(element.textContent || '') ||
|
|
41
|
+
parseJson(element.getAttribute('data-buyer-intent'));
|
|
42
|
+
if (parsed && typeof parsed === 'object') {
|
|
43
|
+
return parsed;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const dataJson = parseJson(element.getAttribute('data-buyer-intent'));
|
|
48
|
+
if (dataJson && typeof dataJson === 'object') {
|
|
49
|
+
return dataJson;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const dataset = element.dataset || {};
|
|
53
|
+
return {
|
|
54
|
+
productIds: parseArray(dataset.productIds),
|
|
55
|
+
categoryIds: parseArray(dataset.categoryIds),
|
|
56
|
+
tag: dataset.tag,
|
|
57
|
+
sourceLocation: dataset.sourceLocation,
|
|
58
|
+
context: parseJson(dataset.context),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function readTags(elements) {
|
|
63
|
+
if (typeof document === 'undefined') {
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const found = elements || new Set();
|
|
68
|
+
const legacy = document.getElementById('buyer-intent-tags');
|
|
69
|
+
if (legacy) {
|
|
70
|
+
found.add(legacy);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
document.querySelectorAll('[data-buyer-intent]').forEach((element) => {
|
|
74
|
+
found.add(element);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
return Array.from(found)
|
|
78
|
+
.map((element) => ({ element, tag: readTagElement(element) }))
|
|
79
|
+
.filter((entry) => entry.tag && typeof entry.tag === 'object');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function readElementConfig(element) {
|
|
83
|
+
if (!element || !element.dataset) {
|
|
84
|
+
return {};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const { origin, userType, distinctId, activityEndpoint } = element.dataset;
|
|
88
|
+
|
|
89
|
+
return { origin, userType, distinctId, activityEndpoint };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function resolveEventName(element, fallback) {
|
|
93
|
+
if (element && element.dataset && element.dataset.eventName) {
|
|
94
|
+
return element.dataset.eventName;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return fallback;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function parseIds(raw) {
|
|
101
|
+
if (!raw) return [];
|
|
102
|
+
try {
|
|
103
|
+
const parsed = JSON.parse(raw);
|
|
104
|
+
if (Array.isArray(parsed)) return parsed.map(Number);
|
|
105
|
+
} catch (_e) {}
|
|
106
|
+
return raw.split(',').map((s) => Number(s.trim())).filter((n) => !Number.isNaN(n));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function readSessionConfig(element) {
|
|
110
|
+
if (!element || typeof element.closest !== 'function') {
|
|
111
|
+
return {};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const session = element.closest('buyer-intent-session');
|
|
115
|
+
if (!session) {
|
|
116
|
+
return {};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
origin: session.getAttribute('origin') || undefined,
|
|
121
|
+
activityEndpoint: session.getAttribute('activity-endpoint') || undefined,
|
|
122
|
+
userType: session.getAttribute('user-type') || undefined,
|
|
123
|
+
distinctId: session.getAttribute('distinct-id') || undefined,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function collectSubjectIds(viewElement) {
|
|
128
|
+
if (!viewElement || typeof viewElement.querySelectorAll !== 'function') {
|
|
129
|
+
return { productIds: [], categoryIds: [] };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const subjects = viewElement.querySelectorAll('buyer-intent-subject');
|
|
133
|
+
const productIds = [];
|
|
134
|
+
const categoryIds = [];
|
|
135
|
+
|
|
136
|
+
for (const subject of subjects) {
|
|
137
|
+
const pids = subject.getAttribute('product-ids');
|
|
138
|
+
const pid = subject.getAttribute('product-id');
|
|
139
|
+
if (pids) {
|
|
140
|
+
productIds.push(...parseIds(pids));
|
|
141
|
+
} else if (pid) {
|
|
142
|
+
productIds.push(Number(pid));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const cids = subject.getAttribute('category-ids');
|
|
146
|
+
const cid = subject.getAttribute('category-id');
|
|
147
|
+
if (cids) {
|
|
148
|
+
categoryIds.push(...parseIds(cids));
|
|
149
|
+
} else if (cid) {
|
|
150
|
+
categoryIds.push(Number(cid));
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return { productIds, categoryIds };
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function readViewContext(clickElement) {
|
|
158
|
+
if (!clickElement || typeof clickElement.closest !== 'function') {
|
|
159
|
+
return {};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const view = clickElement.closest('buyer-intent-view');
|
|
163
|
+
if (!view) {
|
|
164
|
+
return {};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const viewData = readTagElement(view) || {};
|
|
168
|
+
const subjectIds = collectSubjectIds(view);
|
|
169
|
+
|
|
170
|
+
const productIds = [
|
|
171
|
+
...(viewData.productIds || []),
|
|
172
|
+
...subjectIds.productIds,
|
|
173
|
+
];
|
|
174
|
+
const categoryIds = [
|
|
175
|
+
...(viewData.categoryIds || []),
|
|
176
|
+
...subjectIds.categoryIds,
|
|
177
|
+
];
|
|
178
|
+
|
|
179
|
+
return {
|
|
180
|
+
...viewData,
|
|
181
|
+
productIds: productIds.length ? [...new Set(productIds)] : undefined,
|
|
182
|
+
categoryIds: categoryIds.length ? [...new Set(categoryIds)] : undefined,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
@@ -33,6 +33,11 @@ function readIntentData(element) {
|
|
|
33
33
|
data.tag = tag;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
const sourceLocation = element.getAttribute('source-location');
|
|
37
|
+
if (sourceLocation) {
|
|
38
|
+
data.sourceLocation = sourceLocation;
|
|
39
|
+
}
|
|
40
|
+
|
|
36
41
|
const eventName = element.getAttribute('event-name');
|
|
37
42
|
if (eventName) {
|
|
38
43
|
element.dataset.eventName = eventName;
|
|
@@ -58,12 +63,28 @@ function defineElement(tagName, ElementClass) {
|
|
|
58
63
|
}
|
|
59
64
|
}
|
|
60
65
|
|
|
66
|
+
class BuyerIntentSessionElement extends BaseHTMLElement {
|
|
67
|
+
connectedCallback() {
|
|
68
|
+
this.style.display = 'contents';
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
class BuyerIntentSubjectElement extends BaseHTMLElement {
|
|
73
|
+
connectedCallback() {
|
|
74
|
+
this.style.display = 'none';
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
61
78
|
class BuyerIntentViewElement extends BaseHTMLElement {
|
|
62
79
|
connectedCallback() {
|
|
63
80
|
ensureSDK();
|
|
64
81
|
mergeIntentData(this, readIntentData(this));
|
|
65
82
|
this.dataset.trigger = 'view';
|
|
66
|
-
|
|
83
|
+
queueMicrotask(() => {
|
|
84
|
+
this.dispatchEvent(
|
|
85
|
+
new CustomEvent('buyerintent:view', { bubbles: true })
|
|
86
|
+
);
|
|
87
|
+
});
|
|
67
88
|
}
|
|
68
89
|
}
|
|
69
90
|
|
|
@@ -88,10 +109,14 @@ class BuyerIntentClickElement extends BaseHTMLElement {
|
|
|
88
109
|
}
|
|
89
110
|
}
|
|
90
111
|
|
|
112
|
+
defineElement('buyer-intent-session', BuyerIntentSessionElement);
|
|
113
|
+
defineElement('buyer-intent-subject', BuyerIntentSubjectElement);
|
|
91
114
|
defineElement('buyer-intent-view', BuyerIntentViewElement);
|
|
92
115
|
defineElement('buyer-intent-click', BuyerIntentClickElement);
|
|
93
116
|
|
|
94
117
|
export {
|
|
118
|
+
BuyerIntentSessionElement,
|
|
119
|
+
BuyerIntentSubjectElement,
|
|
95
120
|
BuyerIntentViewElement,
|
|
96
121
|
BuyerIntentClickElement,
|
|
97
122
|
mergeIntentData,
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { createBuyerIntentCore } from './core.js';
|
|
2
2
|
import { sendWithBeacon } from './transport.js';
|
|
3
3
|
import { createIdentityManager } from './identity.js';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
readTags,
|
|
6
|
+
readElementConfig,
|
|
7
|
+
resolveEventName,
|
|
8
|
+
readSessionConfig,
|
|
9
|
+
collectSubjectIds,
|
|
10
|
+
readViewContext,
|
|
11
|
+
} from './dom.js';
|
|
5
12
|
|
|
6
13
|
const DEFAULT_ACTIVITY_ENDPOINT = '/activity/events';
|
|
7
14
|
const DEFAULT_VIEW_NAME = '$view';
|
|
@@ -79,23 +86,12 @@ export function createBuyerIntentSDK() {
|
|
|
79
86
|
return entries.length > 0;
|
|
80
87
|
}
|
|
81
88
|
|
|
82
|
-
function
|
|
89
|
+
function sendPayload(element, defaultEventName) {
|
|
83
90
|
if (typeof window === 'undefined') {
|
|
84
91
|
return false;
|
|
85
92
|
}
|
|
86
93
|
|
|
87
|
-
const
|
|
88
|
-
if (pageKey === lastPageKey) {
|
|
89
|
-
return false;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
lastPageKey = pageKey;
|
|
93
|
-
const hasTags = applyDomTags(element);
|
|
94
|
-
if (!hasTags) {
|
|
95
|
-
return false;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const eventName = resolveEventName(element, viewName);
|
|
94
|
+
const eventName = resolveEventName(element, defaultEventName);
|
|
99
95
|
const payload = core.buildPayload({
|
|
100
96
|
name: eventName,
|
|
101
97
|
url: window.location.href,
|
|
@@ -110,25 +106,45 @@ export function createBuyerIntentSDK() {
|
|
|
110
106
|
return sent;
|
|
111
107
|
}
|
|
112
108
|
|
|
109
|
+
function trackPageviewInternal(element) {
|
|
110
|
+
if (typeof window === 'undefined') {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const pageKey = `${window.location.pathname}${window.location.search}`;
|
|
115
|
+
if (pageKey === lastPageKey) {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
lastPageKey = pageKey;
|
|
120
|
+
return sendPayload(element, viewName);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function trackPageview(element) {
|
|
124
|
+
if (typeof window === 'undefined') {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const pageKey = `${window.location.pathname}${window.location.search}`;
|
|
129
|
+
if (pageKey === lastPageKey) {
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
lastPageKey = pageKey;
|
|
134
|
+
const hasTags = applyDomTags(element);
|
|
135
|
+
if (!hasTags) {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return sendPayload(element, viewName);
|
|
140
|
+
}
|
|
141
|
+
|
|
113
142
|
function trackClick(element) {
|
|
114
143
|
if (typeof window === 'undefined' || !element) {
|
|
115
144
|
return false;
|
|
116
145
|
}
|
|
117
146
|
|
|
118
|
-
|
|
119
|
-
const eventName = resolveEventName(element, DEFAULT_CLICK_NAME);
|
|
120
|
-
const payload = core.buildPayload({
|
|
121
|
-
name: eventName,
|
|
122
|
-
url: window.location.href,
|
|
123
|
-
origin: origin || window.location.hostname,
|
|
124
|
-
distinctId: identity.ensure(),
|
|
125
|
-
userType,
|
|
126
|
-
visit: buildVisitContext(),
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
const sent = sendWithBeacon(activityEndpoint, payload);
|
|
130
|
-
core.resetPageState();
|
|
131
|
-
return sent;
|
|
147
|
+
return sendPayload(element, DEFAULT_CLICK_NAME);
|
|
132
148
|
}
|
|
133
149
|
|
|
134
150
|
function init(options = {}) {
|
|
@@ -196,13 +212,58 @@ export function createBuyerIntentSDK() {
|
|
|
196
212
|
return () => nextRouter.events.off('routeChangeComplete', handler);
|
|
197
213
|
}
|
|
198
214
|
|
|
215
|
+
function resolveConfig(element) {
|
|
216
|
+
const session = readSessionConfig(element);
|
|
217
|
+
const own = readElementConfig(element);
|
|
218
|
+
return {
|
|
219
|
+
origin: session.origin || own.origin,
|
|
220
|
+
activityEndpoint: session.activityEndpoint || own.activityEndpoint,
|
|
221
|
+
userType: session.userType || own.userType,
|
|
222
|
+
distinctId: session.distinctId || own.distinctId,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function applyConfig(config) {
|
|
227
|
+
if (config.activityEndpoint) {
|
|
228
|
+
setActivityEndpoint(config.activityEndpoint);
|
|
229
|
+
}
|
|
230
|
+
if (config.origin || config.userType || config.distinctId) {
|
|
231
|
+
setBaseProperties({
|
|
232
|
+
origin: config.origin,
|
|
233
|
+
userType: config.userType,
|
|
234
|
+
distinctId: config.distinctId,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
199
239
|
function handleView(element) {
|
|
200
240
|
if (!element || firedViewElements.has(element)) {
|
|
201
241
|
return false;
|
|
202
242
|
}
|
|
203
243
|
|
|
204
244
|
firedViewElements.add(element);
|
|
205
|
-
|
|
245
|
+
|
|
246
|
+
// 1. Resolve config: session ancestor > element's own data-* attrs
|
|
247
|
+
const config = resolveConfig(element);
|
|
248
|
+
applyConfig(config);
|
|
249
|
+
|
|
250
|
+
// 2. Read page tags from element's data-buyer-intent (existing flow)
|
|
251
|
+
const entries = readTags(new Set([element]));
|
|
252
|
+
entries.forEach(({ element: tagElement, tag }) => {
|
|
253
|
+
if (tagElement !== element) {
|
|
254
|
+
applyElementConfig(tagElement);
|
|
255
|
+
}
|
|
256
|
+
core.tagPage(tag);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
// 3. Collect IDs from descendant <buyer-intent-subject> elements
|
|
260
|
+
const subjectIds = collectSubjectIds(element);
|
|
261
|
+
if (subjectIds.productIds.length || subjectIds.categoryIds.length) {
|
|
262
|
+
core.tagPage(subjectIds);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// 4. Fire pageview
|
|
266
|
+
return trackPageviewInternal(element, config);
|
|
206
267
|
}
|
|
207
268
|
|
|
208
269
|
function handleClick(element) {
|
|
@@ -210,7 +271,20 @@ export function createBuyerIntentSDK() {
|
|
|
210
271
|
return false;
|
|
211
272
|
}
|
|
212
273
|
|
|
213
|
-
|
|
274
|
+
// 1. Resolve config: session ancestor > element's own data-* attrs
|
|
275
|
+
const config = resolveConfig(element);
|
|
276
|
+
applyConfig(config);
|
|
277
|
+
|
|
278
|
+
// 2. Inherit tag/IDs from ancestor <buyer-intent-view>
|
|
279
|
+
const viewCtx = readViewContext(element);
|
|
280
|
+
if (viewCtx && typeof viewCtx === 'object') {
|
|
281
|
+
core.tagPage(viewCtx);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// 3. Also read click element's own data-buyer-intent
|
|
285
|
+
const entries = readTags(new Set([element]));
|
|
286
|
+
entries.forEach(({ tag }) => core.tagPage(tag));
|
|
287
|
+
|
|
214
288
|
return trackClick(element);
|
|
215
289
|
}
|
|
216
290
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export class BuyerIntentSessionElement extends HTMLElement {}
|
|
2
|
+
export class BuyerIntentSubjectElement extends HTMLElement {}
|
|
1
3
|
export class BuyerIntentViewElement extends HTMLElement {}
|
|
2
4
|
export class BuyerIntentClickElement extends HTMLElement {}
|
|
3
5
|
|
|
@@ -11,10 +13,18 @@ export type ViewTag =
|
|
|
11
13
|
|
|
12
14
|
export type ClickEventName = '/ad/clicked' | '/leads/create';
|
|
13
15
|
|
|
16
|
+
/**
|
|
17
|
+
* - `guest` — logged-out visitor
|
|
18
|
+
* - `standard` — logged-in user (default)
|
|
19
|
+
* - `vendor-admin` — vendor role viewing their own content
|
|
20
|
+
* - `observer` — internal employee / superuser
|
|
21
|
+
*/
|
|
22
|
+
export type UserType = 'guest' | 'standard' | 'vendor-admin' | 'observer';
|
|
23
|
+
|
|
14
24
|
interface BuyerIntentBaseAttrs {
|
|
15
25
|
'data-origin'?: string;
|
|
16
26
|
'data-activity-endpoint'?: string;
|
|
17
|
-
'data-user-type'?:
|
|
27
|
+
'data-user-type'?: UserType;
|
|
18
28
|
'data-distinct-id'?: string;
|
|
19
29
|
'data-buyer-intent'?: string;
|
|
20
30
|
'product-id'?: string;
|
|
@@ -22,17 +32,36 @@ interface BuyerIntentBaseAttrs {
|
|
|
22
32
|
'category-id'?: string;
|
|
23
33
|
}
|
|
24
34
|
|
|
35
|
+
export interface BuyerIntentSessionAttrs {
|
|
36
|
+
origin?: string;
|
|
37
|
+
'activity-endpoint'?: string;
|
|
38
|
+
'user-type'?: UserType;
|
|
39
|
+
'distinct-id'?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface BuyerIntentSubjectAttrs {
|
|
43
|
+
'product-id'?: string;
|
|
44
|
+
'product-ids'?: string;
|
|
45
|
+
'category-id'?: string;
|
|
46
|
+
'category-ids'?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
25
49
|
export interface BuyerIntentViewAttrs extends BuyerIntentBaseAttrs {
|
|
26
|
-
tag
|
|
50
|
+
tag?: ViewTag | string;
|
|
51
|
+
'source-location'?: string;
|
|
27
52
|
}
|
|
28
53
|
|
|
29
54
|
export interface BuyerIntentClickAttrs extends BuyerIntentBaseAttrs {
|
|
30
|
-
'event-name'
|
|
55
|
+
'event-name'?: ClickEventName | string;
|
|
31
56
|
}
|
|
32
57
|
|
|
33
58
|
declare global {
|
|
34
59
|
namespace JSX {
|
|
35
60
|
interface IntrinsicElements {
|
|
61
|
+
'buyer-intent-session': BuyerIntentSessionAttrs &
|
|
62
|
+
React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
63
|
+
'buyer-intent-subject': BuyerIntentSubjectAttrs &
|
|
64
|
+
React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
36
65
|
'buyer-intent-view': BuyerIntentViewAttrs &
|
|
37
66
|
React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
38
67
|
'buyer-intent-click': BuyerIntentClickAttrs &
|
|
@@ -46,7 +75,7 @@ export type BuyerIntentInitOptions = {
|
|
|
46
75
|
origin?: string;
|
|
47
76
|
viewName?: string;
|
|
48
77
|
distinctId?: string;
|
|
49
|
-
userType?:
|
|
78
|
+
userType?: UserType;
|
|
50
79
|
};
|
|
51
80
|
|
|
52
81
|
export type BuyerIntentTagOptions = {
|
|
@@ -60,7 +89,7 @@ export type BuyerIntentTagOptions = {
|
|
|
60
89
|
export type BuyerIntentBaseOptions = {
|
|
61
90
|
origin?: string;
|
|
62
91
|
distinctId?: string;
|
|
63
|
-
userType?:
|
|
92
|
+
userType?: UserType;
|
|
64
93
|
};
|
|
65
94
|
|
|
66
95
|
export type BuyerIntentVisitProperties = {
|
|
@@ -1,15 +1,31 @@
|
|
|
1
1
|
import type * as React from 'react';
|
|
2
|
+
import type { UserType } from '../index';
|
|
2
3
|
|
|
3
4
|
type CommonProps = {
|
|
4
5
|
sourceLocation?: string;
|
|
5
6
|
context?: Record<string, unknown>;
|
|
6
7
|
origin?: string;
|
|
7
8
|
activityEndpoint?: string;
|
|
8
|
-
userType?:
|
|
9
|
+
userType?: UserType;
|
|
9
10
|
distinctId?: string;
|
|
10
11
|
children?: React.ReactNode;
|
|
11
12
|
};
|
|
12
13
|
|
|
14
|
+
export type SessionProviderProps = {
|
|
15
|
+
origin?: string;
|
|
16
|
+
activityEndpoint?: string;
|
|
17
|
+
userType?: UserType;
|
|
18
|
+
distinctId?: string;
|
|
19
|
+
children?: React.ReactNode;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export type SubjectTrackerProps = {
|
|
23
|
+
productId?: number;
|
|
24
|
+
categoryId?: number;
|
|
25
|
+
productIds?: number[];
|
|
26
|
+
categoryIds?: number[];
|
|
27
|
+
};
|
|
28
|
+
|
|
13
29
|
export type ViewTrackerProps = CommonProps & {
|
|
14
30
|
tag?: string;
|
|
15
31
|
productId?: number;
|
|
@@ -29,6 +45,8 @@ type CategoryViewProps = CommonProps & { categoryId: number };
|
|
|
29
45
|
type ProductIdsViewProps = CommonProps & { productIds: number[] };
|
|
30
46
|
type ProductIdClickProps = CommonProps & { productId: number };
|
|
31
47
|
|
|
48
|
+
export const SessionProvider: React.FC<SessionProviderProps>;
|
|
49
|
+
export const SubjectTracker: React.FC<SubjectTrackerProps>;
|
|
32
50
|
export const ViewTracker: React.FC<ViewTrackerProps>;
|
|
33
51
|
export const ClickTracker: React.FC<ClickTrackerProps>;
|
|
34
52
|
|
|
@@ -42,6 +60,10 @@ export const AdClick: React.FC<ProductIdClickProps>;
|
|
|
42
60
|
export const LeadCreateClick: React.FC<ProductIdClickProps>;
|
|
43
61
|
|
|
44
62
|
export const BuyerIntent: {
|
|
63
|
+
Session: React.FC<SessionProviderProps>;
|
|
64
|
+
Subject: React.FC<SubjectTrackerProps>;
|
|
65
|
+
View: React.FC<ViewTrackerProps>;
|
|
66
|
+
Click: React.FC<ClickTrackerProps>;
|
|
45
67
|
ViewTracker: React.FC<ViewTrackerProps>;
|
|
46
68
|
ClickTracker: React.FC<ClickTrackerProps>;
|
|
47
69
|
ProfileView: React.FC<ProductIdViewProps>;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import '../browser/elements/index.js';
|
|
2
2
|
import {
|
|
3
|
+
SessionProvider,
|
|
4
|
+
SubjectTracker,
|
|
3
5
|
ViewTracker,
|
|
4
6
|
ClickTracker,
|
|
5
7
|
ProfileView,
|
|
@@ -13,6 +15,8 @@ import {
|
|
|
13
15
|
} from '../browser/components/index.js';
|
|
14
16
|
|
|
15
17
|
export {
|
|
18
|
+
SessionProvider,
|
|
19
|
+
SubjectTracker,
|
|
16
20
|
ViewTracker,
|
|
17
21
|
ClickTracker,
|
|
18
22
|
ProfileView,
|
|
@@ -26,6 +30,10 @@ export {
|
|
|
26
30
|
};
|
|
27
31
|
|
|
28
32
|
export const BuyerIntent = {
|
|
33
|
+
Session: SessionProvider,
|
|
34
|
+
Subject: SubjectTracker,
|
|
35
|
+
View: ViewTracker,
|
|
36
|
+
Click: ClickTracker,
|
|
29
37
|
ViewTracker,
|
|
30
38
|
ClickTracker,
|
|
31
39
|
ProfileView,
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
function buildAttrs({
|
|
4
|
-
productId,
|
|
5
|
-
productIds,
|
|
6
|
-
categoryId,
|
|
7
|
-
tag,
|
|
8
|
-
eventName,
|
|
9
|
-
sourceLocation,
|
|
10
|
-
context,
|
|
11
|
-
origin,
|
|
12
|
-
activityEndpoint,
|
|
13
|
-
userType,
|
|
14
|
-
distinctId,
|
|
15
|
-
}) {
|
|
16
|
-
const payload = { sourceLocation, context };
|
|
17
|
-
const attrs = {
|
|
18
|
-
'data-buyer-intent': JSON.stringify(payload),
|
|
19
|
-
'data-origin': origin,
|
|
20
|
-
'data-activity-endpoint': activityEndpoint,
|
|
21
|
-
'data-user-type': userType,
|
|
22
|
-
'data-distinct-id': distinctId,
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
if (tag) attrs.tag = tag;
|
|
26
|
-
if (eventName) attrs['event-name'] = eventName;
|
|
27
|
-
if (productId != null) attrs['product-id'] = String(productId);
|
|
28
|
-
if (productIds) attrs['product-ids'] = JSON.stringify(productIds);
|
|
29
|
-
if (categoryId != null) attrs['category-id'] = String(categoryId);
|
|
30
|
-
|
|
31
|
-
return attrs;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function ViewTracker({ children, ...rest }) {
|
|
35
|
-
return React.createElement('buyer-intent-view', buildAttrs(rest), children);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export function ClickTracker({ children, ...rest }) {
|
|
39
|
-
return React.createElement('buyer-intent-click', buildAttrs(rest), children);
|
|
40
|
-
}
|