@g2crowd/buyer-intent-provider-sdk 0.2.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 +237 -190
- package/package.json +19 -12
- package/src/browser/components/index.js +29 -0
- package/src/browser/components/tracker.js +105 -0
- package/src/browser/dom.js +184 -0
- package/src/browser/elements/base.js +124 -0
- package/src/browser/elements/index.js +6 -0
- package/src/browser/identity.js +67 -0
- package/src/browser/index.js +8 -0
- package/src/browser/sdk.js +336 -0
- package/src/browser/transport.js +25 -0
- package/src/index.d.ts +126 -0
- package/src/index.js +8 -0
- package/src/react/index.d.ts +77 -0
- package/{browser → src/react}/index.js +20 -10
- package/browser/sdk.js +0 -468
- package/browser/tag_component.js +0 -46
- package/browser/trackers.js +0 -42
- package/index.d.ts +0 -183
- package/index.js +0 -15
- /package/{browser → src/browser}/core.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
package/README.md
CHANGED
|
@@ -1,286 +1,333 @@
|
|
|
1
1
|
# Buyer Intent JS SDK
|
|
2
2
|
|
|
3
|
-
Buyer
|
|
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
|
-
|
|
9
|
+
## Quick Start
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
npm install kafkajs
|
|
15
|
-
```
|
|
11
|
+
Import the SDK, wrap your page in a session, and you're tracking:
|
|
16
12
|
|
|
17
|
-
|
|
13
|
+
```html
|
|
14
|
+
<script type="module">
|
|
15
|
+
import '@g2crowd/buyer-intent-provider-sdk';
|
|
16
|
+
</script>
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
<buyer-intent-session
|
|
19
|
+
origin="yoursite.com"
|
|
20
|
+
activity-endpoint="/api/activity/events"
|
|
21
|
+
>
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
<
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
<button>Get a Demo</button>
|
|
35
|
-
</BuyerIntent.LeadCreateClick>
|
|
36
|
-
</BuyerIntent.ProfileView>
|
|
37
|
-
);
|
|
38
|
-
}
|
|
23
|
+
<buyer-intent-view tag="products.show">
|
|
24
|
+
<buyer-intent-subject product-id="123"></buyer-intent-subject>
|
|
25
|
+
|
|
26
|
+
<h1>Acme CRM</h1>
|
|
27
|
+
<p>Product details here.</p>
|
|
28
|
+
|
|
29
|
+
<buyer-intent-click event-name="/leads/create">
|
|
30
|
+
<button>Get a Demo</button>
|
|
31
|
+
</buyer-intent-click>
|
|
32
|
+
</buyer-intent-view>
|
|
33
|
+
|
|
34
|
+
</buyer-intent-session>
|
|
39
35
|
```
|
|
40
36
|
|
|
41
|
-
|
|
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.
|
|
42
38
|
|
|
43
|
-
|
|
44
|
-
// app/api/activity/events/route.ts
|
|
45
|
-
import { createNextRouteHandler } from '@g2crowd/buyer-intent-provider-sdk/server';
|
|
39
|
+
## Elements
|
|
46
40
|
|
|
47
|
-
|
|
48
|
-
kafkaBrokers: [process.env.KAFKA_BROKER || 'localhost:9092'],
|
|
49
|
-
partnerId: process.env.PARTNER_ID,
|
|
50
|
-
});
|
|
41
|
+
### `<buyer-intent-session>`
|
|
51
42
|
|
|
52
|
-
|
|
43
|
+
Wraps a page (or your entire app) and provides config to all elements inside it. Does not fire any events itself.
|
|
44
|
+
|
|
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 |
|
|
51
|
+
|
|
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 |
|
|
58
|
+
|
|
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>
|
|
53
63
|
```
|
|
54
64
|
|
|
55
|
-
|
|
65
|
+
### `<buyer-intent-view>`
|
|
56
66
|
|
|
57
|
-
|
|
67
|
+
Fires a `$view` event when the element connects to the DOM. One event per page navigation.
|
|
58
68
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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) |
|
|
75
|
+
|
|
76
|
+
For pages with one product, you can put the ID directly on the view:
|
|
77
|
+
|
|
78
|
+
```html
|
|
79
|
+
<buyer-intent-view tag="products.show" product-id="123">
|
|
80
|
+
<h1>Acme CRM</h1>
|
|
81
|
+
</buyer-intent-view>
|
|
62
82
|
```
|
|
63
83
|
|
|
64
|
-
|
|
84
|
+
For pages with multiple products, use `<buyer-intent-subject>` children instead (see below).
|
|
65
85
|
|
|
66
|
-
-
|
|
67
|
-
- `PARTNER_ID`
|
|
68
|
-
- `TOPIC_PREFIX` (optional)
|
|
69
|
-
- `KAFKA_BROKERS` (comma-separated)
|
|
70
|
-
- `KAFKA_TOPIC` (optional override)
|
|
71
|
-
- `KAFKA_CLIENT_ID` (optional)
|
|
72
|
-
- `USE_DEV_LOGGER=true` (logs instead of Kafka)
|
|
86
|
+
### `<buyer-intent-subject>`
|
|
73
87
|
|
|
74
|
-
|
|
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.
|
|
75
89
|
|
|
76
|
-
|
|
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)|
|
|
77
96
|
|
|
78
|
-
|
|
79
|
-
- Topic name (scoped to their tenant)
|
|
80
|
-
- Auth mechanism (SASL user/pass or mTLS)
|
|
81
|
-
- TLS requirements (on/off, CA certs if needed)
|
|
97
|
+
A comparison page that references two products:
|
|
82
98
|
|
|
83
|
-
|
|
99
|
+
```html
|
|
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>
|
|
84
103
|
|
|
85
|
-
|
|
104
|
+
<h1>Acme CRM vs. Rival CRM</h1>
|
|
105
|
+
</buyer-intent-view>
|
|
106
|
+
```
|
|
86
107
|
|
|
87
|
-
|
|
88
|
-
// app/api/activity/events/route.ts
|
|
89
|
-
import { Kafka } from 'kafkajs';
|
|
90
|
-
import { createNextRouteHandler } from '@g2crowd/buyer-intent-provider-sdk/server';
|
|
108
|
+
The resulting event has `product_ids: [101, 201]`. If the view also has an inline `product-id`, they merge together without duplicates.
|
|
91
109
|
|
|
92
|
-
|
|
93
|
-
clientId: 'partner-app',
|
|
94
|
-
brokers: (process.env.KAFKA_BROKERS || '').split(','),
|
|
95
|
-
});
|
|
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:
|
|
96
111
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
112
|
+
```html
|
|
113
|
+
<buyer-intent-view tag="categories.show">
|
|
114
|
+
<buyer-intent-subject category-id="45"></buyer-intent-subject>
|
|
115
|
+
<h1>CRM Software</h1>
|
|
100
116
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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>
|
|
106
122
|
|
|
107
|
-
|
|
123
|
+
<div class="product-card">
|
|
124
|
+
<buyer-intent-subject product-id="201"></buyer-intent-subject>
|
|
125
|
+
<h2>Rival CRM</h2>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
</buyer-intent-view>
|
|
108
129
|
```
|
|
109
130
|
|
|
110
|
-
|
|
131
|
+
This fires one event: `category_ids: [45]`, `product_ids: [101, 201]`, `tag: "categories.show"`.
|
|
111
132
|
|
|
112
|
-
|
|
133
|
+
### `<buyer-intent-click>`
|
|
113
134
|
|
|
114
|
-
|
|
115
|
-
// app/api/activity/events/route.ts
|
|
116
|
-
import {
|
|
117
|
-
createNextRouteHandler,
|
|
118
|
-
createDevLoggerProducer,
|
|
119
|
-
} from '@g2crowd/buyer-intent-provider-sdk/server';
|
|
135
|
+
Fires an event when the user clicks anything inside it.
|
|
120
136
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
});
|
|
137
|
+
| Attribute | Description |
|
|
138
|
+
| ------------ | ------------------------ |
|
|
139
|
+
| `event-name` | Click event type |
|
|
125
140
|
|
|
126
|
-
|
|
141
|
+
```html
|
|
142
|
+
<buyer-intent-click event-name="/leads/create">
|
|
143
|
+
<button>Get a Demo</button>
|
|
144
|
+
</buyer-intent-click>
|
|
127
145
|
```
|
|
128
146
|
|
|
129
|
-
|
|
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.
|
|
130
148
|
|
|
131
|
-
|
|
149
|
+
## Full Example
|
|
132
150
|
|
|
133
|
-
|
|
151
|
+
Putting it all together — a product page with a session, view, subjects, and two click actions:
|
|
134
152
|
|
|
135
|
-
|
|
153
|
+
```html
|
|
154
|
+
<script type="module">
|
|
155
|
+
import '@g2crowd/buyer-intent-provider-sdk';
|
|
156
|
+
</script>
|
|
136
157
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
| `CategoryView` | `categoryId` | `categories.show` |
|
|
143
|
-
| `CompareView` | `productIds` (2+) | `comparisons.show` |
|
|
144
|
-
| `WriteReviewView` | `productId` | `reviewers.take_survey` |
|
|
158
|
+
<buyer-intent-session
|
|
159
|
+
origin="yoursite.com"
|
|
160
|
+
activity-endpoint="/api/activity/events"
|
|
161
|
+
user-type="standard"
|
|
162
|
+
>
|
|
145
163
|
|
|
146
|
-
|
|
147
|
-
|
|
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>
|
|
148
170
|
|
|
149
|
-
<
|
|
150
|
-
|
|
151
|
-
</BuyerIntent.ProfileView>
|
|
171
|
+
<h1>Acme CRM</h1>
|
|
172
|
+
<p>The best CRM for small teams.</p>
|
|
152
173
|
|
|
153
|
-
<
|
|
154
|
-
|
|
155
|
-
</
|
|
174
|
+
<buyer-intent-click event-name="/leads/create">
|
|
175
|
+
<button>Get a Demo</button>
|
|
176
|
+
</buyer-intent-click>
|
|
156
177
|
|
|
157
|
-
<
|
|
158
|
-
|
|
159
|
-
</
|
|
160
|
-
|
|
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>
|
|
161
182
|
|
|
162
|
-
|
|
183
|
+
</buyer-intent-session>
|
|
184
|
+
```
|
|
163
185
|
|
|
164
|
-
|
|
186
|
+
## React Support
|
|
165
187
|
|
|
166
|
-
|
|
167
|
-
| ----------------- | ------------- | --------------- |
|
|
168
|
-
| `AdClick` | `productId` | `/ad/clicked` |
|
|
169
|
-
| `LeadCreateClick` | `productId` | `/leads/create` |
|
|
188
|
+
Import from `/react` and use the same element hierarchy with camelCase props:
|
|
170
189
|
|
|
171
190
|
```tsx
|
|
172
|
-
|
|
173
|
-
<button>Get a Demo</button>
|
|
174
|
-
</BuyerIntent.LeadCreateClick>
|
|
191
|
+
import { BuyerIntent } from '@g2crowd/buyer-intent-provider-sdk/react';
|
|
175
192
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
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
|
+
}
|
|
179
209
|
```
|
|
180
210
|
|
|
181
|
-
|
|
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.
|
|
212
|
+
|
|
213
|
+
## Syntactic Sugar
|
|
182
214
|
|
|
183
|
-
|
|
215
|
+
For common page types, pre-built components hardcode the `tag` or `event-name` so you don't have to:
|
|
184
216
|
|
|
185
|
-
|
|
186
|
-
| ------------------ | ---------------------------------------- |
|
|
187
|
-
| `origin` | Partner hostname |
|
|
188
|
-
| `activityEndpoint` | URL to POST events to |
|
|
189
|
-
| `userType` | User type string (default: `"standard"`) |
|
|
190
|
-
| `distinctId` | Override the auto-generated visitor ID |
|
|
191
|
-
| `sourceLocation` | Controller/action identifier |
|
|
192
|
-
| `context` | Arbitrary metadata object |
|
|
193
|
-
| `eventName` | Override the default event name |
|
|
217
|
+
### Views
|
|
194
218
|
|
|
195
|
-
|
|
219
|
+
| Component | Tag | Required Prop |
|
|
220
|
+
| ----------------- | ----------------------- | ------------- |
|
|
221
|
+
| `ProfileView` | `products.show` | `productId` |
|
|
222
|
+
| `PricingView` | `products.pricing` | `productId` |
|
|
223
|
+
| `CompetitorsView` | `products.competitors` | `productId` |
|
|
224
|
+
| `CategoryView` | `categories.show` | `categoryId` |
|
|
225
|
+
| `CompareView` | `comparisons.show` | `productIds` |
|
|
226
|
+
| `WriteReviewView` | `reviewers.take_survey` | `productId` |
|
|
196
227
|
|
|
197
|
-
|
|
228
|
+
### Clicks
|
|
229
|
+
|
|
230
|
+
| Component | Event Name | Required Prop |
|
|
231
|
+
| ----------------- | --------------- | ------------- |
|
|
232
|
+
| `AdClick` | `/ad/clicked` | `productId` |
|
|
233
|
+
| `LeadCreateClick` | `/leads/create` | `productId` |
|
|
198
234
|
|
|
199
235
|
```tsx
|
|
200
|
-
|
|
201
|
-
tag="custom.page_type"
|
|
202
|
-
productIds={[123]}
|
|
203
|
-
origin="g2.com"
|
|
204
|
-
activityEndpoint="/api/activity/events"
|
|
205
|
-
>
|
|
206
|
-
<CustomPage />
|
|
207
|
-
</BuyerIntent.ViewTracker>
|
|
236
|
+
import { BuyerIntent } from '@g2crowd/buyer-intent-provider-sdk/react';
|
|
208
237
|
|
|
209
|
-
<BuyerIntent.
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
</
|
|
238
|
+
<BuyerIntent.Session origin="yoursite.com" activityEndpoint="/api/activity/events">
|
|
239
|
+
<BuyerIntent.ProfileView productId={123}>
|
|
240
|
+
<h1>Acme CRM</h1>
|
|
241
|
+
|
|
242
|
+
<BuyerIntent.LeadCreateClick productId={123}>
|
|
243
|
+
<button>Get a Demo</button>
|
|
244
|
+
</BuyerIntent.LeadCreateClick>
|
|
245
|
+
</BuyerIntent.ProfileView>
|
|
246
|
+
</BuyerIntent.Session>
|
|
215
247
|
```
|
|
216
248
|
|
|
217
|
-
|
|
249
|
+
These components still accept `origin`, `activityEndpoint`, `sourceLocation`, and `context` props for cases where you aren't using a session wrapper.
|
|
218
250
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
utm_campaign: 'spring_launch',
|
|
230
|
-
utm_term: 'buyer-intent',
|
|
231
|
-
utm_content: 'cta-button',
|
|
251
|
+
## Backend
|
|
252
|
+
|
|
253
|
+
### Next.js Route Handler
|
|
254
|
+
|
|
255
|
+
```ts
|
|
256
|
+
import { createNextRouteHandler } from '@g2crowd/buyer-intent-provider-sdk/server';
|
|
257
|
+
|
|
258
|
+
const POST = createNextRouteHandler({
|
|
259
|
+
kafkaBrokers: [process.env.KAFKA_BROKER || 'localhost:9092'],
|
|
260
|
+
partnerId: process.env.PARTNER_ID,
|
|
232
261
|
});
|
|
262
|
+
|
|
263
|
+
export { POST };
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Standalone Server
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
PARTNER_ID=partner-a KAFKA_BROKERS=broker1:9092,broker2:9092 \
|
|
270
|
+
buyer-intent-server
|
|
233
271
|
```
|
|
234
272
|
|
|
235
|
-
|
|
273
|
+
Environment variables: `PORT` (default 3000), `PARTNER_ID`, `KAFKA_BROKERS` (comma-separated), `TOPIC_PREFIX`, `KAFKA_TOPIC`, `KAFKA_CLIENT_ID`, `USE_DEV_LOGGER=true`.
|
|
236
274
|
|
|
237
|
-
###
|
|
275
|
+
### Custom Kafka Producer
|
|
238
276
|
|
|
239
|
-
|
|
277
|
+
```ts
|
|
278
|
+
import { Kafka } from 'kafkajs';
|
|
279
|
+
import { createNextRouteHandler } from '@g2crowd/buyer-intent-provider-sdk/server';
|
|
240
280
|
|
|
241
|
-
|
|
281
|
+
const kafka = new Kafka({
|
|
282
|
+
clientId: 'partner-app',
|
|
283
|
+
brokers: (process.env.KAFKA_BROKERS || '').split(','),
|
|
284
|
+
});
|
|
242
285
|
|
|
243
|
-
|
|
286
|
+
const POST = createNextRouteHandler({
|
|
287
|
+
producer: kafka.producer({ allowAutoTopicCreation: false }),
|
|
288
|
+
partnerId: process.env.PARTNER_ID,
|
|
289
|
+
});
|
|
244
290
|
|
|
245
|
-
|
|
291
|
+
export { POST };
|
|
292
|
+
```
|
|
246
293
|
|
|
247
|
-
Dev
|
|
294
|
+
### Dev Adapter (No Kafka)
|
|
248
295
|
|
|
249
|
-
|
|
296
|
+
```ts
|
|
297
|
+
import {
|
|
298
|
+
createNextRouteHandler,
|
|
299
|
+
createDevLoggerProducer,
|
|
300
|
+
} from '@g2crowd/buyer-intent-provider-sdk/server';
|
|
250
301
|
|
|
251
|
-
|
|
302
|
+
const POST = createNextRouteHandler({
|
|
303
|
+
producer: createDevLoggerProducer(),
|
|
304
|
+
partnerId: 'dev',
|
|
305
|
+
});
|
|
252
306
|
|
|
253
|
-
|
|
307
|
+
export { POST };
|
|
308
|
+
```
|
|
254
309
|
|
|
255
|
-
|
|
310
|
+
## Event Payload
|
|
256
311
|
|
|
257
312
|
```json
|
|
258
313
|
{
|
|
259
314
|
"name": "$view",
|
|
260
315
|
"properties": {
|
|
261
316
|
"product_ids": [123],
|
|
262
|
-
"category_ids": [
|
|
317
|
+
"category_ids": [45],
|
|
263
318
|
"tag": "products.show",
|
|
264
|
-
"url": "https://
|
|
319
|
+
"url": "https://yoursite.com/products/acme-crm",
|
|
265
320
|
"user_type": "standard",
|
|
266
321
|
"distinct_id": "visitor-uuid",
|
|
267
|
-
"origin": "
|
|
268
|
-
"source_location": "ProductsController#show"
|
|
269
|
-
"context": {
|
|
270
|
-
"page": "product"
|
|
271
|
-
}
|
|
322
|
+
"origin": "yoursite.com",
|
|
323
|
+
"source_location": "ProductsController#show"
|
|
272
324
|
},
|
|
273
325
|
"visit": {
|
|
274
326
|
"properties": {
|
|
275
|
-
"landing_page": "https://
|
|
276
|
-
"referrer": "https://
|
|
327
|
+
"landing_page": "https://yoursite.com/products/acme-crm",
|
|
328
|
+
"referrer": "https://google.com/",
|
|
277
329
|
"user_agent": "Mozilla/5.0",
|
|
278
|
-
"
|
|
279
|
-
"utm_source": "newsletter",
|
|
280
|
-
"utm_medium": "email",
|
|
281
|
-
"utm_campaign": "spring_launch",
|
|
282
|
-
"utm_term": "buyer-intent",
|
|
283
|
-
"utm_content": "cta-button"
|
|
330
|
+
"utm_source": "newsletter"
|
|
284
331
|
}
|
|
285
332
|
}
|
|
286
333
|
}
|
package/package.json
CHANGED
|
@@ -1,27 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@g2crowd/buyer-intent-provider-sdk",
|
|
3
|
-
"version": "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
|
-
"./
|
|
8
|
+
".": "./src/index.js",
|
|
9
|
+
"./react": "./src/react/index.js",
|
|
10
|
+
"./server": "./src/server/index.js"
|
|
10
11
|
},
|
|
11
|
-
"types": "index.d.ts",
|
|
12
|
+
"types": "src/index.d.ts",
|
|
12
13
|
"files": [
|
|
13
|
-
"
|
|
14
|
-
"index.d.ts",
|
|
15
|
-
"browser",
|
|
16
|
-
"server.js",
|
|
17
|
-
"server",
|
|
14
|
+
"src",
|
|
18
15
|
"README.md"
|
|
19
16
|
],
|
|
20
17
|
"scripts": {
|
|
21
18
|
"test": "node --experimental-vm-modules ./node_modules/.bin/jest --config ./jest.config.cjs"
|
|
22
19
|
},
|
|
23
20
|
"bin": {
|
|
24
|
-
"buyer-intent-server": "server.js"
|
|
21
|
+
"buyer-intent-server": "src/server.js"
|
|
25
22
|
},
|
|
26
23
|
"license": "MIT",
|
|
27
24
|
"repository": {
|
|
@@ -35,7 +32,17 @@
|
|
|
35
32
|
"kafkajs": "^2.2.4",
|
|
36
33
|
"react": ">=17"
|
|
37
34
|
},
|
|
38
|
-
"
|
|
35
|
+
"peerDependenciesMeta": {
|
|
36
|
+
"react": {
|
|
37
|
+
"optional": true
|
|
38
|
+
},
|
|
39
|
+
"kafkajs": {
|
|
40
|
+
"optional": true
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"sideEffects": [
|
|
44
|
+
"./src/browser/elements/*.js"
|
|
45
|
+
],
|
|
39
46
|
"devDependencies": {
|
|
40
47
|
"@testing-library/dom": "^9.3.4",
|
|
41
48
|
"@testing-library/react": "^14.3.1",
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export {
|
|
2
|
+
SessionProvider,
|
|
3
|
+
SubjectTracker,
|
|
4
|
+
ViewTracker,
|
|
5
|
+
ClickTracker,
|
|
6
|
+
} from './tracker.js';
|
|
7
|
+
import { SessionProvider, SubjectTracker, ViewTracker, ClickTracker } from './tracker.js';
|
|
8
|
+
import React from 'react';
|
|
9
|
+
|
|
10
|
+
function view(tag) {
|
|
11
|
+
return function ViewComponent({ children, ...rest }) {
|
|
12
|
+
return React.createElement(ViewTracker, { ...rest, tag }, children);
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function click(eventName) {
|
|
17
|
+
return function ClickComponent({ children, ...rest }) {
|
|
18
|
+
return React.createElement(ClickTracker, { ...rest, eventName }, children);
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const ProfileView = view('products.show');
|
|
23
|
+
export const PricingView = view('products.pricing');
|
|
24
|
+
export const CompetitorsView = view('products.competitors');
|
|
25
|
+
export const CategoryView = view('categories.show');
|
|
26
|
+
export const CompareView = view('comparisons.show');
|
|
27
|
+
export const WriteReviewView = view('reviewers.take_survey');
|
|
28
|
+
export const AdClick = click('/ad/clicked');
|
|
29
|
+
export const LeadCreateClick = click('/leads/create');
|