Skip to content

Commit b45c0e4

Browse files
committed
feat: pixel tracking
1 parent 9954cae commit b45c0e4

File tree

6 files changed

+85
-7
lines changed

6 files changed

+85
-7
lines changed

packages/tracker/src/core/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export type TrackerOptions = {
1919
trackInteractions?: boolean;
2020
trackErrors?: boolean;
2121
ignoreBotDetection?: boolean;
22+
usePixel?: boolean;
2223

2324
// Sampling & Retries
2425
samplingRate?: number;

packages/tracker/src/core/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export function getTrackerConfig(): TrackerOptions {
7272
} catch (_e) {
7373
value = [];
7474
}
75-
} else if (value === 'true') {
75+
} else if (value === 'true' || value === '') {
7676
value = true;
7777
} else if (value === 'false') {
7878
value = false;

packages/tracker/src/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { TrackerOptions } from "./core/types";
33
import { generateUUIDv4, getTrackerConfig, isOptedOut } from "./core/utils";
44
import { initErrorTracking } from "./plugins/errors";
55
import { initInteractionTracking } from "./plugins/interactions";
6+
import { initPixelTracking } from "./plugins/pixel";
67
import { initScrollDepthTracking } from "./plugins/scroll-depth";
78
import { initWebVitalsTracking } from "./plugins/vitals";
89

@@ -19,6 +20,10 @@ export class Databuddy extends BaseTracker {
1920
}
2021

2122
if (!this.isServer()) {
23+
if (this.options.usePixel) {
24+
initPixelTracking(this);
25+
}
26+
2227
if (this.options.trackScreenViews) {
2328
this.trackScreenViews();
2429
setTimeout(() => this.screenView(), 0);
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import type { BaseTracker } from "../core/tracker";
2+
3+
export function initPixelTracking(tracker: BaseTracker) {
4+
tracker.options.enableBatching = false;
5+
6+
const sendToPixel = (endpoint: string, data: any): Promise<any> => {
7+
const params = new URLSearchParams();
8+
9+
const flatten = (obj: any, prefix = "") => {
10+
for (const key in obj) {
11+
if (Object.hasOwn(obj, key)) {
12+
const value = obj[key];
13+
const newKey = prefix ? `${prefix}[${key}]` : key;
14+
15+
if (value === null || value === undefined) {
16+
continue;
17+
}
18+
19+
if (typeof value === "object" && value !== null) {
20+
if (prefix === "" && key === "properties") {
21+
params.append(key, JSON.stringify(value));
22+
} else {
23+
params.append(newKey, JSON.stringify(value));
24+
}
25+
} else {
26+
params.append(newKey, String(value));
27+
}
28+
}
29+
}
30+
};
31+
32+
flatten(data);
33+
34+
if (tracker.options.clientId && !params.has("client_id")) {
35+
params.set("client_id", tracker.options.clientId);
36+
}
37+
38+
if (!params.has("sdk_name")) {
39+
params.set("sdk_name", tracker.options.sdk || "web");
40+
}
41+
if (!params.has("sdk_version")) {
42+
params.set("sdk_version", tracker.options.sdkVersion || "2.0.0");
43+
}
44+
45+
const baseUrl = tracker.options.apiUrl || "https://basket.databuddy.cc";
46+
const url = new URL(endpoint === "/" ? "/pixel.gif" : endpoint, baseUrl);
47+
48+
params.forEach((value, key) => {
49+
url.searchParams.append(key, value);
50+
});
51+
52+
return new Promise((resolve) => {
53+
const img = new Image();
54+
img.onload = () => resolve({ success: true });
55+
img.onerror = () => resolve({ success: false });
56+
img.src = url.toString();
57+
});
58+
};
59+
60+
tracker.api.fetch = (endpoint: string, data: any) =>
61+
sendToPixel(endpoint, data);
62+
63+
tracker.sendBeacon = (event: any) => {
64+
sendToPixel("/", event);
65+
return { success: true };
66+
};
67+
68+
tracker.sendBatchBeacon = () => null;
69+
}

packages/tracker/src/plugins/vitals.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ export function initWebVitalsTracking(tracker: BaseTracker) {
1010
const metrics: {
1111
fcp: number | undefined;
1212
lcp: number | undefined;
13-
cls: number;
13+
cls: number | undefined;
1414
inp: number | undefined;
1515
ttfb: number | undefined;
1616
} = {
1717
fcp: undefined,
1818
lcp: undefined,
19-
cls: 0,
19+
cls: undefined,
2020
inp: undefined,
2121
ttfb: undefined,
2222
};
@@ -37,7 +37,7 @@ export function initWebVitalsTracking(tracker: BaseTracker) {
3737
timestamp: Date.now(),
3838
fcp: clamp(metrics.fcp),
3939
lcp: clamp(metrics.lcp),
40-
cls: metrics.cls,
40+
cls: clamp(metrics.cls),
4141
inp: metrics.inp,
4242
ttfb: clamp(metrics.ttfb),
4343
...tracker.getBaseContext(),
@@ -59,7 +59,7 @@ export function initWebVitalsTracking(tracker: BaseTracker) {
5959
metrics.lcp = Math.round(metric.value);
6060
break;
6161
case "CLS":
62-
metrics.cls = metric.value;
62+
metrics.cls = Math.round(metric.value);
6363
break;
6464
case "INP":
6565
metrics.inp = Math.round(metric.value);
@@ -73,14 +73,12 @@ export function initWebVitalsTracking(tracker: BaseTracker) {
7373
logger.log(`Web Vitals Metric: ${metric.name}`, metric.value);
7474
};
7575

76-
// Initialize web-vitals listeners
7776
onFCP(handleMetric);
7877
onLCP(handleMetric);
7978
onCLS(handleMetric);
8079
onINP(handleMetric);
8180
onTTFB(handleMetric);
8281

83-
// Send report on page hide / unload
8482
const report = () => {
8583
if (reported) {
8684
return;

packages/tracker/test-server.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,14 @@ serve({
1717
<html>
1818
<head>
1919
<title>Databuddy Tracker Test</title>
20+
<script src="/dist/databuddy-debug.js" data-client-id="dev-test-id"></script>
2021
</head>
2122
<body>
2223
<h1>Tracker Test Page</h1>
24+
<button onclick="databuddy.track('test_click')">Track Click</button>
25+
<button onclick="databuddyOptOut()">Opt Out</button>
26+
<button onclick="databuddyOptIn()">Opt In</button>
27+
<p>Open console to debug</p>
2328
</body>
2429
</html>
2530
`,

0 commit comments

Comments
 (0)