Skip to content

Commit cd305c8

Browse files
committed
feat: new interface tracking functions
1 parent eeec84d commit cd305c8

File tree

18 files changed

+123
-202
lines changed

18 files changed

+123
-202
lines changed

examples/nuxt-v3/server/api/track-event.post.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,9 @@ import { defineEventHandler, createError } from "h3";
22

33
export default defineEventHandler(async (event) => {
44
try {
5-
await trackEvent("button_clicked", {
6-
event,
7-
metadata: {
8-
source: "test_page",
9-
},
10-
});
5+
await trackEvent(event, "button_clicked", {
6+
external_id: "1234",
7+
});
118

129
return {
1310
success: true,

examples/nuxt-v4/server/api/track-event.post.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,8 @@ import { defineEventHandler, createError } from "h3";
22

33
export default defineEventHandler(async (event) => {
44
try {
5-
await trackEvent("button_clicked", {
6-
event,
7-
metadata: {
8-
source: "test_page",
9-
},
5+
await trackEvent(event, "button_clicked", {
6+
external_id: "1234",
107
});
118

129
return {

packages/nuxt/README.md

Lines changed: 22 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,14 @@ export default defineNuxtConfig({
1818
simpleAnalytics: {
1919
hostname: "your-domain.com",
2020
enabled: true,
21-
proxy: true,
2221
},
2322
});
2423
```
2524

2625
## Usage
2726

27+
Adding the module will automatically enable client-side page view collection though the Simple Analytics script.
28+
2829
### Server-side Pageview Tracking
2930

3031
Track pageviews automatically on the server:
@@ -34,10 +35,7 @@ Track pageviews automatically on the server:
3435
// This will run on the server and track the pageview
3536
if (import.meta.server) {
3637
await trackPageview({
37-
hostname: "your-domain.com",
38-
metadata: {
39-
source: "homepage",
40-
},
38+
some_extra_metadata: "homepage"
4139
});
4240
}
4341
</script>
@@ -48,14 +46,11 @@ if (import.meta.server) {
4846
Track custom events from API routes or server-side code:
4947

5048
```ts
51-
// In a server API route
49+
// In a (Nitro) server API route
5250
export default defineEventHandler(async (event) => {
53-
await trackEvent("user_signup", {
54-
event,
55-
metadata: {
56-
source: "registration_form",
57-
user_type: "new",
58-
},
51+
await trackEvent(event, "user_signup", {
52+
source: "registration_form",
53+
user_type: "new",
5954
});
6055

6156
return { success: true };
@@ -75,9 +70,6 @@ export default defineNuxtConfig({
7570
// Enable/disable the module
7671
enabled: true,
7772

78-
// Enable/disable proxy
79-
proxy: true,
80-
8173
// Auto-collect events
8274
autoCollect: true,
8375

@@ -99,6 +91,9 @@ export default defineNuxtConfig({
9991
screensize: false,
10092
viewportsize: false,
10193
language: false,
94+
95+
// Use vendor specific timezone headers to the determine the visitors location (server only)
96+
timezone: false
10297
},
10398

10499
// Ignore specific pages
@@ -112,6 +107,9 @@ export default defineNuxtConfig({
112107

113108
// Strict UTM parameter parsing
114109
strictUtm: true,
110+
111+
// Enable enhanced bot detection during server tracking (server only)
112+
enhancedBotDetection: false
115113
},
116114
});
117115
```
@@ -131,7 +129,7 @@ Track a pageview on the server.
131129

132130
**Parameters:**
133131

134-
- `options` (object): Additional metadata to track (optional)
132+
- `metadata` (object): Additional metadata to track (optional)
135133

136134
### `trackEvent(eventName, options)`
137135

@@ -140,40 +138,28 @@ Track a custom event on the server.
140138
**Parameters:**
141139

142140
- `eventName` (string): Name of the event to track
143-
- `options` (object): Additional metadata to track (option)
141+
- `metadata` (object): Additional metadata to track (optional)
144142

145143
## API Reference (Nitro)
146144

147-
### `trackPageview(requestEvent, options)`
145+
### `trackPageview(event, options)`
148146

149147
Track a pageview on the server.
150148

151149
**Parameters:**
152150

153-
- `options` (object): Additional metadata to track (optional)
151+
- `event` (H3Event): Nitro request event
152+
- `metadata` (object): Additional metadata to track (optional)
154153

155-
### `trackEvent(requestEvent, eventName, options)`
154+
### `trackEvent(event, eventName, options)`
156155

157156
Track a custom event on the server.
158157

159158
**Parameters:**
160159

161-
- `options` (object):
162-
- `hostname` (string): Your Simple Analytics hostname
163-
- `metadata` (object): Additional metadata to track
164-
- `ignoreMetrics` (object): Metrics to ignore for this pageview
165-
- `collectDnt` (boolean): Whether to collect data when DNT is enabled
166-
- `strictUtm` (boolean): Whether to use strict UTM parameter parsing
167-
168-
## Migration to v2.0
169-
170-
## Do Not Track (DNT)
171-
172-
### Client-side analytics
173-
174-
### Server-side analytics
175-
176-
## Ignoring metrics To also record DNT visitors you can add data-collect-dnt="true" to the script tag
160+
- `event` (H3Event): Nitro request event
161+
- `eventName` (string): Name of the event to track
162+
- `metadata` (object): Additional metadata to track (optional)
177163

178164
## License
179165

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
export default defineNuxtConfig({
22
modules: ["../src/module"],
33
devtools: { enabled: true },
4+
simpleAnalytics: {
5+
hostname: "playground.example.com",
6+
},
47
});

packages/nuxt/playground/server/api/track-event.post.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,8 @@ export default defineEventHandler(async (event) => {
55
const { eventName, metadata } = await readBody(event);
66

77
// Track the custom event using server-side function
8-
await trackEvent(eventName, {
9-
event,
10-
metadata,
11-
hostname: "playground.example.com",
8+
await trackEvent(event, eventName, {
9+
...metadata,
1210
});
1311

1412
return {

packages/nuxt/src/runtime/interfaces.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,15 @@ export interface SimpleAnalyticsOptions {
1919
screensize?: boolean;
2020
viewportsize?: boolean;
2121
language?: boolean;
22+
// server-side only
23+
timezone?: boolean;
2224
};
2325
ignorePages?: string[];
2426
allowParams?: string[];
2527
nonUniqueParams?: string[];
2628
strictUtm?: boolean;
29+
// server-side only
30+
enhancedBotDetection?: boolean;
2731
}
32+
33+
export type IgnoredMetrics = SimpleAnalyticsOptions['ignoreMetrics'];

packages/nuxt/src/runtime/nitro/interface.ts

Lines changed: 0 additions & 5 deletions
This file was deleted.

packages/nuxt/src/runtime/nitro/track-event.ts

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,48 @@
1-
import type { AnalyticsEvent, TrackingOptions } from "../server/lib/interfaces";
1+
import type { AnalyticsEvent } from "../server/lib/interfaces";
22
import {
33
isProduction,
44
isDoNotTrackEnabled,
5-
isEnhancedBotDetectionEnabled,
65
} from "../server/lib/utils";
76
import { parseHeaders } from "../server/lib/headers";
87
import { useRuntimeConfig } from "#imports";
9-
import type { NitroContext } from "./interface";
10-
11-
type TrackEventOptions = TrackingOptions & NitroContext;
8+
import type { H3Event } from "h3";
129

1310
export async function trackEvent(
11+
event: H3Event,
1412
eventName: string,
15-
options: TrackEventOptions
13+
metadata?: Record<string, string | boolean | number | Date>
1614
) {
1715
if (!isProduction()) {
1816
return;
1917
}
2018

21-
const hostname =
22-
options?.hostname ?? useRuntimeConfig().public.simpleAnalytics.hostname;
19+
const config = useRuntimeConfig().public.simpleAnalytics;
20+
const hostname = config.hostname;
2321

2422
if (!hostname) {
2523
console.warn("No hostname provided for Simple Analytics");
2624
return;
2725
}
2826

29-
const { headers } = options.event;
30-
31-
if (isDoNotTrackEnabled(headers) && !options?.collectDnt) {
27+
if (isDoNotTrackEnabled(event.headers) && !config.collectDnt) {
3228
return;
3329
}
3430

3531
const payload: AnalyticsEvent = {
3632
type: "event",
3733
hostname,
3834
event: eventName,
39-
metadata: options?.metadata,
40-
...parseHeaders(headers, options?.ignoreMetrics),
35+
metadata,
36+
...parseHeaders(event.headers, config.ignoreMetrics),
4137
};
4238

4339
const response = await fetch("https://queue.simpleanalyticscdn.com/events", {
4440
method: "POST",
4541
headers: {
4642
"Content-Type": "application/json",
47-
...(headers.has("X-Forwarded-For") &&
48-
options &&
49-
isEnhancedBotDetectionEnabled(options) && {
50-
"X-Forwarded-For": headers.get("X-Forwarded-For")!,
43+
...(event.headers.has("X-Forwarded-For") &&
44+
config.enhancedBotDetection && {
45+
"X-Forwarded-For": event.headers.get("X-Forwarded-For")!,
5146
}),
5247
},
5348
body: JSON.stringify(payload),

packages/nuxt/src/runtime/nitro/track-pageview.ts

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,44 @@
11
import type {
22
AnalyticsPageview,
3-
TrackingOptions,
43
} from "../server/lib/interfaces";
54
import {
65
isProduction,
76
isDoNotTrackEnabled,
8-
isEnhancedBotDetectionEnabled,
97
} from "../server/lib/utils";
108
import { parseHeaders } from "../server/lib/headers";
119
import { parseUtmParameters } from "../server/lib/utm";
1210
import { useRuntimeConfig } from "#imports";
13-
import type { NitroContext } from "./interface";
11+
import type { H3Event } from "h3";
1412

1513
// eslint-disable-next-line regexp/no-unused-capturing-group
1614
const PROXY_PATHS = /^\/(proxy\.js|auto-events\.js|simple\/.*)$/;
1715

18-
type TrackPageviewOptions = TrackingOptions & NitroContext;
19-
20-
export async function trackPageview(options: TrackPageviewOptions) {
16+
export async function trackPageview(event: H3Event, metadata?: Record<string, string | boolean | number | Date>) {
2117
if (!isProduction()) {
2218
return;
2319
}
2420

25-
const hostname =
26-
options?.hostname ?? useRuntimeConfig().public.simpleAnalytics.hostname;
21+
const config = useRuntimeConfig().public.simpleAnalytics;
22+
const hostname = config.hostname;
2723

2824
if (!hostname) {
2925
console.warn("No hostname provided for Simple Analytics");
3026
return;
3127
}
3228

3329
// We don't record non-GET requests
34-
if (options.event.method !== "GET") {
30+
if (event.method !== "GET") {
3531
return;
3632
}
3733

38-
const { headers } = options.event;
39-
const { path, query } = options.event.context.route;
34+
const { path, query } = event.context.route;
4035

4136
// We don't record non-navigation requests
42-
if (headers.get("Sec-Fetch-Mode") !== "navigate") {
37+
if (event.headers.get("Sec-Fetch-Mode") !== "navigate") {
4338
return;
4439
}
4540

46-
if (isDoNotTrackEnabled(headers) && !options?.collectDnt) {
41+
if (isDoNotTrackEnabled(event.headers) && !config.collectDnt) {
4742
return;
4843
}
4944

@@ -56,10 +51,11 @@ export async function trackPageview(options: TrackPageviewOptions) {
5651
hostname,
5752
event: "pageview",
5853
path,
59-
...parseHeaders(headers, options?.ignoreMetrics),
60-
...(query && !options?.ignoreMetrics?.utm
54+
metadata,
55+
...parseHeaders(event.headers, config.ignoreMetrics),
56+
...(query && !config.ignoreMetrics?.utm
6157
? parseUtmParameters(query, {
62-
strictUtm: options?.strictUtm ?? true,
58+
strictUtm: config.strictUtm ?? true,
6359
})
6460
: {}),
6561
};
@@ -68,10 +64,9 @@ export async function trackPageview(options: TrackPageviewOptions) {
6864
method: "POST",
6965
headers: {
7066
"Content-Type": "application/json",
71-
...(headers.has("X-Forwarded-For") &&
72-
options &&
73-
isEnhancedBotDetectionEnabled(options) && {
74-
"X-Forwarded-For": headers.get("X-Forwarded-For")!,
67+
...(event.headers.has("X-Forwarded-For") &&
68+
config.enhancedBotDetection && {
69+
"X-Forwarded-For": event.headers.get("X-Forwarded-For")!,
7570
}),
7671
},
7772
body: JSON.stringify(payload),

packages/nuxt/src/runtime/plugin.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,26 @@ type SimpleAnalyticsPlugin = Plugin & {
1010
install(app: App, options?: SimpleAnalyticsOptions): void;
1111
};
1212

13+
function removeServerOnlyOptions(options: SimpleAnalyticsOptions) {
14+
return {
15+
...options,
16+
ignoreMetrics: {
17+
...options.ignoreMetrics ?? {},
18+
timezone: undefined,
19+
},
20+
enhancedBotDetection: undefined,
21+
};
22+
}
23+
1324
export default defineNuxtPlugin((nuxtApp) => {
1425
const config = useRuntimeConfig();
1526

27+
// TODO: add proxy support Vue plugin
1628
const { enabled, proxy, ...options } = config.public.simpleAnalytics;
1729

1830
// We have to cast the plugin here because the forced .mjs import
1931
nuxtApp.vueApp.use(SimpleAnalytics as SimpleAnalyticsPlugin, {
2032
skip: config.public.simpleAnalytics.enabled === false,
21-
...options,
33+
...removeServerOnlyOptions(options),
2234
});
2335
});

0 commit comments

Comments
 (0)