Skip to content

Commit 7671c80

Browse files
committed
fix(UmamiAnalytics): v2.18 compatibility
Fixes #459
1 parent f9d9cc9 commit 7671c80

File tree

3 files changed

+98
-3
lines changed

3 files changed

+98
-3
lines changed

docs/content/scripts/analytics/umami-analytics.md

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ useScriptUmamiAnalytics({
100100
```ts
101101
export interface UmamiAnalyticsApi {
102102
track: ((payload?: Record<string, any>) => void) &((event_name: string, event_data: Record<string, any>) => void)
103-
identify: (session_data?: Record<string, any>) => void
103+
identify: (session_data?: Record<string, any> | string) => void
104104
}
105105
```
106106

@@ -133,6 +133,75 @@ export const UmamiAnalyticsOptions = object({
133133
* Events can be filtered in the dashboard by a specific tag.
134134
*/
135135
tag: optional(string()),
136+
/**
137+
* Function that will be called before data is sent to Umami.
138+
* The function takes two parameters: type and payload.
139+
* Return the payload to continue sending, or return a falsy value to cancel.
140+
*/
141+
beforeSend: optional(union([
142+
custom<(type: string, payload: Record<string, any>) => Record<string, any> | null | false>(input => typeof input === 'function'),
143+
string(),
144+
])),
145+
})
146+
```
147+
148+
## Advanced Features
149+
150+
### Session Identification
151+
152+
Umami v2.18.0+ supports setting unique session IDs using the `identify` function. You can pass either a string (unique ID) or an object with session data:
153+
154+
```ts
155+
const { proxy } = useScriptUmamiAnalytics({
156+
websiteId: 'YOUR_WEBSITE_ID'
157+
})
158+
159+
// Using a unique string ID
160+
proxy.identify('user-12345')
161+
162+
// Using session data object
163+
proxy.identify({
164+
userId: 'user-12345',
165+
plan: 'premium'
166+
})
167+
```
168+
169+
### Data Filtering with beforeSend
170+
171+
The `beforeSend` option allows you to inspect, modify, or cancel data before it's sent to Umami. This is useful for implementing custom privacy controls or data filtering:
172+
173+
```ts
174+
useScriptUmamiAnalytics({
175+
websiteId: 'YOUR_WEBSITE_ID',
176+
beforeSend: (type, payload) => {
177+
// Log what's being sent (for debugging)
178+
console.log('Sending to Umami:', type, payload)
179+
180+
// Filter out sensitive data
181+
if (payload.url && payload.url.includes('private')) {
182+
return false // Cancel send
183+
}
184+
185+
// Modify payload before sending
186+
return {
187+
...payload,
188+
referrer: '' // Remove referrer for privacy
189+
}
190+
}
191+
})
192+
```
193+
194+
You can also provide a string with the name of a globally defined function:
195+
196+
```ts
197+
// Define function globally
198+
window.myBeforeSendHandler = (type, payload) => {
199+
return checkPrivacyRules(payload) ? payload : false
200+
}
201+
202+
useScriptUmamiAnalytics({
203+
websiteId: 'YOUR_WEBSITE_ID',
204+
beforeSend: 'myBeforeSendHandler'
136205
})
137206
```
138207

src/runtime/registry/umami-analytics.ts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { useRegistryScript } from '../utils'
2-
import { object, optional, string, boolean, array } from '#nuxt-scripts-validator'
2+
import { object, optional, string, boolean, array, union, custom } from '#nuxt-scripts-validator'
33
import type { RegistryScriptInput } from '#nuxt-scripts/types'
44

55
export const UmamiAnalyticsOptions = object({
@@ -26,13 +26,22 @@ export const UmamiAnalyticsOptions = object({
2626
* Events can be filtered in the dashboard by a specific tag.
2727
*/
2828
tag: optional(string()),
29+
/**
30+
* Function that will be called before data is sent to Umami.
31+
* The function takes two parameters: type and payload.
32+
* Return the payload to continue sending, or return a falsy value to cancel.
33+
*/
34+
beforeSend: optional(union([
35+
custom<(type: string, payload: Record<string, any>) => Record<string, any> | null | false>(input => typeof input === 'function'),
36+
string(),
37+
])),
2938
})
3039

3140
export type UmamiAnalyticsInput = RegistryScriptInput<typeof UmamiAnalyticsOptions, false>
3241

3342
export interface UmamiAnalyticsApi {
3443
track: ((payload?: Record<string, any>) => void) & ((event_name: string, event_data: Record<string, any>) => void)
35-
identify: (session_data?: Record<string, any>) => void
44+
identify: (session_data?: Record<string, any> | string) => void
3645
}
3746

3847
declare global {
@@ -44,6 +53,21 @@ declare global {
4453
export function useScriptUmamiAnalytics<T extends UmamiAnalyticsApi>(_options?: UmamiAnalyticsInput) {
4554
return useRegistryScript<T, typeof UmamiAnalyticsOptions>('umamiAnalytics', (options) => {
4655
const domains = Array.isArray(options?.domains) ? options.domains.join(',') : options?.domains
56+
57+
let beforeSendFunctionName: string | undefined
58+
if (import.meta.client) {
59+
// Handle beforeSend function
60+
if (options?.beforeSend && typeof options.beforeSend === 'function') {
61+
// Generate a random function name
62+
beforeSendFunctionName = `__umamiBeforeSend_${Math.random().toString(36).substring(2, 15)}`
63+
// Add function to window global scope
64+
;(window as any)[beforeSendFunctionName] = options.beforeSend
65+
}
66+
else if (typeof options.beforeSend === 'string') {
67+
// If it's a string, assume it's a function name already defined in the global scope
68+
beforeSendFunctionName = options.beforeSend
69+
}
70+
}
4771
return {
4872
scriptInput: {
4973
'src': 'https://cloud.umami.is/script.js',
@@ -52,6 +76,7 @@ export function useScriptUmamiAnalytics<T extends UmamiAnalyticsApi>(_options?:
5276
'data-auto-track': typeof options?.autoTrack === 'boolean' ? options.autoTrack : true,
5377
'data-domains': domains || undefined,
5478
'data-tag': options?.tag || undefined,
79+
'data-before-send': beforeSendFunctionName || undefined,
5580
},
5681
schema: import.meta.dev ? UmamiAnalyticsOptions : undefined,
5782
scriptOptions: {

src/runtime/validation/mock.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ export const any = noop
2121
export const minLength = noop
2222

2323
export const pipe = noop
24+
export const custom = noop

0 commit comments

Comments
 (0)