@journium/react 0.1.0-alpha.3 → 0.1.0-alpha.4
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/package.json +1 -1
- package/readme.md +197 -290
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -30,10 +30,12 @@ function Root() {
|
|
|
30
30
|
<JourniumProvider
|
|
31
31
|
config={{
|
|
32
32
|
token: "your-journium-token",
|
|
33
|
-
apiHost: "https://your-journium-instance.com"
|
|
34
|
-
|
|
33
|
+
apiHost: "https://your-journium-instance.com",
|
|
34
|
+
debug: true, // Optional: Enable debug logging
|
|
35
|
+
flushAt: 5, // Optional: Send events after 5 events
|
|
36
|
+
flushInterval: 10000 // Optional: Send events every 10 seconds
|
|
35
37
|
}}
|
|
36
|
-
autoCapture={true} // Enables auto-pageview and
|
|
38
|
+
autoCapture={true} // Enables auto-pageview and click tracking
|
|
37
39
|
>
|
|
38
40
|
<App />
|
|
39
41
|
</JourniumProvider>
|
|
@@ -43,20 +45,21 @@ function Root() {
|
|
|
43
45
|
export default Root;
|
|
44
46
|
```
|
|
45
47
|
|
|
46
|
-
###
|
|
48
|
+
### Track Custom Events
|
|
47
49
|
|
|
48
|
-
|
|
50
|
+
Use the `useTrackEvent` hook to track custom events:
|
|
49
51
|
|
|
50
52
|
```jsx
|
|
51
53
|
import React from 'react';
|
|
52
|
-
import {
|
|
54
|
+
import { useTrackEvent } from '@journium/react';
|
|
53
55
|
|
|
54
56
|
function SignupButton() {
|
|
55
|
-
const
|
|
57
|
+
const trackEvent = useTrackEvent();
|
|
56
58
|
|
|
57
59
|
const handleSignup = () => {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
trackEvent('user_signup', {
|
|
61
|
+
method: 'email',
|
|
62
|
+
source: 'landing_page',
|
|
60
63
|
plan: 'free'
|
|
61
64
|
});
|
|
62
65
|
// Your signup logic
|
|
@@ -66,71 +69,100 @@ function SignupButton() {
|
|
|
66
69
|
}
|
|
67
70
|
```
|
|
68
71
|
|
|
69
|
-
## 📖
|
|
72
|
+
## 📖 Tracking Hooks
|
|
70
73
|
|
|
71
|
-
###
|
|
74
|
+
### useTrackEvent - Track Custom Events
|
|
72
75
|
|
|
73
|
-
The
|
|
76
|
+
The primary hook for tracking custom business events:
|
|
74
77
|
|
|
75
78
|
```jsx
|
|
76
|
-
|
|
77
|
-
token="your-token" // Required: Your project token
|
|
78
|
-
apiHost="https://api.journium.com" // Required: API endpoint
|
|
79
|
-
debug={false} // Optional: Enable debug mode
|
|
80
|
-
flushAt={20} // Optional: Flush after N events
|
|
81
|
-
flushInterval={10000} // Optional: Flush interval (ms)
|
|
82
|
-
autocapture={true} // Optional: Enable auto-capture
|
|
83
|
-
sessionTimeout={1800000} // Optional: Session timeout (30m)
|
|
84
|
-
>
|
|
85
|
-
<YourApp />
|
|
86
|
-
</JourniumProvider>
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### useJournium Hook
|
|
90
|
-
|
|
91
|
-
Access Journium functionality throughout your React app:
|
|
92
|
-
|
|
93
|
-
```jsx
|
|
94
|
-
import { useJournium } from '@journium/react';
|
|
79
|
+
import { useTrackEvent } from '@journium/react';
|
|
95
80
|
|
|
96
|
-
function
|
|
97
|
-
const
|
|
81
|
+
function EcommerceComponent() {
|
|
82
|
+
const trackEvent = useTrackEvent();
|
|
98
83
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
84
|
+
const handlePurchase = () => {
|
|
85
|
+
trackEvent('purchase_completed', {
|
|
86
|
+
product_id: 'prod_123',
|
|
87
|
+
price: 29.99,
|
|
88
|
+
currency: 'USD',
|
|
89
|
+
category: 'electronics'
|
|
104
90
|
});
|
|
105
91
|
};
|
|
106
92
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
93
|
+
const handleAddToCart = () => {
|
|
94
|
+
trackEvent('product_added_to_cart', {
|
|
95
|
+
product_id: 'prod_123',
|
|
96
|
+
quantity: 1,
|
|
97
|
+
source: 'product_page'
|
|
112
98
|
});
|
|
113
99
|
};
|
|
114
100
|
|
|
115
|
-
// Control auto-capture
|
|
116
|
-
const toggleTracking = () => {
|
|
117
|
-
if (trackingEnabled) {
|
|
118
|
-
stopAutoCapture();
|
|
119
|
-
} else {
|
|
120
|
-
startAutoCapture();
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
|
-
|
|
124
101
|
return (
|
|
125
102
|
<div>
|
|
126
|
-
<button onClick={
|
|
127
|
-
<button onClick={
|
|
128
|
-
<button onClick={toggleTracking}>Toggle Tracking</button>
|
|
103
|
+
<button onClick={handleAddToCart}>Add to Cart</button>
|
|
104
|
+
<button onClick={handlePurchase}>Buy Now</button>
|
|
129
105
|
</div>
|
|
130
106
|
);
|
|
131
107
|
}
|
|
132
108
|
```
|
|
133
109
|
|
|
110
|
+
### useTrackPageview - Manual Pageview Tracking
|
|
111
|
+
|
|
112
|
+
For tracking custom pageviews beyond automatic route tracking:
|
|
113
|
+
|
|
114
|
+
```jsx
|
|
115
|
+
import { useTrackPageview } from '@journium/react';
|
|
116
|
+
|
|
117
|
+
function CustomPageTracker() {
|
|
118
|
+
const trackPageview = useTrackPageview();
|
|
119
|
+
|
|
120
|
+
const handleSpecialPageview = () => {
|
|
121
|
+
trackPageview({
|
|
122
|
+
page_type: 'modal',
|
|
123
|
+
content_type: 'pricing_calculator',
|
|
124
|
+
user_segment: 'premium'
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
return (
|
|
129
|
+
<button onClick={handleSpecialPageview}>
|
|
130
|
+
Track Modal View
|
|
131
|
+
</button>
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### useAutoTrackPageview - Automatic Pageview on Mount
|
|
137
|
+
|
|
138
|
+
Automatically track pageviews when components mount or dependencies change:
|
|
139
|
+
|
|
140
|
+
```jsx
|
|
141
|
+
import { useAutoTrackPageview } from '@journium/react';
|
|
142
|
+
|
|
143
|
+
function ProductPage({ productId, category }) {
|
|
144
|
+
// Tracks pageview when component mounts or productId changes
|
|
145
|
+
useAutoTrackPageview([productId], {
|
|
146
|
+
page_type: 'product_detail',
|
|
147
|
+
product_id: productId,
|
|
148
|
+
category: category
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
return <div>Product {productId}</div>;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function BlogPost({ postId }) {
|
|
155
|
+
// Track pageview for blog posts
|
|
156
|
+
useAutoTrackPageview([postId], {
|
|
157
|
+
page_type: 'blog_post',
|
|
158
|
+
post_id: postId,
|
|
159
|
+
content_type: 'article'
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
return <article>Blog post content</article>;
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
134
166
|
## 🔧 Advanced Usage
|
|
135
167
|
|
|
136
168
|
### Form Tracking
|
|
@@ -138,27 +170,27 @@ function MyComponent() {
|
|
|
138
170
|
Track form interactions and submissions:
|
|
139
171
|
|
|
140
172
|
```jsx
|
|
141
|
-
import {
|
|
173
|
+
import { useTrackEvent } from '@journium/react';
|
|
142
174
|
|
|
143
175
|
function ContactForm() {
|
|
144
|
-
const
|
|
176
|
+
const trackEvent = useTrackEvent();
|
|
145
177
|
|
|
146
178
|
const handleSubmit = (e) => {
|
|
147
179
|
e.preventDefault();
|
|
148
180
|
|
|
149
|
-
|
|
181
|
+
trackEvent('form_submitted', {
|
|
150
182
|
form_name: 'contact',
|
|
151
183
|
form_type: 'lead_generation',
|
|
152
|
-
|
|
184
|
+
fields_completed: ['name', 'email', 'company']
|
|
153
185
|
});
|
|
154
186
|
|
|
155
187
|
// Submit form logic
|
|
156
188
|
};
|
|
157
189
|
|
|
158
|
-
const handleFieldChange = (
|
|
159
|
-
|
|
190
|
+
const handleFieldChange = (fieldName) => {
|
|
191
|
+
trackEvent('form_field_completed', {
|
|
160
192
|
form_name: 'contact',
|
|
161
|
-
field_name:
|
|
193
|
+
field_name: fieldName
|
|
162
194
|
});
|
|
163
195
|
};
|
|
164
196
|
|
|
@@ -180,174 +212,96 @@ function ContactForm() {
|
|
|
180
212
|
}
|
|
181
213
|
```
|
|
182
214
|
|
|
183
|
-
###
|
|
215
|
+
### User Journey Tracking
|
|
184
216
|
|
|
185
|
-
Track
|
|
217
|
+
Track multi-step user flows:
|
|
186
218
|
|
|
187
219
|
```jsx
|
|
188
|
-
import {
|
|
220
|
+
import { useTrackEvent, useTrackPageview } from '@journium/react';
|
|
189
221
|
|
|
190
|
-
function
|
|
191
|
-
const
|
|
222
|
+
function OnboardingFlow({ step }) {
|
|
223
|
+
const trackEvent = useTrackEvent();
|
|
224
|
+
const trackPageview = useTrackPageview();
|
|
192
225
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
currency: 'USD'
|
|
226
|
+
useEffect(() => {
|
|
227
|
+
// Track onboarding step pageview
|
|
228
|
+
trackPageview({
|
|
229
|
+
page_type: 'onboarding',
|
|
230
|
+
step: step,
|
|
231
|
+
flow: 'user_setup'
|
|
200
232
|
});
|
|
201
|
-
};
|
|
233
|
+
}, [step, trackPageview]);
|
|
202
234
|
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
products: orderData.items.map(item => ({
|
|
209
|
-
product_id: item.id,
|
|
210
|
-
quantity: item.quantity,
|
|
211
|
-
price: item.price
|
|
212
|
-
}))
|
|
235
|
+
const handleStepComplete = () => {
|
|
236
|
+
trackEvent('onboarding_step_completed', {
|
|
237
|
+
step: step,
|
|
238
|
+
time_spent: Date.now() - stepStartTime,
|
|
239
|
+
completed_successfully: true
|
|
213
240
|
});
|
|
214
241
|
};
|
|
215
242
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
<button onClick={handleAddToCart}>Add to Cart</button>
|
|
221
|
-
</div>
|
|
222
|
-
);
|
|
223
|
-
}
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
### React Router Integration
|
|
227
|
-
|
|
228
|
-
Track page navigation automatically:
|
|
229
|
-
|
|
230
|
-
```jsx
|
|
231
|
-
import { useEffect } from 'react';
|
|
232
|
-
import { useLocation } from 'react-router-dom';
|
|
233
|
-
import { useJournium } from '@journium/react';
|
|
234
|
-
|
|
235
|
-
function PageTracker() {
|
|
236
|
-
const location = useLocation();
|
|
237
|
-
const { capturePageview } = useJournium();
|
|
238
|
-
|
|
239
|
-
useEffect(() => {
|
|
240
|
-
capturePageview({
|
|
241
|
-
path: location.pathname,
|
|
242
|
-
search: location.search,
|
|
243
|
-
referrer: document.referrer
|
|
243
|
+
const handleSkipStep = () => {
|
|
244
|
+
trackEvent('onboarding_step_skipped', {
|
|
245
|
+
step: step,
|
|
246
|
+
reason: 'user_choice'
|
|
244
247
|
});
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
return null;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// Add to your router setup
|
|
251
|
-
function App() {
|
|
252
|
-
return (
|
|
253
|
-
<Router>
|
|
254
|
-
<PageTracker />
|
|
255
|
-
<Routes>
|
|
256
|
-
{/* Your routes */}
|
|
257
|
-
</Routes>
|
|
258
|
-
</Router>
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
### Conditional Tracking
|
|
264
|
-
|
|
265
|
-
Control tracking based on user preferences or environment:
|
|
266
|
-
|
|
267
|
-
```jsx
|
|
268
|
-
import { useJournium } from '@journium/react';
|
|
269
|
-
|
|
270
|
-
function ConditionalTracker() {
|
|
271
|
-
const { track, startAutoCapture, stopAutoCapture } = useJournium();
|
|
272
|
-
const [hasConsent, setHasConsent] = useState(false);
|
|
273
|
-
|
|
274
|
-
useEffect(() => {
|
|
275
|
-
if (hasConsent) {
|
|
276
|
-
startAutoCapture();
|
|
277
|
-
track('tracking_consent_given');
|
|
278
|
-
} else {
|
|
279
|
-
stopAutoCapture();
|
|
280
|
-
}
|
|
281
|
-
}, [hasConsent, startAutoCapture, stopAutoCapture, track]);
|
|
248
|
+
};
|
|
282
249
|
|
|
283
250
|
return (
|
|
284
251
|
<div>
|
|
285
|
-
<
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
checked={hasConsent}
|
|
289
|
-
onChange={(e) => setHasConsent(e.target.checked)}
|
|
290
|
-
/>
|
|
291
|
-
Allow analytics tracking
|
|
292
|
-
</label>
|
|
252
|
+
<h2>Step {step}</h2>
|
|
253
|
+
<button onClick={handleStepComplete}>Complete Step</button>
|
|
254
|
+
<button onClick={handleSkipStep}>Skip</button>
|
|
293
255
|
</div>
|
|
294
256
|
);
|
|
295
257
|
}
|
|
296
258
|
```
|
|
297
259
|
|
|
298
|
-
###
|
|
260
|
+
### Feature Usage Tracking
|
|
299
261
|
|
|
300
|
-
Create reusable tracking
|
|
262
|
+
Create reusable tracking patterns:
|
|
301
263
|
|
|
302
264
|
```jsx
|
|
303
|
-
import {
|
|
304
|
-
|
|
305
|
-
function useUserActions() {
|
|
306
|
-
const { track } = useJournium();
|
|
265
|
+
import { useTrackEvent } from '@journium/react';
|
|
307
266
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
selected_plan: plan,
|
|
312
|
-
timestamp: new Date().toISOString()
|
|
313
|
-
});
|
|
314
|
-
};
|
|
267
|
+
// Custom hook for feature tracking
|
|
268
|
+
function useFeatureTracking() {
|
|
269
|
+
const trackEvent = useTrackEvent();
|
|
315
270
|
|
|
316
|
-
const
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
timestamp: new Date().toISOString()
|
|
271
|
+
const trackFeatureUsed = (featureName, context = {}) => {
|
|
272
|
+
trackEvent('feature_used', {
|
|
273
|
+
feature_name: featureName,
|
|
274
|
+
timestamp: new Date().toISOString(),
|
|
275
|
+
...context
|
|
320
276
|
});
|
|
321
277
|
};
|
|
322
278
|
|
|
323
|
-
const
|
|
324
|
-
|
|
325
|
-
feature_name:
|
|
326
|
-
|
|
327
|
-
timestamp: new Date().toISOString()
|
|
279
|
+
const trackFeatureDiscovered = (featureName, discoveryMethod) => {
|
|
280
|
+
trackEvent('feature_discovered', {
|
|
281
|
+
feature_name: featureName,
|
|
282
|
+
discovery_method: discoveryMethod
|
|
328
283
|
});
|
|
329
284
|
};
|
|
330
285
|
|
|
331
|
-
return {
|
|
332
|
-
trackSignup,
|
|
333
|
-
trackLogin,
|
|
334
|
-
trackFeatureUsed
|
|
335
|
-
};
|
|
286
|
+
return { trackFeatureUsed, trackFeatureDiscovered };
|
|
336
287
|
}
|
|
337
288
|
|
|
338
289
|
// Usage in components
|
|
339
|
-
function
|
|
340
|
-
const {
|
|
290
|
+
function AdvancedFeature() {
|
|
291
|
+
const { trackFeatureUsed, trackFeatureDiscovered } = useFeatureTracking();
|
|
341
292
|
|
|
342
|
-
const
|
|
343
|
-
|
|
344
|
-
|
|
293
|
+
const handleFeatureClick = () => {
|
|
294
|
+
trackFeatureUsed('advanced_search', {
|
|
295
|
+
search_type: 'filters',
|
|
296
|
+
filter_count: 3
|
|
297
|
+
});
|
|
345
298
|
};
|
|
346
299
|
|
|
347
300
|
return (
|
|
348
301
|
<div>
|
|
349
|
-
<button onClick={
|
|
350
|
-
|
|
302
|
+
<button onClick={handleFeatureClick}>
|
|
303
|
+
Use Advanced Search
|
|
304
|
+
</button>
|
|
351
305
|
</div>
|
|
352
306
|
);
|
|
353
307
|
}
|
|
@@ -357,41 +311,43 @@ function LoginForm() {
|
|
|
357
311
|
|
|
358
312
|
### User Consent Management
|
|
359
313
|
|
|
314
|
+
Control tracking based on user consent:
|
|
315
|
+
|
|
360
316
|
```jsx
|
|
361
317
|
import { useState, useEffect } from 'react';
|
|
362
|
-
import {
|
|
318
|
+
import { useAutocapture } from '@journium/react';
|
|
363
319
|
|
|
364
|
-
function
|
|
365
|
-
const {
|
|
366
|
-
const [
|
|
320
|
+
function ConsentBanner() {
|
|
321
|
+
const { startAutocapture, stopAutocapture } = useAutocapture();
|
|
322
|
+
const [hasConsent, setHasConsent] = useState(null);
|
|
323
|
+
|
|
324
|
+
useEffect(() => {
|
|
325
|
+
const savedConsent = localStorage.getItem('tracking_consent');
|
|
326
|
+
if (savedConsent === 'true') {
|
|
327
|
+
setHasConsent(true);
|
|
328
|
+
startAutocapture();
|
|
329
|
+
} else if (savedConsent === 'false') {
|
|
330
|
+
setHasConsent(false);
|
|
331
|
+
stopAutocapture();
|
|
332
|
+
}
|
|
333
|
+
}, [startAutocapture, stopAutocapture]);
|
|
367
334
|
|
|
368
335
|
const handleAccept = () => {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
336
|
+
setHasConsent(true);
|
|
337
|
+
localStorage.setItem('tracking_consent', 'true');
|
|
338
|
+
startAutocapture();
|
|
372
339
|
};
|
|
373
340
|
|
|
374
341
|
const handleDecline = () => {
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
342
|
+
setHasConsent(false);
|
|
343
|
+
localStorage.setItem('tracking_consent', 'false');
|
|
344
|
+
stopAutocapture();
|
|
378
345
|
};
|
|
379
346
|
|
|
380
|
-
|
|
381
|
-
const consent = localStorage.getItem('journium_consent');
|
|
382
|
-
if (consent === 'false') {
|
|
383
|
-
stopAutoCapture();
|
|
384
|
-
setShowBanner(false);
|
|
385
|
-
} else if (consent === 'true') {
|
|
386
|
-
startAutoCapture();
|
|
387
|
-
setShowBanner(false);
|
|
388
|
-
}
|
|
389
|
-
}, [startAutoCapture, stopAutoCapture]);
|
|
390
|
-
|
|
391
|
-
if (!showBanner) return null;
|
|
347
|
+
if (hasConsent !== null) return null;
|
|
392
348
|
|
|
393
349
|
return (
|
|
394
|
-
<div className="
|
|
350
|
+
<div className="consent-banner">
|
|
395
351
|
<p>We use analytics to improve your experience.</p>
|
|
396
352
|
<button onClick={handleAccept}>Accept</button>
|
|
397
353
|
<button onClick={handleDecline}>Decline</button>
|
|
@@ -402,21 +358,20 @@ function PrivacyBanner() {
|
|
|
402
358
|
|
|
403
359
|
### Excluding Sensitive Data
|
|
404
360
|
|
|
361
|
+
Configure autocapture to ignore sensitive elements:
|
|
362
|
+
|
|
405
363
|
```jsx
|
|
406
364
|
<JourniumProvider
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
'input[type="password"]',
|
|
416
|
-
|
|
417
|
-
'.credit-card-input',
|
|
418
|
-
'[data-private]'
|
|
419
|
-
]
|
|
365
|
+
config={{
|
|
366
|
+
token: "your-token",
|
|
367
|
+
apiHost: "https://api.journium.com",
|
|
368
|
+
autocapture: {
|
|
369
|
+
captureClicks: true,
|
|
370
|
+
captureFormSubmits: true,
|
|
371
|
+
captureFormChanges: false,
|
|
372
|
+
ignoreClasses: ['no-track', 'sensitive', 'pii'],
|
|
373
|
+
ignoreElements: ['input[type="password"]', '.credit-card']
|
|
374
|
+
}
|
|
420
375
|
}}
|
|
421
376
|
>
|
|
422
377
|
<App />
|
|
@@ -428,84 +383,36 @@ function PrivacyBanner() {
|
|
|
428
383
|
Full TypeScript support with complete type definitions:
|
|
429
384
|
|
|
430
385
|
```typescript
|
|
431
|
-
import {
|
|
386
|
+
import { useTrackEvent, JourniumConfig } from '@journium/react';
|
|
432
387
|
|
|
433
|
-
interface
|
|
388
|
+
interface PurchaseEventProperties {
|
|
434
389
|
product_id: string;
|
|
435
390
|
category: string;
|
|
436
391
|
price: number;
|
|
392
|
+
currency: string;
|
|
437
393
|
}
|
|
438
394
|
|
|
439
395
|
function TypedComponent() {
|
|
440
|
-
const
|
|
396
|
+
const trackEvent = useTrackEvent();
|
|
441
397
|
|
|
442
|
-
const handlePurchase = () => {
|
|
398
|
+
const handlePurchase = (productData: PurchaseEventProperties) => {
|
|
443
399
|
// Fully typed event tracking
|
|
444
|
-
|
|
445
|
-
product_id: 'prod_123',
|
|
446
|
-
category: 'electronics',
|
|
447
|
-
price: 299.99
|
|
448
|
-
} as CustomEventProperties);
|
|
400
|
+
trackEvent('product_purchased', productData);
|
|
449
401
|
};
|
|
450
402
|
|
|
451
403
|
return <button onClick={handlePurchase}>Purchase</button>;
|
|
452
404
|
}
|
|
453
|
-
|
|
454
|
-
// Type-safe provider configuration
|
|
455
|
-
const config: JourniumConfig = {
|
|
456
|
-
token: 'your-token',
|
|
457
|
-
apiHost: 'https://api.journium.com',
|
|
458
|
-
autocapture: {
|
|
459
|
-
captureClicks: true,
|
|
460
|
-
captureFormSubmits: true,
|
|
461
|
-
ignoreClasses: ['no-track']
|
|
462
|
-
}
|
|
463
|
-
};
|
|
464
405
|
```
|
|
465
406
|
|
|
466
|
-
##
|
|
407
|
+
## 🔗 Available Hooks
|
|
467
408
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
})));
|
|
476
|
-
|
|
477
|
-
function App() {
|
|
478
|
-
return (
|
|
479
|
-
<Suspense fallback={<div>Loading...</div>}>
|
|
480
|
-
<JourniumProvider token="your-token" apiHost="https://api.journium.com">
|
|
481
|
-
<YourApp />
|
|
482
|
-
</JourniumProvider>
|
|
483
|
-
</Suspense>
|
|
484
|
-
);
|
|
485
|
-
}
|
|
486
|
-
```
|
|
487
|
-
|
|
488
|
-
### Event Batching
|
|
489
|
-
|
|
490
|
-
```jsx
|
|
491
|
-
import { useJournium } from '@journium/react';
|
|
492
|
-
|
|
493
|
-
function BatchedTracking() {
|
|
494
|
-
const { track, flush } = useJournium();
|
|
495
|
-
|
|
496
|
-
const handleMultipleActions = async () => {
|
|
497
|
-
// Queue multiple events
|
|
498
|
-
track('action_1', { step: 1 });
|
|
499
|
-
track('action_2', { step: 2 });
|
|
500
|
-
track('action_3', { step: 3 });
|
|
501
|
-
|
|
502
|
-
// Force flush all queued events
|
|
503
|
-
await flush();
|
|
504
|
-
};
|
|
505
|
-
|
|
506
|
-
return <button onClick={handleMultipleActions}>Complete Flow</button>;
|
|
507
|
-
}
|
|
508
|
-
```
|
|
409
|
+
| Hook | Purpose | Usage |
|
|
410
|
+
|------|---------|-------|
|
|
411
|
+
| `useTrackEvent()` | Track custom events | `trackEvent('event_name', properties)` |
|
|
412
|
+
| `useTrackPageview()` | Manual pageview tracking | `trackPageview(properties)` |
|
|
413
|
+
| `useAutoTrackPageview(deps, props)` | Automatic pageview on mount | Auto-tracks when deps change |
|
|
414
|
+
| `useAutocapture()` | Control autocapture | `{ startAutocapture, stopAutocapture }` |
|
|
415
|
+
| `useJournium()` | Direct Journium instance access | Advanced use cases only |
|
|
509
416
|
|
|
510
417
|
## 🔗 Related Packages
|
|
511
418
|
|