@traffical/react 0.6.5 → 0.6.7
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 +19 -15
- package/dist/context.d.ts +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ function App() {
|
|
|
24
24
|
orgId: 'org_123',
|
|
25
25
|
projectId: 'proj_456',
|
|
26
26
|
env: 'production',
|
|
27
|
-
apiKey: '
|
|
27
|
+
apiKey: 'traffical_pk_…',
|
|
28
28
|
}}
|
|
29
29
|
>
|
|
30
30
|
<MyComponent />
|
|
@@ -298,7 +298,7 @@ That's it. Default tracking is enabled automatically, and `track` knows which de
|
|
|
298
298
|
|
|
299
299
|
### `useTraffical(options)`
|
|
300
300
|
|
|
301
|
-
The primary hook for parameter resolution and
|
|
301
|
+
The primary hook for parameter resolution and event tracking.
|
|
302
302
|
|
|
303
303
|
```tsx
|
|
304
304
|
const { params, decision, ready, error, trackExposure, track } = useTraffical({
|
|
@@ -347,7 +347,7 @@ function Dashboard() {
|
|
|
347
347
|
|
|
348
348
|
### 2. A/B Test with Conversion Tracking
|
|
349
349
|
|
|
350
|
-
Test different
|
|
350
|
+
Test different allocations and measure which performs better.
|
|
351
351
|
|
|
352
352
|
```tsx
|
|
353
353
|
function PricingPage() {
|
|
@@ -484,7 +484,7 @@ function ProductDetails({ productId, defaultPrice }: Props) {
|
|
|
484
484
|
|
|
485
485
|
### 6. Component with Self-Contained Parameters
|
|
486
486
|
|
|
487
|
-
Reusable component that owns its
|
|
487
|
+
Reusable component that owns its parameter surface.
|
|
488
488
|
|
|
489
489
|
```tsx
|
|
490
490
|
function CheckoutButton({ onCheckout }: { onCheckout: () => void }) {
|
|
@@ -712,12 +712,12 @@ function ConnectedPricingSection() {
|
|
|
712
712
|
### 1. Always Provide Sensible Defaults
|
|
713
713
|
|
|
714
714
|
Defaults are used when:
|
|
715
|
-
- No
|
|
715
|
+
- No policy is running
|
|
716
716
|
- User doesn't match targeting conditions
|
|
717
717
|
- SDK is still loading
|
|
718
718
|
|
|
719
719
|
```tsx
|
|
720
|
-
// ✅ Good: Works without any
|
|
720
|
+
// ✅ Good: Works without any policy
|
|
721
721
|
const { params } = useTraffical({
|
|
722
722
|
defaults: {
|
|
723
723
|
"pricing.discount": 0,
|
|
@@ -725,7 +725,7 @@ const { params } = useTraffical({
|
|
|
725
725
|
},
|
|
726
726
|
});
|
|
727
727
|
|
|
728
|
-
// ❌ Bad: Undefined behavior without
|
|
728
|
+
// ❌ Bad: Undefined behavior without a policy
|
|
729
729
|
const { params } = useTraffical({
|
|
730
730
|
defaults: {
|
|
731
731
|
"pricing.discount": undefined, // What does this mean?
|
|
@@ -754,7 +754,7 @@ const discount = useTraffical({ defaults: { "pricing.discount": 0 } });
|
|
|
754
754
|
|
|
755
755
|
### 3. Track Events at Conversion Points
|
|
756
756
|
|
|
757
|
-
Events enable Traffical to learn which
|
|
757
|
+
Events enable Traffical to learn which allocations perform best. Use the bound `track` from `useTraffical()` — it automatically includes the `decisionId`.
|
|
758
758
|
|
|
759
759
|
```tsx
|
|
760
760
|
const { params, track } = useTraffical({
|
|
@@ -801,9 +801,9 @@ category.subcategory.name
|
|
|
801
801
|
|
|
802
802
|
feature.* → Feature flags (boolean)
|
|
803
803
|
ui.* → Visual variations (string, number)
|
|
804
|
-
pricing.* → Pricing
|
|
804
|
+
pricing.* → Pricing policies (number)
|
|
805
805
|
copy.* → Copywriting tests (string)
|
|
806
|
-
experiment.* → Explicit
|
|
806
|
+
experiment.* → Explicit allocations (string)
|
|
807
807
|
```
|
|
808
808
|
|
|
809
809
|
### 5. Handle Loading State
|
|
@@ -828,7 +828,7 @@ return <Hero variant={params["ui.heroVariant"]} />;
|
|
|
828
828
|
|
|
829
829
|
## Flicker-Free SSR (Next.js App Router)
|
|
830
830
|
|
|
831
|
-
The classic A/B testing problem: users briefly see the default content before it switches to their assigned
|
|
831
|
+
The classic A/B testing problem: users briefly see the default content before it switches to their assigned allocation. This section shows how to eliminate that flicker entirely.
|
|
832
832
|
|
|
833
833
|
### The Problem
|
|
834
834
|
|
|
@@ -949,12 +949,16 @@ import configBundle from '@/data/config-bundle.json';
|
|
|
949
949
|
export const trafficalConfig = {
|
|
950
950
|
orgId: process.env.NEXT_PUBLIC_TRAFFICAL_ORG_ID,
|
|
951
951
|
projectId: process.env.NEXT_PUBLIC_TRAFFICAL_PROJECT_ID,
|
|
952
|
-
apiKey: process.env.
|
|
952
|
+
apiKey: process.env.NEXT_PUBLIC_TRAFFICAL_PUBLISHABLE_KEY,
|
|
953
953
|
// This is the key to flicker-free SSR!
|
|
954
954
|
localConfig: configBundle as ConfigBundle,
|
|
955
955
|
};
|
|
956
956
|
```
|
|
957
957
|
|
|
958
|
+
> **Use a publishable key here.** `NEXT_PUBLIC_*` variables are inlined into the
|
|
959
|
+
> client bundle, so this must be a `traffical_pk_…` key — never the server key
|
|
960
|
+
> (`traffical_sk_…`), which grants access to your full ruleset.
|
|
961
|
+
|
|
958
962
|
#### Step 5: TrafficalWrapper Uses UserId
|
|
959
963
|
|
|
960
964
|
```tsx
|
|
@@ -985,7 +989,7 @@ Request Flow (First Visit):
|
|
|
985
989
|
3. Server layout reads userId from HEADER
|
|
986
990
|
4. Server passes userId to React via props
|
|
987
991
|
5. useTraffical's useState resolves from localConfig + userId
|
|
988
|
-
6. Server renders HTML with CORRECT
|
|
992
|
+
6. Server renders HTML with CORRECT allocation
|
|
989
993
|
7. Response sent with Set-Cookie header
|
|
990
994
|
8. Client hydrates with SAME userId → NO FLICKER ✅
|
|
991
995
|
─────────────────────────────────────────────────────────────────
|
|
@@ -1009,7 +1013,7 @@ Subsequent Requests:
|
|
|
1009
1013
|
|
|
1010
1014
|
### What This Solves
|
|
1011
1015
|
|
|
1012
|
-
- ✅ **First page load** - No flicker, correct
|
|
1016
|
+
- ✅ **First page load** - No flicker, correct allocation from the start
|
|
1013
1017
|
- ✅ **Client-side navigation** - Already worked (bundle cached)
|
|
1014
1018
|
- ✅ **Page refresh** - UserId persisted in cookie
|
|
1015
1019
|
- ✅ **New users** - UserId generated on first request
|
|
@@ -1024,7 +1028,7 @@ No. The SDK fetches the config bundle once and caches it. All resolution happens
|
|
|
1024
1028
|
|
|
1025
1029
|
**Q: What happens if the SDK fails to load?**
|
|
1026
1030
|
|
|
1027
|
-
Defaults are returned. Your app works normally, just without
|
|
1031
|
+
Defaults are returned. Your app works normally, just without experimentation.
|
|
1028
1032
|
|
|
1029
1033
|
**Q: Should I use `tracking: "none"` for SSR?**
|
|
1030
1034
|
|
package/dist/context.d.ts
CHANGED
|
@@ -44,7 +44,7 @@ export interface TrafficalProviderConfig {
|
|
|
44
44
|
decisionDeduplicationTtlMs?: number;
|
|
45
45
|
/**
|
|
46
46
|
* Exposure deduplication session TTL in milliseconds (default: 30 minutes).
|
|
47
|
-
* Same user seeing same
|
|
47
|
+
* Same user seeing the same allocation won't trigger multiple exposure events.
|
|
48
48
|
*/
|
|
49
49
|
exposureSessionTtlMs?: number;
|
|
50
50
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@traffical/react",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.7",
|
|
4
4
|
"description": "Traffical SDK for React - Provider and hooks for parameter resolution",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
"typecheck": "tsc --noEmit"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@traffical/core": "0.12.
|
|
26
|
-
"@traffical/js-client": "0.
|
|
25
|
+
"@traffical/core": "0.12.1",
|
|
26
|
+
"@traffical/js-client": "0.19.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@happy-dom/global-registrator": "^15",
|