shopkit-analytics 1.0.2 → 1.0.3

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.
Files changed (53) hide show
  1. package/README.md +35 -100
  2. package/dist/adapters/index.d.mts +2 -1
  3. package/dist/adapters/index.d.ts +2 -1
  4. package/dist/adapters/index.js +230 -64
  5. package/dist/adapters/index.js.map +1 -1
  6. package/dist/adapters/index.mjs +3 -1
  7. package/dist/chunk-4RDPDMGW.mjs +68 -0
  8. package/dist/chunk-4RDPDMGW.mjs.map +1 -0
  9. package/dist/chunk-NC25KOAF.mjs +156 -0
  10. package/dist/chunk-NC25KOAF.mjs.map +1 -0
  11. package/dist/chunk-NGPUKV7E.mjs +46 -0
  12. package/dist/chunk-NGPUKV7E.mjs.map +1 -0
  13. package/dist/{chunk-U3UOXFS4.mjs → chunk-NJQ2MOM2.mjs} +206 -116
  14. package/dist/chunk-NJQ2MOM2.mjs.map +1 -0
  15. package/dist/chunk-NKDB4KX2.mjs +2 -0
  16. package/dist/chunk-NKDB4KX2.mjs.map +1 -0
  17. package/dist/{chunk-BNV3EVHH.mjs → chunk-QCS5UARA.mjs} +2 -2
  18. package/dist/events/index.js +218 -54
  19. package/dist/events/index.js.map +1 -1
  20. package/dist/events/index.mjs +9 -7
  21. package/dist/experiment/index.d.mts +25 -0
  22. package/dist/experiment/index.d.ts +25 -0
  23. package/dist/experiment/index.js +74 -0
  24. package/dist/experiment/index.js.map +1 -0
  25. package/dist/experiment/index.mjs +15 -0
  26. package/dist/experiment/index.mjs.map +1 -0
  27. package/dist/{index-DS9OI5Mz.d.ts → index-D_8w5bL_.d.ts} +13 -0
  28. package/dist/{index-Bym1_EAp.d.mts → index-th6sBtE3.d.mts} +13 -0
  29. package/dist/index.d.mts +6 -2
  30. package/dist/index.d.ts +6 -2
  31. package/dist/index.js +400 -64
  32. package/dist/index.js.map +1 -1
  33. package/dist/index.mjs +30 -7
  34. package/dist/index.mjs.map +1 -1
  35. package/dist/services/index.d.mts +51 -0
  36. package/dist/services/index.d.ts +51 -0
  37. package/dist/services/index.js +180 -0
  38. package/dist/services/index.js.map +1 -0
  39. package/dist/services/index.mjs +11 -0
  40. package/dist/services/index.mjs.map +1 -0
  41. package/dist/types-C__2IBCj.d.mts +7 -0
  42. package/dist/types-C__2IBCj.d.ts +7 -0
  43. package/dist/utils/index.d.mts +19 -0
  44. package/dist/utils/index.d.ts +19 -0
  45. package/dist/utils/index.js +93 -0
  46. package/dist/utils/index.js.map +1 -0
  47. package/dist/utils/index.mjs +12 -0
  48. package/dist/utils/index.mjs.map +1 -0
  49. package/package.json +19 -1
  50. package/templates/nextjs/README.md +206 -0
  51. package/templates/nextjs/api-events-route.ts +62 -0
  52. package/dist/chunk-U3UOXFS4.mjs.map +0 -1
  53. /package/dist/{chunk-BNV3EVHH.mjs.map → chunk-QCS5UARA.mjs.map} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shopkit-analytics",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "A comprehensive analytics package combining event tracking and affiliate tracking for e-commerce applications with multiple platform adapters",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -21,11 +21,26 @@
21
21
  "import": "./dist/affiliate/index.mjs",
22
22
  "require": "./dist/affiliate/index.js"
23
23
  },
24
+ "./experiment": {
25
+ "types": "./dist/experiment/index.d.ts",
26
+ "import": "./dist/experiment/index.mjs",
27
+ "require": "./dist/experiment/index.js"
28
+ },
24
29
  "./adapters": {
25
30
  "types": "./dist/adapters/index.d.ts",
26
31
  "import": "./dist/adapters/index.mjs",
27
32
  "require": "./dist/adapters/index.js"
28
33
  },
34
+ "./services": {
35
+ "types": "./dist/services/index.d.ts",
36
+ "import": "./dist/services/index.mjs",
37
+ "require": "./dist/services/index.js"
38
+ },
39
+ "./utils": {
40
+ "types": "./dist/utils/index.d.ts",
41
+ "import": "./dist/utils/index.mjs",
42
+ "require": "./dist/utils/index.js"
43
+ },
29
44
  "./types": {
30
45
  "types": "./dist/types.d.ts",
31
46
  "import": "./dist/types.mjs",
@@ -34,6 +49,7 @@
34
49
  },
35
50
  "files": [
36
51
  "dist",
52
+ "templates",
37
53
  "README.md",
38
54
  "LICENSE"
39
55
  ],
@@ -55,6 +71,8 @@
55
71
  "tracking",
56
72
  "events",
57
73
  "affiliate",
74
+ "experiment",
75
+ "ab-testing",
58
76
  "utm",
59
77
  "google-analytics",
60
78
  "facebook-pixel",
@@ -0,0 +1,206 @@
1
+ # Facebook CAPI Setup Guide for Next.js
2
+
3
+ This guide helps you set up Facebook Conversions API (CAPI) server-side tracking with the @shopkit/analytics package.
4
+
5
+ ## Quick Setup
6
+
7
+ ### 1. Environment Variables
8
+
9
+ Add these to your `.env.local` file:
10
+
11
+ ```bash
12
+ # Required for Facebook CAPI
13
+ FACEBOOK_CAPI_ACCESS_TOKEN="your_facebook_access_token"
14
+ NEXT_PUBLIC_PIXEL_ID="123456789"
15
+
16
+ # Optional (for testing)
17
+ FACEBOOK_TEST_EVENT_CODE="TEST12345"
18
+ ```
19
+
20
+ ### 2. Create API Route
21
+
22
+ **For Next.js App Router (app directory):**
23
+
24
+ Create `app/api/events/route.ts` and copy the contents from `api-events-route.ts` in this directory.
25
+
26
+ **For Next.js Pages Router (pages directory):**
27
+
28
+ Create `pages/api/events.ts`:
29
+
30
+ ```typescript
31
+ import { createFacebookCAPIService } from "@shopkit/analytics/services";
32
+ import { TEvent } from "@shopkit/analytics/types";
33
+ import type { NextApiRequest, NextApiResponse } from "next";
34
+
35
+ function getClientIpAddress(req: NextApiRequest): string | undefined {
36
+ const forwarded = req.headers["x-forwarded-for"];
37
+ const realIp = req.headers["x-real-ip"];
38
+ const cfConnectingIp = req.headers["cf-connecting-ip"];
39
+
40
+ if (typeof forwarded === "string") {
41
+ return forwarded.split(",")[0];
42
+ }
43
+ if (typeof realIp === "string") {
44
+ return realIp;
45
+ }
46
+ if (typeof cfConnectingIp === "string") {
47
+ return cfConnectingIp;
48
+ }
49
+ return undefined;
50
+ }
51
+
52
+ export default async function handler(
53
+ req: NextApiRequest,
54
+ res: NextApiResponse
55
+ ) {
56
+ if (req.method !== "POST") {
57
+ return res.status(405).json({ error: "Method not allowed" });
58
+ }
59
+
60
+ try {
61
+ const { events, userInfo } = req.body;
62
+
63
+ if (!Array.isArray(events) || events.length === 0) {
64
+ return res.status(400).json({ error: "Invalid events data" });
65
+ }
66
+
67
+ const capiService = createFacebookCAPIService({
68
+ accessToken: process.env.FACEBOOK_CAPI_ACCESS_TOKEN!,
69
+ pixelId: process.env.NEXT_PUBLIC_PIXEL_ID!,
70
+ testEventCode: process.env.FACEBOOK_TEST_EVENT_CODE,
71
+ });
72
+
73
+ if (!capiService) {
74
+ console.warn("Facebook CAPI service not available - missing configuration");
75
+ return res.status(500).json({ error: "CAPI service not configured" });
76
+ }
77
+
78
+ const enhancedUserInfo = {
79
+ ...userInfo,
80
+ clientIpAddress: getClientIpAddress(req),
81
+ };
82
+
83
+ await capiService.sendEvents(events as TEvent[], enhancedUserInfo);
84
+
85
+ return res.json({
86
+ success: true,
87
+ message: `Successfully sent ${events.length} events to Facebook CAPI`,
88
+ });
89
+ } catch (error) {
90
+ console.error("API Events Error:", error);
91
+ return res.status(500).json({ error: "Failed to process events" });
92
+ }
93
+ }
94
+ ```
95
+
96
+ ### 3. CAPI Configuration (Enabled by Default)
97
+
98
+ ```typescript
99
+ import { ShopkitAnalytics } from "@shopkit/analytics";
100
+
101
+ <ShopkitAnalytics
102
+ config={{
103
+ facebookPixel: {
104
+ pixelId: process.env.NEXT_PUBLIC_PIXEL_ID!,
105
+ // enableCAPI: true, // Default: enabled for better data reliability
106
+ // enableCAPI: false, // Uncomment to disable server-side tracking
107
+ },
108
+ }}
109
+ >
110
+ <YourApp />
111
+ </ShopkitAnalytics>
112
+ ```
113
+
114
+ **Important**: CAPI is **enabled by default** to provide better data reliability and privacy compliance. The system will gracefully handle cases where the API endpoint is not set up - client-side tracking will continue to work normally.
115
+
116
+ ## Getting Facebook Access Token
117
+
118
+ 1. Go to [Facebook Business Manager](https://business.facebook.com/)
119
+ 2. Navigate to **Business Settings** → **System Users**
120
+ 3. Create a new system user or select existing one
121
+ 4. Generate an access token with these permissions:
122
+ - `ads_management`
123
+ - `business_management`
124
+ 5. Copy the access token to your environment variables
125
+
126
+ ## Testing
127
+
128
+ ### Development Testing
129
+
130
+ 1. Set the test event code in your environment:
131
+ ```bash
132
+ FACEBOOK_TEST_EVENT_CODE="TEST12345"
133
+ ```
134
+
135
+ 2. Trigger some events in your app
136
+
137
+ 3. Check Facebook Events Manager → Test Events to see if events are received
138
+
139
+ ### Production Verification
140
+
141
+ 1. Remove or comment out `FACEBOOK_TEST_EVENT_CODE`
142
+ 2. Monitor Facebook Events Manager for real events
143
+ 3. Check your server logs for any CAPI errors
144
+
145
+ ## Troubleshooting
146
+
147
+ ### Common Issues
148
+
149
+ 1. **"CAPI service not configured"**
150
+ - Ensure `FACEBOOK_CAPI_ACCESS_TOKEN` and `NEXT_PUBLIC_PIXEL_ID` are set
151
+ - Verify environment variables are loaded correctly
152
+
153
+ 2. **"Method not allowed" (Pages Router)**
154
+ - Ensure you're using POST requests
155
+ - Check the API route is created correctly
156
+
157
+ 3. **Events not appearing in Facebook**
158
+ - Verify your access token has correct permissions
159
+ - Check if test event code is set (events go to Test Events tool)
160
+ - Monitor server logs for error messages
161
+
162
+ 4. **CORS errors**
163
+ - API route should be on the same domain as your app
164
+ - Next.js API routes handle CORS automatically
165
+
166
+ ### Debug Logging
167
+
168
+ Enable debug logging to see detailed information:
169
+
170
+ ```typescript
171
+ <ShopkitAnalytics
172
+ config={{
173
+ logger: {
174
+ enabled: true,
175
+ level: "debug",
176
+ prettyPrint: true,
177
+ },
178
+ facebookPixel: {
179
+ pixelId: process.env.NEXT_PUBLIC_PIXEL_ID!,
180
+ enableCAPI: true,
181
+ },
182
+ }}
183
+ />
184
+ ```
185
+
186
+ ## How It Works
187
+
188
+ 1. **Event Triggered**: User performs an action (add to cart, etc.)
189
+ 2. **Dual Tracking**: Event sent to both client-side pixel and server-side CAPI (enabled by default)
190
+ 3. **Event ID**: Unique ID prevents double counting
191
+ 4. **Enhanced Data**: Automatically includes experiment and affiliate data
192
+ 5. **Deduplication**: Facebook uses event ID to merge client/server events
193
+ 6. **Graceful Fallback**: If API endpoint is missing, only client-side tracking runs (no errors)
194
+
195
+ ### Default Behavior
196
+
197
+ - **CAPI is enabled by default** for all Facebook Pixel configurations
198
+ - **No setup required** for basic client-side tracking
199
+ - **API endpoint optional** - system works without it (client-side only)
200
+ - **Better data quality** when API endpoint is properly configured
201
+
202
+ ## Support
203
+
204
+ - Check the main package README for more details
205
+ - Monitor browser console and server logs for errors
206
+ - Use Facebook's Test Events tool during development
@@ -0,0 +1,62 @@
1
+ import { createFacebookCAPIService } from "@shopkit/analytics/services";
2
+ import { TEvent } from "@shopkit/analytics/types";
3
+
4
+ /**
5
+ * Get client IP address from request headers
6
+ */
7
+ function getClientIpAddress(request: Request): string | undefined {
8
+ // Try different headers for IP address
9
+ const forwarded = request.headers.get("x-forwarded-for");
10
+ const realIp = request.headers.get("x-real-ip");
11
+ const cfConnectingIp = request.headers.get("cf-connecting-ip");
12
+
13
+ return forwarded?.split(",")[0] || realIp || cfConnectingIp || undefined;
14
+ }
15
+
16
+ export async function POST(request: Request) {
17
+ try {
18
+ const { events, userInfo } = await request.json();
19
+
20
+ // Validate events array
21
+ if (!Array.isArray(events) || events.length === 0) {
22
+ return Response.json({ error: "Invalid events data" }, { status: 400 });
23
+ }
24
+
25
+ // Create CAPI service with explicit configuration
26
+ const capiService = createFacebookCAPIService({
27
+ accessToken: process.env.FACEBOOK_CAPI_ACCESS_TOKEN!,
28
+ pixelId: process.env.NEXT_PUBLIC_PIXEL_ID!,
29
+ testEventCode: process.env.FACEBOOK_TEST_EVENT_CODE,
30
+ });
31
+
32
+ if (!capiService) {
33
+ console.warn(
34
+ "Facebook CAPI service not available - missing configuration"
35
+ );
36
+ return Response.json(
37
+ { error: "CAPI service not configured" },
38
+ { status: 500 }
39
+ );
40
+ }
41
+
42
+ // Enhance user info with server-side data
43
+ const enhancedUserInfo = {
44
+ ...userInfo,
45
+ clientIpAddress: getClientIpAddress(request),
46
+ };
47
+
48
+ // Send events to Facebook CAPI
49
+ await capiService.sendEvents(events as TEvent[], enhancedUserInfo);
50
+
51
+ return Response.json({
52
+ success: true,
53
+ message: `Successfully sent ${events.length} events to Facebook CAPI`,
54
+ });
55
+ } catch (error) {
56
+ console.error("API Events Error:", error);
57
+ return Response.json(
58
+ { error: "Failed to process events" },
59
+ { status: 500 }
60
+ );
61
+ }
62
+ }