@journium/react 0.1.0-alpha.3 → 0.1.0-alpha.5

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
@@ -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
- // autocapture: true by default - no need to specify unless disabling
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 triggers autocapture
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
- ### Using the Hook
48
+ ### Track Custom Events
47
49
 
48
- Track events anywhere in your components:
50
+ Use the `useTrackEvent` hook to track custom events:
49
51
 
50
52
  ```jsx
51
53
  import React from 'react';
52
- import { useJournium } from '@journium/react';
54
+ import { useTrackEvent } from '@journium/react';
53
55
 
54
56
  function SignupButton() {
55
- const { track } = useJournium();
57
+ const trackEvent = useTrackEvent();
56
58
 
57
59
  const handleSignup = () => {
58
- track('signup_attempted', {
59
- source: 'homepage',
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,161 @@ function SignupButton() {
66
69
  }
67
70
  ```
68
71
 
69
- ## 📖 API Reference
72
+ ## 📖 Tracking Hooks
70
73
 
71
- ### JourniumProvider
74
+ ### useTrackEvent - Track Custom Events
72
75
 
73
- The main provider component that initializes Journium for your React app.
76
+ The primary hook for tracking custom business events:
74
77
 
75
78
  ```jsx
76
- <JourniumProvider
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>
79
+ import { useTrackEvent } from '@journium/react';
80
+
81
+ function EcommerceComponent() {
82
+ const trackEvent = useTrackEvent();
83
+
84
+ const handlePurchase = () => {
85
+ trackEvent('purchase_completed', {
86
+ product_id: 'prod_123',
87
+ price: 29.99,
88
+ currency: 'USD',
89
+ category: 'electronics'
90
+ });
91
+ };
92
+
93
+ const handleAddToCart = () => {
94
+ trackEvent('product_added_to_cart', {
95
+ product_id: 'prod_123',
96
+ quantity: 1,
97
+ source: 'product_page'
98
+ });
99
+ };
100
+
101
+ return (
102
+ <div>
103
+ <button onClick={handleAddToCart}>Add to Cart</button>
104
+ <button onClick={handlePurchase}>Buy Now</button>
105
+ </div>
106
+ );
107
+ }
87
108
  ```
88
109
 
89
- ### useJournium Hook
110
+ ### useIdentify - User Identification
90
111
 
91
- Access Journium functionality throughout your React app:
112
+ Use this hook to identify users when they log in or sign up. This should be used instead of tracking user login as a custom event.
92
113
 
93
114
  ```jsx
94
- import { useJournium } from '@journium/react';
95
-
96
- function MyComponent() {
97
- const { track, capturePageview, startAutoCapture, stopAutoCapture, flush } = useJournium();
115
+ import { useIdentify } from '@journium/react';
98
116
 
99
- // Track events
100
- const handleClick = () => {
101
- track('button_clicked', {
102
- button_id: 'cta-primary',
103
- page: 'pricing'
104
- });
117
+ function LoginForm() {
118
+ const identify = useIdentify();
119
+
120
+ const handleLogin = async (email, password) => {
121
+ try {
122
+ const user = await loginUser(email, password);
123
+
124
+ // Identify the user after successful login
125
+ identify(user.id, {
126
+ name: user.name,
127
+ email: user.email,
128
+ });
129
+
130
+ // Redirect to dashboard or show success
131
+ } catch (error) {
132
+ // Handle login error
133
+ }
105
134
  };
106
135
 
107
- // Manual pageview
108
- const handleNavigate = () => {
109
- capturePageview({
110
- previous_page: '/home',
111
- user_type: 'premium'
112
- });
113
- };
136
+ return (
137
+ <form onSubmit={handleLogin}>
138
+ {/* Login form fields */}
139
+ </form>
140
+ );
141
+ }
142
+ ```
114
143
 
115
- // Control auto-capture
116
- const toggleTracking = () => {
117
- if (trackingEnabled) {
118
- stopAutoCapture();
119
- } else {
120
- startAutoCapture();
144
+ ### useReset - User Logout
145
+
146
+ Use this hook to reset user identity when they log out:
147
+
148
+ ```jsx
149
+ import { useReset } from '@journium/react';
150
+
151
+ function LogoutButton() {
152
+ const reset = useReset();
153
+
154
+ const handleLogout = async () => {
155
+ try {
156
+ await logoutUser();
157
+
158
+ // Reset user identity after successful logout
159
+ reset();
160
+
161
+ // Redirect to home or login page
162
+ } catch (error) {
163
+ // Handle logout error
121
164
  }
122
165
  };
123
166
 
167
+ return <button onClick={handleLogout}>Log Out</button>;
168
+ }
169
+ ```
170
+
171
+ ### useTrackPageview - Manual Pageview Tracking
172
+
173
+ For tracking custom pageviews beyond automatic route tracking:
174
+
175
+ ```jsx
176
+ import { useTrackPageview } from '@journium/react';
177
+
178
+ function CustomPageTracker() {
179
+ const trackPageview = useTrackPageview();
180
+
181
+ const handleSpecialPageview = () => {
182
+ trackPageview({
183
+ page_type: 'modal',
184
+ content_type: 'pricing_calculator',
185
+ user_segment: 'premium'
186
+ });
187
+ };
188
+
124
189
  return (
125
- <div>
126
- <button onClick={handleClick}>Track Click</button>
127
- <button onClick={handleNavigate}>Manual Pageview</button>
128
- <button onClick={toggleTracking}>Toggle Tracking</button>
129
- </div>
190
+ <button onClick={handleSpecialPageview}>
191
+ Track Modal View
192
+ </button>
130
193
  );
131
194
  }
132
195
  ```
133
196
 
197
+ ### useAutoTrackPageview - Automatic Pageview on Mount
198
+
199
+ Automatically track pageviews when components mount or dependencies change:
200
+
201
+ ```jsx
202
+ import { useAutoTrackPageview } from '@journium/react';
203
+
204
+ function ProductPage({ productId, category }) {
205
+ // Tracks pageview when component mounts or productId changes
206
+ useAutoTrackPageview([productId], {
207
+ page_type: 'product_detail',
208
+ product_id: productId,
209
+ category: category
210
+ });
211
+
212
+ return <div>Product {productId}</div>;
213
+ }
214
+
215
+ function BlogPost({ postId }) {
216
+ // Track pageview for blog posts
217
+ useAutoTrackPageview([postId], {
218
+ page_type: 'blog_post',
219
+ post_id: postId,
220
+ content_type: 'article'
221
+ });
222
+
223
+ return <article>Blog post content</article>;
224
+ }
225
+ ```
226
+
134
227
  ## 🔧 Advanced Usage
135
228
 
136
229
  ### Form Tracking
@@ -138,27 +231,27 @@ function MyComponent() {
138
231
  Track form interactions and submissions:
139
232
 
140
233
  ```jsx
141
- import { useJournium } from '@journium/react';
234
+ import { useTrackEvent } from '@journium/react';
142
235
 
143
236
  function ContactForm() {
144
- const { track } = useJournium();
237
+ const trackEvent = useTrackEvent();
145
238
 
146
239
  const handleSubmit = (e) => {
147
240
  e.preventDefault();
148
241
 
149
- track('form_submitted', {
242
+ trackEvent('form_submitted', {
150
243
  form_name: 'contact',
151
244
  form_type: 'lead_generation',
152
- fields_filled: ['name', 'email', 'company']
245
+ fields_completed: ['name', 'email', 'company']
153
246
  });
154
247
 
155
248
  // Submit form logic
156
249
  };
157
250
 
158
- const handleFieldChange = (field) => {
159
- track('form_field_changed', {
251
+ const handleFieldChange = (fieldName) => {
252
+ trackEvent('form_field_completed', {
160
253
  form_name: 'contact',
161
- field_name: field
254
+ field_name: fieldName
162
255
  });
163
256
  };
164
257
 
@@ -180,174 +273,96 @@ function ContactForm() {
180
273
  }
181
274
  ```
182
275
 
183
- ### E-commerce Tracking
276
+ ### User Journey Tracking
184
277
 
185
- Track purchase flows and product interactions:
278
+ Track multi-step user flows:
186
279
 
187
280
  ```jsx
188
- import { useJournium } from '@journium/react';
281
+ import { useTrackEvent, useTrackPageview } from '@journium/react';
189
282
 
190
- function ProductPage({ product }) {
191
- const { track } = useJournium();
283
+ function OnboardingFlow({ step }) {
284
+ const trackEvent = useTrackEvent();
285
+ const trackPageview = useTrackPageview();
192
286
 
193
- const handleAddToCart = () => {
194
- track('product_added_to_cart', {
195
- product_id: product.id,
196
- product_name: product.name,
197
- category: product.category,
198
- price: product.price,
199
- currency: 'USD'
287
+ useEffect(() => {
288
+ // Track onboarding step pageview
289
+ trackPageview({
290
+ page_type: 'onboarding',
291
+ step: step,
292
+ flow: 'user_setup'
200
293
  });
201
- };
294
+ }, [step, trackPageview]);
202
295
 
203
- const handlePurchase = (orderData) => {
204
- track('purchase_completed', {
205
- order_id: orderData.id,
206
- revenue: orderData.total,
207
- currency: 'USD',
208
- products: orderData.items.map(item => ({
209
- product_id: item.id,
210
- quantity: item.quantity,
211
- price: item.price
212
- }))
296
+ const handleStepComplete = () => {
297
+ trackEvent('onboarding_step_completed', {
298
+ step: step,
299
+ time_spent: Date.now() - stepStartTime,
300
+ completed_successfully: true
213
301
  });
214
302
  };
215
303
 
216
- return (
217
- <div>
218
- <h1>{product.name}</h1>
219
- <p>${product.price}</p>
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
304
+ const handleSkipStep = () => {
305
+ trackEvent('onboarding_step_skipped', {
306
+ step: step,
307
+ reason: 'user_choice'
244
308
  });
245
- }, [location, capturePageview]);
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]);
309
+ };
282
310
 
283
311
  return (
284
312
  <div>
285
- <label>
286
- <input
287
- type="checkbox"
288
- checked={hasConsent}
289
- onChange={(e) => setHasConsent(e.target.checked)}
290
- />
291
- Allow analytics tracking
292
- </label>
313
+ <h2>Step {step}</h2>
314
+ <button onClick={handleStepComplete}>Complete Step</button>
315
+ <button onClick={handleSkipStep}>Skip</button>
293
316
  </div>
294
317
  );
295
318
  }
296
319
  ```
297
320
 
298
- ### Custom Hook for User Actions
321
+ ### Feature Usage Tracking
299
322
 
300
- Create reusable tracking hooks:
323
+ Create reusable tracking patterns:
301
324
 
302
325
  ```jsx
303
- import { useJournium } from '@journium/react';
304
-
305
- function useUserActions() {
306
- const { track } = useJournium();
326
+ import { useTrackEvent } from '@journium/react';
307
327
 
308
- const trackSignup = (method, plan) => {
309
- track('user_signup', {
310
- signup_method: method,
311
- selected_plan: plan,
312
- timestamp: new Date().toISOString()
313
- });
314
- };
328
+ // Custom hook for feature tracking
329
+ function useFeatureTracking() {
330
+ const trackEvent = useTrackEvent();
315
331
 
316
- const trackLogin = (method) => {
317
- track('user_login', {
318
- login_method: method,
319
- timestamp: new Date().toISOString()
332
+ const trackFeatureUsed = (featureName, context = {}) => {
333
+ trackEvent('feature_used', {
334
+ feature_name: featureName,
335
+ timestamp: new Date().toISOString(),
336
+ ...context
320
337
  });
321
338
  };
322
339
 
323
- const trackFeatureUsed = (feature, context = {}) => {
324
- track('feature_used', {
325
- feature_name: feature,
326
- ...context,
327
- timestamp: new Date().toISOString()
340
+ const trackFeatureDiscovered = (featureName, discoveryMethod) => {
341
+ trackEvent('feature_discovered', {
342
+ feature_name: featureName,
343
+ discovery_method: discoveryMethod
328
344
  });
329
345
  };
330
346
 
331
- return {
332
- trackSignup,
333
- trackLogin,
334
- trackFeatureUsed
335
- };
347
+ return { trackFeatureUsed, trackFeatureDiscovered };
336
348
  }
337
349
 
338
350
  // Usage in components
339
- function LoginForm() {
340
- const { trackLogin } = useUserActions();
351
+ function AdvancedFeature() {
352
+ const { trackFeatureUsed, trackFeatureDiscovered } = useFeatureTracking();
341
353
 
342
- const handleLogin = (method) => {
343
- trackLogin(method);
344
- // Login logic
354
+ const handleFeatureClick = () => {
355
+ trackFeatureUsed('advanced_search', {
356
+ search_type: 'filters',
357
+ filter_count: 3
358
+ });
345
359
  };
346
360
 
347
361
  return (
348
362
  <div>
349
- <button onClick={() => handleLogin('email')}>Login with Email</button>
350
- <button onClick={() => handleLogin('google')}>Login with Google</button>
363
+ <button onClick={handleFeatureClick}>
364
+ Use Advanced Search
365
+ </button>
351
366
  </div>
352
367
  );
353
368
  }
@@ -357,41 +372,43 @@ function LoginForm() {
357
372
 
358
373
  ### User Consent Management
359
374
 
375
+ Control tracking based on user consent:
376
+
360
377
  ```jsx
361
378
  import { useState, useEffect } from 'react';
362
- import { useJournium } from '@journium/react';
379
+ import { useAutocapture } from '@journium/react';
363
380
 
364
- function PrivacyBanner() {
365
- const { startAutoCapture, stopAutoCapture, flush } = useJournium();
366
- const [showBanner, setShowBanner] = useState(true);
381
+ function ConsentBanner() {
382
+ const { startAutocapture, stopAutocapture } = useAutocapture();
383
+ const [hasConsent, setHasConsent] = useState(null);
384
+
385
+ useEffect(() => {
386
+ const savedConsent = localStorage.getItem('tracking_consent');
387
+ if (savedConsent === 'true') {
388
+ setHasConsent(true);
389
+ startAutocapture();
390
+ } else if (savedConsent === 'false') {
391
+ setHasConsent(false);
392
+ stopAutocapture();
393
+ }
394
+ }, [startAutocapture, stopAutocapture]);
367
395
 
368
396
  const handleAccept = () => {
369
- localStorage.setItem('journium_consent', 'true');
370
- setShowBanner(false);
371
- startAutoCapture();
397
+ setHasConsent(true);
398
+ localStorage.setItem('tracking_consent', 'true');
399
+ startAutocapture();
372
400
  };
373
401
 
374
402
  const handleDecline = () => {
375
- localStorage.setItem('journium_consent', 'false');
376
- setShowBanner(false);
377
- stopAutoCapture();
403
+ setHasConsent(false);
404
+ localStorage.setItem('tracking_consent', 'false');
405
+ stopAutocapture();
378
406
  };
379
407
 
380
- useEffect(() => {
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;
408
+ if (hasConsent !== null) return null;
392
409
 
393
410
  return (
394
- <div className="privacy-banner">
411
+ <div className="consent-banner">
395
412
  <p>We use analytics to improve your experience.</p>
396
413
  <button onClick={handleAccept}>Accept</button>
397
414
  <button onClick={handleDecline}>Decline</button>
@@ -402,21 +419,20 @@ function PrivacyBanner() {
402
419
 
403
420
  ### Excluding Sensitive Data
404
421
 
422
+ Configure autocapture to ignore sensitive elements:
423
+
405
424
  ```jsx
406
425
  <JourniumProvider
407
- token="your-token"
408
- apiHost="https://api.journium.com"
409
- autocapture={{
410
- captureClicks: true,
411
- captureFormSubmits: true,
412
- captureFormChanges: false,
413
- ignoreClasses: ['no-track', 'sensitive', 'pii'],
414
- ignoreElements: [
415
- 'input[type="password"]',
416
- 'input[type="email"]',
417
- '.credit-card-input',
418
- '[data-private]'
419
- ]
426
+ config={{
427
+ token: "your-token",
428
+ apiHost: "https://api.journium.com",
429
+ autocapture: {
430
+ captureClicks: true,
431
+ captureFormSubmits: true,
432
+ captureFormChanges: false,
433
+ ignoreClasses: ['no-track', 'sensitive', 'pii'],
434
+ ignoreElements: ['input[type="password"]', '.credit-card']
435
+ }
420
436
  }}
421
437
  >
422
438
  <App />
@@ -428,84 +444,38 @@ function PrivacyBanner() {
428
444
  Full TypeScript support with complete type definitions:
429
445
 
430
446
  ```typescript
431
- import { useJournium, JourniumConfig } from '@journium/react';
447
+ import { useTrackEvent, JourniumConfig } from '@journium/react';
432
448
 
433
- interface CustomEventProperties {
449
+ interface PurchaseEventProperties {
434
450
  product_id: string;
435
451
  category: string;
436
452
  price: number;
453
+ currency: string;
437
454
  }
438
455
 
439
456
  function TypedComponent() {
440
- const { track } = useJournium();
457
+ const trackEvent = useTrackEvent();
441
458
 
442
- const handlePurchase = () => {
459
+ const handlePurchase = (productData: PurchaseEventProperties) => {
443
460
  // Fully typed event tracking
444
- track('product_purchased', {
445
- product_id: 'prod_123',
446
- category: 'electronics',
447
- price: 299.99
448
- } as CustomEventProperties);
461
+ trackEvent('product_purchased', productData);
449
462
  };
450
463
 
451
464
  return <button onClick={handlePurchase}>Purchase</button>;
452
465
  }
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
- ```
465
-
466
- ## ⚡ Performance Optimization
467
-
468
- ### Lazy Loading
469
-
470
- ```jsx
471
- import { lazy, Suspense } from 'react';
472
-
473
- const JourniumProvider = lazy(() => import('@journium/react').then(module => ({
474
- default: module.JourniumProvider
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
466
  ```
487
467
 
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
- ```
468
+ ## 🔗 Available Hooks
469
+
470
+ | Hook | Purpose | Usage |
471
+ |------|---------|-------|
472
+ | `useTrackEvent()` | Track custom events | `trackEvent('event_name', properties)` |
473
+ | `useIdentify()` | Identify users on login/signup | `identify(distinctId, attributes)` |
474
+ | `useReset()` | Reset user identity on logout | `reset()` |
475
+ | `useTrackPageview()` | Manual pageview tracking | `trackPageview(properties)` |
476
+ | `useAutoTrackPageview(deps, props)` | Automatic pageview on mount | Auto-tracks when deps change |
477
+ | `useAutocapture()` | Control autocapture | `{ startAutocapture, stopAutocapture }` |
478
+ | `useJournium()` | Direct Journium instance access | Advanced use cases only |
509
479
 
510
480
  ## 🔗 Related Packages
511
481