@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 CHANGED
@@ -1,193 +1,220 @@
1
1
  # Buyer Intent JS SDK
2
2
 
3
- Buyer intent tracking SDK for partner sites. Works in any frontend — drop in custom HTML elements, or use the React convenience layer. Events are sent via `sendBeacon` for best-effort delivery during navigation. React is never loaded unless you import from the `/react` subpath.
4
-
5
- ## Install
3
+ Buyer intent tracking for partner sites. Drop custom HTML elements into any page no framework required. Events are sent via `sendBeacon` for reliable delivery during navigation.
6
4
 
7
5
  ```bash
8
6
  npm install @g2crowd/buyer-intent-provider-sdk
9
7
  ```
10
8
 
11
- ## Entry Points
12
-
13
- | Import Path | Contains | React Required |
14
- | ------------------------------------------- | -------------------- | -------------- |
15
- | `@g2crowd/buyer-intent-provider-sdk` | SDK, custom elements | No |
16
- | `@g2crowd/buyer-intent-provider-sdk/react` | React components | Yes |
17
- | `@g2crowd/buyer-intent-provider-sdk/server` | Server handlers | No |
18
-
19
9
  ## Quick Start
20
10
 
21
- ### HTML Custom Elements (any framework)
22
-
23
- The SDK registers two custom elements — `<buyer-intent-view>` and `<buyer-intent-click>` — that work in any HTML page. No React, no build step required.
11
+ Import the SDK, wrap your page in a session, and you're tracking:
24
12
 
25
13
  ```html
26
14
  <script type="module">
27
15
  import '@g2crowd/buyer-intent-provider-sdk';
28
16
  </script>
29
17
 
30
- <buyer-intent-view
31
- tag="products.show"
32
- product-id="123"
33
- data-origin="g2.com"
34
- data-activity-endpoint="/api/activity/events"
18
+ <buyer-intent-session
19
+ origin="yoursite.com"
20
+ activity-endpoint="/api/activity/events"
35
21
  >
36
- <h1>Acme CRM</h1>
37
- <p>Product details here.</p>
38
-
39
- <buyer-intent-click
40
- event-name="/leads/create"
41
- product-id="123"
42
- data-origin="g2.com"
43
- data-activity-endpoint="/api/activity/events"
44
- >
45
- <button>Get a Demo</button>
46
- </buyer-intent-click>
47
- </buyer-intent-view>
48
- ```
49
22
 
50
- ### React Components
23
+ <buyer-intent-view tag="products.show">
24
+ <buyer-intent-subject product-id="123"></buyer-intent-subject>
51
25
 
52
- For React apps, import from `/react` to get named components with typed props. Each component hardcodes its `tag` or `event-name`, so typos are caught at compile time.
26
+ <h1>Acme CRM</h1>
27
+ <p>Product details here.</p>
53
28
 
54
- ```tsx
55
- import { BuyerIntent } from '@g2crowd/buyer-intent-provider-sdk/react';
29
+ <buyer-intent-click event-name="/leads/create">
30
+ <button>Get a Demo</button>
31
+ </buyer-intent-click>
32
+ </buyer-intent-view>
56
33
 
57
- export default function ProductPage() {
58
- return (
59
- <BuyerIntent.ProfileView
60
- productId={123}
61
- origin="g2.com"
62
- activityEndpoint="/api/activity/events"
63
- >
64
- <h1>Acme CRM</h1>
65
- <p>Product details here.</p>
66
-
67
- <BuyerIntent.LeadCreateClick productId={123}>
68
- <button>Get a Demo</button>
69
- </BuyerIntent.LeadCreateClick>
70
- </BuyerIntent.ProfileView>
71
- );
72
- }
34
+ </buyer-intent-session>
73
35
  ```
74
36
 
75
- ### Mixing Both
37
+ That's it. When the page loads, a `$view` event fires with `product_ids: [123]` and `tag: "products.show"`. When the user clicks "Get a Demo", a `/leads/create` event fires. Both events inherit the session's `origin` and `activity-endpoint` automatically.
76
38
 
77
- Custom elements and React components use the same underlying event system. You can mix them freely on the same page:
39
+ ## Elements
78
40
 
79
- ```tsx
80
- import { BuyerIntent } from '@g2crowd/buyer-intent-provider-sdk/react';
41
+ ### `<buyer-intent-session>`
81
42
 
82
- <BuyerIntent.PricingView
83
- productId={123}
84
- origin="g2.com"
85
- activityEndpoint="/api/activity/events"
86
- >
87
- <h1>Pricing</h1>
43
+ Wraps a page (or your entire app) and provides config to all elements inside it. Does not fire any events itself.
88
44
 
89
- <buyer-intent-click
90
- event-name="/leads/create"
91
- product-id="123"
92
- data-origin="g2.com"
93
- data-activity-endpoint="/api/activity/events"
94
- >
95
- <button>Start Free Trial</button>
96
- </buyer-intent-click>
97
- </BuyerIntent.PricingView>;
98
- ```
45
+ | Attribute | Description |
46
+ | -------------------- | -------------------------------------------- |
47
+ | `origin` | Partner hostname |
48
+ | `activity-endpoint` | URL to POST events to |
49
+ | `user-type` | Visitor role (default: `"standard"`) |
50
+ | `distinct-id` | Override the auto-generated visitor ID |
99
51
 
100
- ## Custom Elements
52
+ | User Type | Meaning |
53
+ | ---------------- | ------------------------------------------------- |
54
+ | `guest` | Logged-out visitor |
55
+ | `standard` | Logged-in user (default) |
56
+ | `vendor-admin` | Vendor role viewing their own content |
57
+ | `observer` | Internal employee / superuser |
101
58
 
102
- Two elements cover all tracking scenarios. The `tag` or `event-name` attribute determines the interaction type.
59
+ ```html
60
+ <buyer-intent-session origin="yoursite.com" activity-endpoint="/api/activity/events">
61
+ <!-- everything inside inherits origin and endpoint -->
62
+ </buyer-intent-session>
63
+ ```
103
64
 
104
65
  ### `<buyer-intent-view>`
105
66
 
106
67
  Fires a `$view` event when the element connects to the DOM. One event per page navigation.
107
68
 
108
- | Attribute | Required | Description |
109
- | ------------- | -------- | ---------------------------------------------------- |
110
- | `tag` | Yes | View type (see supported tags below) |
111
- | `product-id` | - | Single product ID |
112
- | `product-ids` | - | Multiple product IDs (JSON array or comma-separated) |
113
- | `category-id` | - | Category ID |
69
+ | Attribute | Description |
70
+ | ----------------- | ------------------------------------------- |
71
+ | `tag` | View type identifier (optional) |
72
+ | `source-location` | Controller/action string (optional) |
73
+ | `product-id` | Single product ID (simple pages) |
74
+ | `category-id` | Single category ID (simple pages) |
114
75
 
115
- Supported `tag` values: `products.show`, `products.pricing`, `products.competitors`, `categories.show`, `comparisons.show`, `reviewers.take_survey`
76
+ For pages with one product, you can put the ID directly on the view:
116
77
 
117
78
  ```html
118
- <buyer-intent-view
119
- tag="categories.show"
120
- category-id="45"
121
- data-origin="g2.com"
122
- data-activity-endpoint="/api/activity/events"
123
- >
124
- <h1>CRM Software</h1>
79
+ <buyer-intent-view tag="products.show" product-id="123">
80
+ <h1>Acme CRM</h1>
125
81
  </buyer-intent-view>
126
82
  ```
127
83
 
128
- Multiple product IDs (for comparisons):
84
+ For pages with multiple products, use `<buyer-intent-subject>` children instead (see below).
85
+
86
+ ### `<buyer-intent-subject>`
87
+
88
+ Declares that a product or category is a **subject** of the current view. Nest any number of these inside a `<buyer-intent-view>` — their IDs accumulate into the view's event automatically. Does not render anything visible.
89
+
90
+ | Attribute | Description |
91
+ | -------------- | ---------------------------------------------------- |
92
+ | `product-id` | Single product ID |
93
+ | `product-ids` | Multiple product IDs (JSON array or comma-separated) |
94
+ | `category-id` | Single category ID |
95
+ | `category-ids` | Multiple category IDs (JSON array or comma-separated)|
96
+
97
+ A comparison page that references two products:
129
98
 
130
99
  ```html
131
- <buyer-intent-view tag="comparisons.show" product-ids="[101, 201]">
132
- ...
100
+ <buyer-intent-view tag="comparisons.show">
101
+ <buyer-intent-subject product-id="101"></buyer-intent-subject>
102
+ <buyer-intent-subject product-id="201"></buyer-intent-subject>
103
+
104
+ <h1>Acme CRM vs. Rival CRM</h1>
133
105
  </buyer-intent-view>
106
+ ```
107
+
108
+ The resulting event has `product_ids: [101, 201]`. If the view also has an inline `product-id`, they merge together without duplicates.
109
+
110
+ Subjects can live anywhere inside the view — they don't need to be direct children. This makes them easy to place next to the content they describe:
111
+
112
+ ```html
113
+ <buyer-intent-view tag="categories.show">
114
+ <buyer-intent-subject category-id="45"></buyer-intent-subject>
115
+ <h1>CRM Software</h1>
134
116
 
135
- <buyer-intent-view tag="comparisons.show" product-ids="101,201">
136
- ...
117
+ <div class="product-grid">
118
+ <div class="product-card">
119
+ <buyer-intent-subject product-id="101"></buyer-intent-subject>
120
+ <h2>Acme CRM</h2>
121
+ </div>
122
+
123
+ <div class="product-card">
124
+ <buyer-intent-subject product-id="201"></buyer-intent-subject>
125
+ <h2>Rival CRM</h2>
126
+ </div>
127
+ </div>
137
128
  </buyer-intent-view>
138
129
  ```
139
130
 
140
- ### `<buyer-intent-click>`
131
+ This fires one event: `category_ids: [45]`, `product_ids: [101, 201]`, `tag: "categories.show"`.
141
132
 
142
- Fires an event each time the user clicks anything inside the element.
133
+ ### `<buyer-intent-click>`
143
134
 
144
- | Attribute | Required | Description |
145
- | ------------ | -------- | ----------------------------------- |
146
- | `event-name` | Yes | Click event type (see values below) |
147
- | `product-id` | - | Product ID |
135
+ Fires an event when the user clicks anything inside it.
148
136
 
149
- Supported `event-name` values: `/ad/clicked`, `/leads/create`
137
+ | Attribute | Description |
138
+ | ------------ | ------------------------ |
139
+ | `event-name` | Click event type |
150
140
 
151
141
  ```html
152
- <buyer-intent-click
153
- event-name="/leads/create"
154
- product-id="123"
155
- data-origin="g2.com"
156
- data-activity-endpoint="/api/activity/events"
157
- >
142
+ <buyer-intent-click event-name="/leads/create">
158
143
  <button>Get a Demo</button>
159
144
  </buyer-intent-click>
160
145
  ```
161
146
 
162
- ### Common Attributes
147
+ A click element inside a view automatically inherits the view's tag, product IDs, and category IDs. A click inside a session inherits the session's config. You don't need to repeat anything.
148
+
149
+ ## Full Example
150
+
151
+ Putting it all together — a product page with a session, view, subjects, and two click actions:
152
+
153
+ ```html
154
+ <script type="module">
155
+ import '@g2crowd/buyer-intent-provider-sdk';
156
+ </script>
157
+
158
+ <buyer-intent-session
159
+ origin="yoursite.com"
160
+ activity-endpoint="/api/activity/events"
161
+ user-type="standard"
162
+ >
163
163
 
164
- Both elements accept these optional `data-*` attributes:
164
+ <buyer-intent-view
165
+ tag="products.show"
166
+ source-location="ProductsController#show"
167
+ >
168
+ <buyer-intent-subject product-id="123"></buyer-intent-subject>
169
+ <buyer-intent-subject category-id="45"></buyer-intent-subject>
170
+
171
+ <h1>Acme CRM</h1>
172
+ <p>The best CRM for small teams.</p>
165
173
 
166
- | Attribute | Description |
167
- | ------------------------ | ------------------------------------------------------ |
168
- | `data-origin` | Partner hostname |
169
- | `data-activity-endpoint` | URL to POST events to |
170
- | `data-user-type` | User type string (default: `"standard"`) |
171
- | `data-distinct-id` | Override the auto-generated visitor ID |
172
- | `data-buyer-intent` | JSON object with `sourceLocation` and `context` fields |
174
+ <buyer-intent-click event-name="/leads/create">
175
+ <button>Get a Demo</button>
176
+ </buyer-intent-click>
173
177
 
174
- ### TypeScript Support
178
+ <buyer-intent-click event-name="/ad/clicked">
179
+ <a href="https://acme.example.com">Visit Acme</a>
180
+ </buyer-intent-click>
181
+ </buyer-intent-view>
182
+
183
+ </buyer-intent-session>
184
+ ```
175
185
 
176
- The package augments `JSX.IntrinsicElements` with typed attributes. The `tag` and `event-name` attributes are union types, so invalid values are caught at compile time:
186
+ ## React Support
187
+
188
+ Import from `/react` and use the same element hierarchy with camelCase props:
177
189
 
178
190
  ```tsx
179
- // Type-safe
180
- <buyer-intent-view tag="products.show" product-id="123">
191
+ import { BuyerIntent } from '@g2crowd/buyer-intent-provider-sdk/react';
181
192
 
182
- // Type error: '"invalid.tag"' is not assignable to type 'ViewTag'
183
- <buyer-intent-view tag="invalid.tag" product-id="123">
193
+ export default function ProductPage() {
194
+ return (
195
+ <BuyerIntent.Session origin="yoursite.com" activityEndpoint="/api/activity/events">
196
+ <BuyerIntent.View tag="products.show" sourceLocation="ProductsController#show">
197
+ <BuyerIntent.Subject productId={123} />
198
+ <BuyerIntent.Subject categoryId={45} />
199
+
200
+ <h1>Acme CRM</h1>
201
+
202
+ <BuyerIntent.Click eventName="/leads/create">
203
+ <button>Get a Demo</button>
204
+ </BuyerIntent.Click>
205
+ </BuyerIntent.View>
206
+ </BuyerIntent.Session>
207
+ );
208
+ }
184
209
  ```
185
210
 
186
- ## React Components
211
+ `BuyerIntent.Session`, `BuyerIntent.View`, `BuyerIntent.Subject`, and `BuyerIntent.Click` map 1:1 to the HTML elements described above. The session is a good fit for a layout component or `_app` wrapper so it's set once for every page.
187
212
 
188
- Named React components wrap the custom elements with hardcoded `tag`/`event-name` values. They accept camelCase props instead of HTML attributes.
213
+ ## Syntactic Sugar
189
214
 
190
- ### View Components
215
+ For common page types, pre-built components hardcode the `tag` or `event-name` so you don't have to:
216
+
217
+ ### Views
191
218
 
192
219
  | Component | Tag | Required Prop |
193
220
  | ----------------- | ----------------------- | ------------- |
@@ -198,62 +225,28 @@ Named React components wrap the custom elements with hardcoded `tag`/`event-name
198
225
  | `CompareView` | `comparisons.show` | `productIds` |
199
226
  | `WriteReviewView` | `reviewers.take_survey` | `productId` |
200
227
 
201
- ### Click Components
228
+ ### Clicks
202
229
 
203
230
  | Component | Event Name | Required Prop |
204
231
  | ----------------- | --------------- | ------------- |
205
232
  | `AdClick` | `/ad/clicked` | `productId` |
206
233
  | `LeadCreateClick` | `/leads/create` | `productId` |
207
234
 
208
- ### Generic Trackers
209
-
210
- For custom interaction types, use `ViewTracker` or `ClickTracker` directly:
211
-
212
235
  ```tsx
213
236
  import { BuyerIntent } from '@g2crowd/buyer-intent-provider-sdk/react';
214
237
 
215
- <BuyerIntent.ViewTracker
216
- tag="custom.page_type"
217
- productIds={[123]}
218
- origin="g2.com"
219
- activityEndpoint="/api/activity/events"
220
- >
221
- <CustomPage />
222
- </BuyerIntent.ViewTracker>
238
+ <BuyerIntent.Session origin="yoursite.com" activityEndpoint="/api/activity/events">
239
+ <BuyerIntent.ProfileView productId={123}>
240
+ <h1>Acme CRM</h1>
223
241
 
224
- <BuyerIntent.ClickTracker eventName="$custom_action" productIds={[123]}>
225
- <button>Custom Action</button>
226
- </BuyerIntent.ClickTracker>
242
+ <BuyerIntent.LeadCreateClick productId={123}>
243
+ <button>Get a Demo</button>
244
+ </BuyerIntent.LeadCreateClick>
245
+ </BuyerIntent.ProfileView>
246
+ </BuyerIntent.Session>
227
247
  ```
228
248
 
229
- ### Common Props
230
-
231
- | Prop | Description |
232
- | ------------------ | ---------------------------------------- |
233
- | `origin` | Partner hostname |
234
- | `activityEndpoint` | URL to POST events to |
235
- | `userType` | User type string (default: `"standard"`) |
236
- | `distinctId` | Override the auto-generated visitor ID |
237
- | `sourceLocation` | Controller/action identifier |
238
- | `context` | Arbitrary metadata object |
239
-
240
- ## Visit Properties
241
-
242
- ```js
243
- import { buyerIntent } from '@g2crowd/buyer-intent-provider-sdk';
244
-
245
- buyerIntent.setVisitProperties({
246
- ip: '203.0.113.10',
247
- referrer: 'https://example.com/',
248
- landing_page: 'https://example.com/products/abc',
249
- user_agent: 'Mozilla/5.0',
250
- utm_source: 'newsletter',
251
- utm_medium: 'email',
252
- utm_campaign: 'spring_launch',
253
- utm_term: 'buyer-intent',
254
- utm_content: 'cta-button',
255
- });
256
- ```
249
+ These components still accept `origin`, `activityEndpoint`, `sourceLocation`, and `context` props for cases where you aren't using a session wrapper.
257
250
 
258
251
  ## Backend
259
252
 
@@ -314,22 +307,6 @@ const POST = createNextRouteHandler({
314
307
  export { POST };
315
308
  ```
316
309
 
317
- ## Server API
318
-
319
- | Function | Purpose |
320
- | ---------------------------------- | ---------------------------------------------------------------------------------- |
321
- | `createActivityHandler(options)` | Framework-agnostic handler that validates, enriches, and publishes events to Kafka |
322
- | `createNextRouteHandler(options)` | Next.js Route Handler wrapper around `createActivityHandler` |
323
- | `createDevLoggerProducer(options)` | Dev-only producer that logs messages instead of sending to Kafka |
324
- | `topicName(options)` | Builds a topic name from `partnerId` and optional `prefix` |
325
-
326
- ## Kafka Setup (Partner Checklist)
327
-
328
- - Kafka broker list (host:port)
329
- - Topic name (scoped to their tenant, default: `intent_events_<partnerId>`)
330
- - Auth mechanism (SASL user/pass or mTLS)
331
- - TLS requirements (on/off, CA certs if needed)
332
-
333
310
  ## Event Payload
334
311
 
335
312
  ```json
@@ -337,26 +314,20 @@ export { POST };
337
314
  "name": "$view",
338
315
  "properties": {
339
316
  "product_ids": [123],
340
- "category_ids": [78],
317
+ "category_ids": [45],
341
318
  "tag": "products.show",
342
- "url": "https://example.com/products/abc",
319
+ "url": "https://yoursite.com/products/acme-crm",
343
320
  "user_type": "standard",
344
321
  "distinct_id": "visitor-uuid",
345
- "origin": "g2.com",
346
- "source_location": "ProductsController#show",
347
- "context": { "page": "product" }
322
+ "origin": "yoursite.com",
323
+ "source_location": "ProductsController#show"
348
324
  },
349
325
  "visit": {
350
326
  "properties": {
351
- "landing_page": "https://example.com/products/abc",
352
- "referrer": "https://example.com/",
327
+ "landing_page": "https://yoursite.com/products/acme-crm",
328
+ "referrer": "https://google.com/",
353
329
  "user_agent": "Mozilla/5.0",
354
- "ip": "203.0.113.10",
355
- "utm_source": "newsletter",
356
- "utm_medium": "email",
357
- "utm_campaign": "spring_launch",
358
- "utm_term": "buyer-intent",
359
- "utm_content": "cta-button"
330
+ "utm_source": "newsletter"
360
331
  }
361
332
  }
362
333
  }
package/package.json CHANGED
@@ -1,29 +1,24 @@
1
1
  {
2
2
  "name": "@g2crowd/buyer-intent-provider-sdk",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Buyer intent tracking SDK with pageview defaults",
5
5
  "type": "module",
6
- "main": "index.js",
6
+ "main": "src/index.js",
7
7
  "exports": {
8
- ".": "./index.js",
9
- "./react": "./react/index.js",
10
- "./server": "./server/index.js"
8
+ ".": "./src/index.js",
9
+ "./react": "./src/react/index.js",
10
+ "./server": "./src/server/index.js"
11
11
  },
12
- "types": "index.d.ts",
12
+ "types": "src/index.d.ts",
13
13
  "files": [
14
- "index.js",
15
- "index.d.ts",
16
- "browser",
17
- "react",
18
- "server.js",
19
- "server",
14
+ "src",
20
15
  "README.md"
21
16
  ],
22
17
  "scripts": {
23
18
  "test": "node --experimental-vm-modules ./node_modules/.bin/jest --config ./jest.config.cjs"
24
19
  },
25
20
  "bin": {
26
- "buyer-intent-server": "server.js"
21
+ "buyer-intent-server": "src/server.js"
27
22
  },
28
23
  "license": "MIT",
29
24
  "repository": {
@@ -46,7 +41,7 @@
46
41
  }
47
42
  },
48
43
  "sideEffects": [
49
- "./browser/elements/*.js"
44
+ "./src/browser/elements/*.js"
50
45
  ],
51
46
  "devDependencies": {
52
47
  "@testing-library/dom": "^9.3.4",
@@ -1,5 +1,10 @@
1
- export { ViewTracker, ClickTracker } from './tracker.js';
2
- import { ViewTracker, ClickTracker } from './tracker.js';
1
+ export {
2
+ SessionProvider,
3
+ SubjectTracker,
4
+ ViewTracker,
5
+ ClickTracker,
6
+ } from './tracker.js';
7
+ import { SessionProvider, SubjectTracker, ViewTracker, ClickTracker } from './tracker.js';
3
8
  import React from 'react';
4
9
 
5
10
  function view(tag) {
@@ -0,0 +1,105 @@
1
+ import React from 'react';
2
+
3
+ function buildViewAttrs({
4
+ productId,
5
+ productIds,
6
+ categoryId,
7
+ tag,
8
+ sourceLocation,
9
+ context,
10
+ origin,
11
+ activityEndpoint,
12
+ userType,
13
+ distinctId,
14
+ }) {
15
+ const payload = { sourceLocation, context };
16
+ const attrs = {
17
+ 'data-buyer-intent': JSON.stringify(payload),
18
+ 'data-origin': origin,
19
+ 'data-activity-endpoint': activityEndpoint,
20
+ 'data-user-type': userType,
21
+ 'data-distinct-id': distinctId,
22
+ };
23
+
24
+ if (tag) attrs.tag = tag;
25
+ if (sourceLocation) attrs['source-location'] = sourceLocation;
26
+ if (productId != null) attrs['product-id'] = String(productId);
27
+ if (productIds) attrs['product-ids'] = JSON.stringify(productIds);
28
+ if (categoryId != null) attrs['category-id'] = String(categoryId);
29
+
30
+ return attrs;
31
+ }
32
+
33
+ function buildClickAttrs({
34
+ eventName,
35
+ productId,
36
+ productIds,
37
+ categoryId,
38
+ sourceLocation,
39
+ context,
40
+ origin,
41
+ activityEndpoint,
42
+ userType,
43
+ distinctId,
44
+ }) {
45
+ const payload = { sourceLocation, context };
46
+ const attrs = {
47
+ 'data-buyer-intent': JSON.stringify(payload),
48
+ 'data-origin': origin,
49
+ 'data-activity-endpoint': activityEndpoint,
50
+ 'data-user-type': userType,
51
+ 'data-distinct-id': distinctId,
52
+ };
53
+
54
+ if (eventName) attrs['event-name'] = eventName;
55
+ if (productId != null) attrs['product-id'] = String(productId);
56
+ if (productIds) attrs['product-ids'] = JSON.stringify(productIds);
57
+ if (categoryId != null) attrs['category-id'] = String(categoryId);
58
+
59
+ return attrs;
60
+ }
61
+
62
+ export function SessionProvider({
63
+ origin,
64
+ activityEndpoint,
65
+ userType,
66
+ distinctId,
67
+ children,
68
+ }) {
69
+ const attrs = {};
70
+ if (origin) attrs.origin = origin;
71
+ if (activityEndpoint) attrs['activity-endpoint'] = activityEndpoint;
72
+ if (userType) attrs['user-type'] = userType;
73
+ if (distinctId) attrs['distinct-id'] = distinctId;
74
+ return React.createElement('buyer-intent-session', attrs, children);
75
+ }
76
+
77
+ export function SubjectTracker({
78
+ productId,
79
+ categoryId,
80
+ productIds,
81
+ categoryIds,
82
+ }) {
83
+ const attrs = {};
84
+ if (productId != null) attrs['product-id'] = String(productId);
85
+ if (categoryId != null) attrs['category-id'] = String(categoryId);
86
+ if (productIds) attrs['product-ids'] = JSON.stringify(productIds);
87
+ if (categoryIds) attrs['category-ids'] = JSON.stringify(categoryIds);
88
+ return React.createElement('buyer-intent-subject', attrs);
89
+ }
90
+
91
+ export function ViewTracker({ children, ...rest }) {
92
+ return React.createElement(
93
+ 'buyer-intent-view',
94
+ buildViewAttrs(rest),
95
+ children
96
+ );
97
+ }
98
+
99
+ export function ClickTracker({ children, ...rest }) {
100
+ return React.createElement(
101
+ 'buyer-intent-click',
102
+ buildClickAttrs(rest),
103
+ children
104
+ );
105
+ }