qwik-umami 1.0.2 → 1.1.0
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 +210 -46
- package/lib/index.qwik.cjs +84 -57
- package/lib/index.qwik.cjs.map +1 -1
- package/lib/index.qwik.mjs +85 -58
- package/lib/index.qwik.mjs.map +1 -1
- package/lib/server.cjs +60 -0
- package/lib/server.cjs.map +1 -0
- package/lib/server.mjs +60 -0
- package/lib/server.mjs.map +1 -0
- package/lib-types/hooks/use-umami-track.d.ts +1 -3
- package/lib-types/index.d.ts +1 -1
- package/lib-types/server/index.d.ts +3 -0
- package/lib-types/server/umami-plugin.d.ts +3 -0
- package/lib-types/server/umami-server.d.ts +3 -0
- package/lib-types/types.d.ts +46 -4
- package/lib-types/utils/track.d.ts +8 -0
- package/llms.txt +190 -92
- package/package.json +72 -60
package/README.md
CHANGED
|
@@ -4,12 +4,13 @@
|
|
|
4
4
|
[](https://github.com/murcisluis/qwik-umami/blob/main/LICENSE)
|
|
5
5
|
[](https://bundlephobia.com/package/qwik-umami)
|
|
6
6
|
|
|
7
|
-
SSR-safe [Umami Analytics](https://umami.is) integration for [Qwik](https://qwik.dev). Drop-in component +
|
|
7
|
+
SSR-safe [Umami Analytics](https://umami.is) integration for [Qwik](https://qwik.dev). Drop-in component + utility functions for automatic page views, custom event tracking, and server-side analytics.
|
|
8
8
|
|
|
9
9
|
- **Zero config** — one component in `root.tsx` and you're tracking
|
|
10
10
|
- **SSR-safe** — no-ops on the server, hydrates on the client
|
|
11
|
+
- **Server-side tracking** — send events from `routeLoader$`, `routeAction$`, or `server$`
|
|
11
12
|
- **Self-hosted ready** — works with Umami Cloud and self-hosted instances
|
|
12
|
-
- **Typed** — full TypeScript support
|
|
13
|
+
- **Typed** — full TypeScript support, typed against the official Umami API
|
|
13
14
|
- **Lightweight** — no runtime dependencies, just Qwik as peer dep
|
|
14
15
|
|
|
15
16
|
## Installation
|
|
@@ -46,39 +47,45 @@ export default component$(() => {
|
|
|
46
47
|
|
|
47
48
|
That's it. Page views are tracked automatically.
|
|
48
49
|
|
|
49
|
-
### 2. Track custom events
|
|
50
|
-
|
|
51
|
-
Use the `useUmamiTrack` hook in any component:
|
|
50
|
+
### 2. Track custom events (client-side)
|
|
52
51
|
|
|
53
52
|
```tsx
|
|
54
53
|
import { component$ } from '@builder.io/qwik';
|
|
55
|
-
import {
|
|
54
|
+
import { umamiTrack } from 'qwik-umami';
|
|
56
55
|
|
|
57
56
|
export const SignupButton = component$(() => {
|
|
58
|
-
const { track } = useUmamiTrack();
|
|
59
|
-
|
|
60
57
|
return (
|
|
61
|
-
<button onClick$={() =>
|
|
58
|
+
<button onClick$={() => umamiTrack('signup-click', { plan: 'pro' })}>
|
|
62
59
|
Start free trial
|
|
63
60
|
</button>
|
|
64
61
|
);
|
|
65
62
|
});
|
|
66
63
|
```
|
|
67
64
|
|
|
68
|
-
###
|
|
65
|
+
### 3. Track events server-side
|
|
66
|
+
|
|
67
|
+
Use `serverUmamiTrack` inside `routeLoader$`, `routeAction$`, or `server$`:
|
|
69
68
|
|
|
70
69
|
```tsx
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
70
|
+
import { routeAction$ } from '@builder.io/qwik-city';
|
|
71
|
+
import { serverUmamiTrack } from 'qwik-umami/server';
|
|
72
|
+
|
|
73
|
+
const options = {
|
|
74
|
+
websiteId: import.meta.env.UMAMI_WEBSITE_ID,
|
|
75
|
+
hostUrl: import.meta.env.UMAMI_HOST_URL,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export const useCheckout = routeAction$(async (data) => {
|
|
79
|
+
await serverUmamiTrack(options, 'purchase', { plan: data.plan });
|
|
80
|
+
// ...
|
|
81
|
+
});
|
|
75
82
|
```
|
|
76
83
|
|
|
77
84
|
## API
|
|
78
85
|
|
|
79
86
|
### `<UmamiScript>`
|
|
80
87
|
|
|
81
|
-
Component that loads the Umami tracking script.
|
|
88
|
+
Component that loads the Umami tracking script. Uses `useTask$` with `isServer` guard to preserve Qwik's resumability model. Loads via `requestIdleCallback` by default to avoid blocking the main thread.
|
|
82
89
|
|
|
83
90
|
| Prop | Type | Default | Description |
|
|
84
91
|
| --- | --- | --- | --- |
|
|
@@ -86,61 +93,218 @@ Component that loads the Umami tracking script. Checks service availability befo
|
|
|
86
93
|
| `src` | `string` | `https://cloud.umami.is/script.js` | URL of the tracking script |
|
|
87
94
|
| `hostUrl` | `string` | — | Custom host URL for data collection |
|
|
88
95
|
| `autoTrack` | `boolean` | `true` | Enable automatic page view tracking |
|
|
89
|
-
| `domains` | `string` | — | Comma-separated allowed domains |
|
|
90
|
-
| `
|
|
96
|
+
| `domains` | `string` | — | Comma-separated list of allowed domains |
|
|
97
|
+
| `tag` | `string` | — | Assign events to a specific tag |
|
|
98
|
+
| `excludeSearch` | `boolean` | — | Exclude URL search parameters from tracking |
|
|
99
|
+
| `excludeHash` | `boolean` | — | Exclude URL hash fragments from tracking |
|
|
100
|
+
| `doNotTrack` | `boolean` | — | Respect the browser's Do Not Track setting |
|
|
101
|
+
| `strategy` | `'eager' \| 'idle'` | `'idle'` | `'idle'` defers loading via `requestIdleCallback`, `'eager'` loads immediately |
|
|
91
102
|
|
|
92
|
-
|
|
103
|
+
---
|
|
93
104
|
|
|
94
|
-
|
|
105
|
+
### `umamiTrack()`
|
|
106
|
+
|
|
107
|
+
Client-side utility function. SSR-safe (no-op on server). Import from `'qwik-umami'`.
|
|
95
108
|
|
|
96
109
|
```ts
|
|
97
|
-
|
|
110
|
+
// Track a pageview manually
|
|
111
|
+
umamiTrack();
|
|
112
|
+
|
|
113
|
+
// Track a named event
|
|
114
|
+
umamiTrack('button-click');
|
|
98
115
|
|
|
99
|
-
//
|
|
100
|
-
|
|
116
|
+
// Track an event with data
|
|
117
|
+
umamiTrack('purchase', { plan: 'pro', price: 29 });
|
|
101
118
|
|
|
102
|
-
//
|
|
103
|
-
|
|
119
|
+
// Track with a full custom payload
|
|
120
|
+
umamiTrack({ website: 'id', url: '/checkout', title: 'Checkout' });
|
|
104
121
|
```
|
|
105
122
|
|
|
106
|
-
|
|
107
|
-
- SSR-safe: no-op on the server, works after hydration
|
|
108
|
-
- Silent in production, logs warnings in development if Umami isn't loaded
|
|
109
|
-
- Gracefully handles ad blockers and network failures — no errors, no broken pages
|
|
123
|
+
---
|
|
110
124
|
|
|
111
|
-
###
|
|
125
|
+
### `umamiIdentify()`
|
|
126
|
+
|
|
127
|
+
Associates the current session with a user or custom data. Client-side only. Import from `'qwik-umami'`.
|
|
112
128
|
|
|
113
129
|
```ts
|
|
114
|
-
|
|
130
|
+
// Identify with session data only
|
|
131
|
+
umamiIdentify({ plan: 'pro', role: 'admin' });
|
|
132
|
+
|
|
133
|
+
// Identify with a unique ID
|
|
134
|
+
umamiIdentify('user-123');
|
|
115
135
|
|
|
116
|
-
//
|
|
117
|
-
|
|
136
|
+
// Identify with a unique ID and data
|
|
137
|
+
umamiIdentify('user-123', { plan: 'pro' });
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
### `serverUmamiTrack()`
|
|
143
|
+
|
|
144
|
+
Server-side event tracking. Works in `routeLoader$`, `routeAction$`, `server$`. Import from `'qwik-umami/server'`.
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
import { serverUmamiTrack } from 'qwik-umami/server';
|
|
148
|
+
import type { UmamiServerOptions } from 'qwik-umami/server';
|
|
149
|
+
|
|
150
|
+
const options: UmamiServerOptions = {
|
|
151
|
+
websiteId: 'your-website-id',
|
|
152
|
+
hostUrl: 'https://your-umami-instance.com', // or https://cloud.umami.is
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
// Track a named event
|
|
156
|
+
await serverUmamiTrack(options, 'signup');
|
|
157
|
+
|
|
158
|
+
// Track with data
|
|
159
|
+
await serverUmamiTrack(options, 'purchase', { plan: 'pro', amount: 29 });
|
|
160
|
+
|
|
161
|
+
// Track with full payload
|
|
162
|
+
await serverUmamiTrack(options, {
|
|
163
|
+
url: '/checkout',
|
|
164
|
+
title: 'Checkout',
|
|
165
|
+
name: 'page-view',
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
### `createUmamiPlugin()`
|
|
172
|
+
|
|
173
|
+
Server-side Qwik City plugin for automatic page view tracking. Tracks every page request via the Umami API without requiring the client-side script. Import from `'qwik-umami/server'`. Requires `@builder.io/qwik-city` as peer dependency.
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
// src/routes/plugin@umami.ts
|
|
177
|
+
import { createUmamiPlugin } from 'qwik-umami/server';
|
|
178
|
+
|
|
179
|
+
export const onRequest = createUmamiPlugin({
|
|
180
|
+
websiteId: import.meta.env.PUBLIC_UMAMI_ID,
|
|
181
|
+
hostUrl: import.meta.env.UMAMI_HOST_URL,
|
|
182
|
+
});
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
| Option | Type | Default | Description |
|
|
186
|
+
| --- | --- | --- | --- |
|
|
187
|
+
| `websiteId` | `string` | **required** | Your Umami website ID |
|
|
188
|
+
| `hostUrl` | `string` | **required** | Umami instance URL |
|
|
189
|
+
| `userAgent` | `string` | request UA | Custom user-agent for tracking requests |
|
|
190
|
+
| `filter` | `(url: URL, headers: Headers) => boolean` | — | Return `false` to skip tracking for specific routes |
|
|
191
|
+
|
|
192
|
+
**How it works:**
|
|
193
|
+
- Only tracks `GET` requests (skips POST, PUT, DELETE, etc.)
|
|
194
|
+
- Automatically ignores static assets (`.js`, `.css`, `.png`, `.ico`, etc.)
|
|
195
|
+
- Fire-and-forget — the tracking request does NOT block the response
|
|
196
|
+
- Extracts `referrer`, `language`, and `user-agent` from request headers
|
|
197
|
+
|
|
198
|
+
**Filter example:**
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
export const onRequest = createUmamiPlugin({
|
|
202
|
+
websiteId: 'your-id',
|
|
203
|
+
hostUrl: 'https://your-umami.com',
|
|
204
|
+
filter: (url) => !url.pathname.startsWith('/api/'),
|
|
205
|
+
});
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
### `serverUmamiIdentify()`
|
|
211
|
+
|
|
212
|
+
Server-side session identification. Import from `'qwik-umami/server'`.
|
|
213
|
+
|
|
214
|
+
```ts
|
|
215
|
+
import { serverUmamiIdentify } from 'qwik-umami/server';
|
|
216
|
+
|
|
217
|
+
await serverUmamiIdentify(options, { userId: 'abc', plan: 'pro' });
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
### Types
|
|
223
|
+
|
|
224
|
+
```ts
|
|
225
|
+
import type {
|
|
226
|
+
UmamiConfig, // Props for <UmamiScript>
|
|
227
|
+
UmamiEventData, // Record<string, string | number | boolean>
|
|
228
|
+
UmamiPayload, // Full browser tracker payload
|
|
229
|
+
} from 'qwik-umami';
|
|
230
|
+
|
|
231
|
+
import type {
|
|
232
|
+
UmamiServerOptions, // { websiteId, hostUrl, userAgent? }
|
|
233
|
+
UmamiServerPayload, // Server-side payload shape
|
|
234
|
+
UmamiPluginOptions, // { websiteId, hostUrl, userAgent?, filter? }
|
|
235
|
+
} from 'qwik-umami/server';
|
|
118
236
|
```
|
|
119
237
|
|
|
120
238
|
## Real-world example
|
|
121
239
|
|
|
122
|
-
|
|
240
|
+
```tsx
|
|
241
|
+
// Tracking a full auth + conversion funnel
|
|
242
|
+
|
|
243
|
+
// Landing page CTA (client)
|
|
244
|
+
<button onClick$={() => umamiTrack('cta-click', { location: 'hero' })}>
|
|
245
|
+
Get started
|
|
246
|
+
</button>
|
|
247
|
+
|
|
248
|
+
// Auth action (server)
|
|
249
|
+
export const useLogin = routeAction$(async (data) => {
|
|
250
|
+
const user = await loginUser(data);
|
|
251
|
+
await serverUmamiTrack(options, 'login', { success: true });
|
|
252
|
+
return user;
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
// Identify after login (client)
|
|
256
|
+
umamiIdentify(user.id, { plan: user.plan });
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## Self-hosted Umami
|
|
123
260
|
|
|
124
261
|
```tsx
|
|
125
|
-
|
|
126
|
-
|
|
262
|
+
<UmamiScript
|
|
263
|
+
websiteId="your-website-id"
|
|
264
|
+
src="https://your-umami-instance.com/script.js"
|
|
265
|
+
/>
|
|
266
|
+
```
|
|
127
267
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
268
|
+
```ts
|
|
269
|
+
const options = {
|
|
270
|
+
websiteId: 'your-website-id',
|
|
271
|
+
hostUrl: 'https://your-umami-instance.com',
|
|
272
|
+
};
|
|
273
|
+
```
|
|
131
274
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
275
|
+
## Which approach should I use?
|
|
276
|
+
|
|
277
|
+
| Approach | Best for |
|
|
278
|
+
| --- | --- |
|
|
279
|
+
| **`<UmamiScript>` only** | Most apps — full browser data (screen size, timezone, JS events) |
|
|
280
|
+
| **`createUmamiPlugin` only** | Server-rendered sites, bot tracking, ad-blocker resilience |
|
|
281
|
+
| **Both together** | Maximum coverage — use plugin for page views + component for events |
|
|
282
|
+
|
|
283
|
+
**Using both together:**
|
|
284
|
+
|
|
285
|
+
```tsx
|
|
286
|
+
// src/routes/plugin@umami.ts — handles page views server-side
|
|
287
|
+
import { createUmamiPlugin } from 'qwik-umami/server';
|
|
288
|
+
|
|
289
|
+
export const onRequest = createUmamiPlugin({
|
|
290
|
+
websiteId: import.meta.env.PUBLIC_UMAMI_ID,
|
|
291
|
+
hostUrl: import.meta.env.UMAMI_HOST_URL,
|
|
292
|
+
});
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
```tsx
|
|
296
|
+
// src/root.tsx — handles custom events client-side (autoTrack disabled to avoid duplicate page views)
|
|
297
|
+
<UmamiScript websiteId="your-website-id" autoTrack={false} />
|
|
136
298
|
```
|
|
137
299
|
|
|
138
300
|
## How it works
|
|
139
301
|
|
|
140
|
-
1. `<UmamiScript>` uses Qwik's `
|
|
141
|
-
2.
|
|
142
|
-
3. If the
|
|
143
|
-
4. `
|
|
302
|
+
1. `<UmamiScript>` uses Qwik's `useTask$` with an `isServer` guard — preserves resumability (no eager JS download)
|
|
303
|
+
2. By default, the script loads via `requestIdleCallback` to avoid blocking the main thread
|
|
304
|
+
3. If the script fails to load (blocked by ad blocker, network error), it fails silently and cleans up
|
|
305
|
+
4. `umamiTrack()` and `umamiIdentify()` check for `window.umami` before calling — safe everywhere
|
|
306
|
+
5. `serverUmamiTrack()` and `serverUmamiIdentify()` POST directly to the Umami `/api/send` endpoint — no browser required
|
|
307
|
+
6. `createUmamiPlugin()` intercepts every GET request at the middleware level and sends a page view to Umami — fire-and-forget, never blocks the response
|
|
144
308
|
|
|
145
309
|
## License
|
|
146
310
|
|
package/lib/index.qwik.cjs
CHANGED
|
@@ -1,72 +1,99 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const qwik = require("@builder.io/qwik");
|
|
4
|
-
const
|
|
5
|
-
|
|
4
|
+
const build = require("@builder.io/qwik/build");
|
|
5
|
+
const UmamiScript = qwik.component$(({ websiteId, src = "https://cloud.umami.is/script.js", hostUrl, autoTrack = true, domains, tag, excludeSearch, excludeHash, doNotTrack, strategy = "idle" }) => {
|
|
6
|
+
qwik.useTask$(({ cleanup }) => {
|
|
7
|
+
if (build.isServer) return;
|
|
6
8
|
if (document.querySelector(`script[data-website-id="${websiteId}"]`)) {
|
|
7
9
|
return;
|
|
8
10
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
});
|
|
18
|
-
clearTimeout(timeoutId);
|
|
19
|
-
loadUmamiScript();
|
|
20
|
-
} catch (error) {
|
|
11
|
+
let script = null;
|
|
12
|
+
const loadScript = () => {
|
|
13
|
+
script = document.createElement("script");
|
|
14
|
+
script.defer = true;
|
|
15
|
+
script.src = src;
|
|
16
|
+
script.setAttribute("data-website-id", websiteId);
|
|
17
|
+
if (hostUrl) {
|
|
18
|
+
script.setAttribute("data-host-url", hostUrl);
|
|
21
19
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
script.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
script.setAttribute("data-data-domains", dataDomains);
|
|
40
|
-
}
|
|
41
|
-
script.onerror = () => {
|
|
42
|
-
if (false) ;
|
|
43
|
-
script.remove();
|
|
44
|
-
};
|
|
45
|
-
script.onload = () => {
|
|
46
|
-
if (false) ;
|
|
47
|
-
};
|
|
48
|
-
document.head.appendChild(script);
|
|
49
|
-
} catch (error) {
|
|
20
|
+
if (!autoTrack) {
|
|
21
|
+
script.setAttribute("data-auto-track", "false");
|
|
22
|
+
}
|
|
23
|
+
if (domains) {
|
|
24
|
+
script.setAttribute("data-domains", domains);
|
|
25
|
+
}
|
|
26
|
+
if (tag) {
|
|
27
|
+
script.setAttribute("data-tag", tag);
|
|
28
|
+
}
|
|
29
|
+
if (excludeSearch) {
|
|
30
|
+
script.setAttribute("data-exclude-search", "true");
|
|
31
|
+
}
|
|
32
|
+
if (excludeHash) {
|
|
33
|
+
script.setAttribute("data-exclude-hash", "true");
|
|
34
|
+
}
|
|
35
|
+
if (doNotTrack) {
|
|
36
|
+
script.setAttribute("data-do-not-track", "true");
|
|
50
37
|
}
|
|
38
|
+
script.onerror = () => {
|
|
39
|
+
script?.remove();
|
|
40
|
+
script = null;
|
|
41
|
+
};
|
|
42
|
+
document.head.appendChild(script);
|
|
51
43
|
};
|
|
52
|
-
|
|
44
|
+
if (strategy === "eager") {
|
|
45
|
+
loadScript();
|
|
46
|
+
} else {
|
|
47
|
+
if ("requestIdleCallback" in window) {
|
|
48
|
+
const id = window.requestIdleCallback(loadScript);
|
|
49
|
+
cleanup(() => {
|
|
50
|
+
window.cancelIdleCallback(id);
|
|
51
|
+
script?.remove();
|
|
52
|
+
});
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const timeoutId = setTimeout(loadScript, 0);
|
|
56
|
+
cleanup(() => {
|
|
57
|
+
clearTimeout(timeoutId);
|
|
58
|
+
script?.remove();
|
|
59
|
+
});
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
cleanup(() => {
|
|
63
|
+
script?.remove();
|
|
64
|
+
});
|
|
53
65
|
});
|
|
54
66
|
return null;
|
|
55
67
|
});
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
68
|
+
function umamiTrack(eventNameOrPayload, data) {
|
|
69
|
+
if (typeof window === "undefined") return;
|
|
70
|
+
try {
|
|
71
|
+
if (window.umami?.track) {
|
|
72
|
+
if (eventNameOrPayload === void 0) {
|
|
73
|
+
window.umami.track();
|
|
74
|
+
} else if (typeof eventNameOrPayload === "string") {
|
|
75
|
+
window.umami.track(eventNameOrPayload, data);
|
|
76
|
+
} else {
|
|
77
|
+
window.umami.track(eventNameOrPayload);
|
|
65
78
|
}
|
|
66
|
-
})
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
}
|
|
79
|
+
} else if (false) ;
|
|
80
|
+
} catch (error) {
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function umamiIdentify(uniqueIdOrData, data) {
|
|
84
|
+
if (typeof window === "undefined") return;
|
|
85
|
+
try {
|
|
86
|
+
if (window.umami?.identify) {
|
|
87
|
+
if (typeof uniqueIdOrData === "string") {
|
|
88
|
+
window.umami.identify(uniqueIdOrData, data);
|
|
89
|
+
} else {
|
|
90
|
+
window.umami.identify(uniqueIdOrData);
|
|
91
|
+
}
|
|
92
|
+
} else if (false) ;
|
|
93
|
+
} catch (error) {
|
|
94
|
+
}
|
|
95
|
+
}
|
|
70
96
|
exports.UmamiScript = UmamiScript;
|
|
71
|
-
exports.
|
|
97
|
+
exports.umamiIdentify = umamiIdentify;
|
|
98
|
+
exports.umamiTrack = umamiTrack;
|
|
72
99
|
//# sourceMappingURL=index.qwik.cjs.map
|
package/lib/index.qwik.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.qwik.cjs","sources":["../src/components/umami-script.tsx","../src/
|
|
1
|
+
{"version":3,"file":"index.qwik.cjs","sources":["../src/components/umami-script.tsx","../src/utils/track.ts"],"sourcesContent":["import { component$, useTask$ } from '@builder.io/qwik';\nimport { isServer } from '@builder.io/qwik/build';\nimport type { UmamiConfig } from '../types';\n\nexport const UmamiScript = component$<UmamiConfig>(\n ({\n websiteId,\n src = 'https://cloud.umami.is/script.js',\n hostUrl,\n autoTrack = true,\n domains,\n tag,\n excludeSearch,\n excludeHash,\n doNotTrack,\n strategy = 'idle',\n }) => {\n useTask$(({ cleanup }) => {\n if (isServer) return;\n\n if (document.querySelector(`script[data-website-id=\"${websiteId}\"]`)) {\n return;\n }\n\n let script: HTMLScriptElement | null = null;\n\n const loadScript = () => {\n script = document.createElement('script');\n script.defer = true;\n script.src = src;\n script.setAttribute('data-website-id', websiteId);\n\n if (hostUrl) {\n script.setAttribute('data-host-url', hostUrl);\n }\n\n if (!autoTrack) {\n script.setAttribute('data-auto-track', 'false');\n }\n\n if (domains) {\n script.setAttribute('data-domains', domains);\n }\n\n if (tag) {\n script.setAttribute('data-tag', tag);\n }\n\n if (excludeSearch) {\n script.setAttribute('data-exclude-search', 'true');\n }\n\n if (excludeHash) {\n script.setAttribute('data-exclude-hash', 'true');\n }\n\n if (doNotTrack) {\n script.setAttribute('data-do-not-track', 'true');\n }\n\n script.onerror = () => {\n if (import.meta.env.DEV) {\n console.warn('[qwik-umami] Failed to load script');\n }\n script?.remove();\n script = null;\n };\n\n if (import.meta.env.DEV) {\n script.onload = () => {\n console.log('[qwik-umami] Script loaded successfully');\n };\n }\n\n document.head.appendChild(script);\n };\n\n if (strategy === 'eager') {\n loadScript();\n } else {\n if ('requestIdleCallback' in window) {\n const id = window.requestIdleCallback(loadScript);\n cleanup(() => {\n window.cancelIdleCallback(id);\n script?.remove();\n });\n return;\n }\n const timeoutId = setTimeout(loadScript, 0);\n cleanup(() => {\n clearTimeout(timeoutId);\n script?.remove();\n });\n return;\n }\n\n cleanup(() => {\n script?.remove();\n });\n });\n\n return null;\n },\n);\n","import type { UmamiEventData, UmamiPayload } from '../types';\r\n\r\nexport function umamiTrack(): void;\r\nexport function umamiTrack(payload: UmamiPayload): void;\r\nexport function umamiTrack(eventName: string): void;\r\nexport function umamiTrack(eventName: string, data: UmamiEventData): void;\r\nexport function umamiTrack(\r\n eventNameOrPayload?: string | UmamiPayload,\r\n data?: UmamiEventData,\r\n): void {\r\n if (typeof window === 'undefined') return;\r\n\r\n try {\r\n if (window.umami?.track) {\r\n if (eventNameOrPayload === undefined) {\r\n window.umami.track();\r\n } else if (typeof eventNameOrPayload === 'string') {\r\n window.umami.track(eventNameOrPayload, data!);\r\n } else {\r\n window.umami.track(eventNameOrPayload);\r\n }\r\n } else if (import.meta.env.DEV) {\r\n console.warn('[qwik-umami] Tracking unavailable');\r\n }\r\n } catch (error) {\r\n if (import.meta.env.DEV) {\r\n console.warn('[qwik-umami] Error sending event:', eventNameOrPayload, error);\r\n }\r\n }\r\n}\r\n\r\nexport function umamiIdentify(data: UmamiEventData): void;\r\nexport function umamiIdentify(uniqueId: string): void;\r\nexport function umamiIdentify(uniqueId: string, data: UmamiEventData): void;\r\nexport function umamiIdentify(\r\n uniqueIdOrData: string | UmamiEventData,\r\n data?: UmamiEventData,\r\n): void {\r\n if (typeof window === 'undefined') return;\r\n\r\n try {\r\n if (window.umami?.identify) {\r\n if (typeof uniqueIdOrData === 'string') {\r\n window.umami.identify(uniqueIdOrData, data!);\r\n } else {\r\n window.umami.identify(uniqueIdOrData);\r\n }\r\n } else if (import.meta.env.DEV) {\r\n console.warn('[qwik-umami] Identify unavailable');\r\n }\r\n } catch (error) {\r\n if (import.meta.env.DEV) {\r\n console.warn('[qwik-umami] Error identifying:', error);\r\n }\r\n }\r\n}\r\n"],"names":["component$","useTask$","isServer"],"mappings":";;;;AAIO,MAAM,cAAcA,KAAAA,WACzB,CAAC,EACC,WACA,MAAM,oCACN,SACA,YAAY,MACZ,SACA,KACA,eACA,aACA,YACA,WAAW,aACZ;AACCC,gBAAS,CAAC,EAAE,cAAS;AACnB,QAAIC,eAAU;AAEd,QAAI,SAAS,cAAc,2BAA2B,SAAA,IAAa,GAAG;AACpE;AAAA,IACF;AAEA,QAAI,SAAmC;AAEvC,UAAM,aAAa,MAAA;AACjB,eAAS,SAAS,cAAc,QAAA;AAChC,aAAO,QAAQ;AACf,aAAO,MAAM;AACb,aAAO,aAAa,mBAAmB,SAAA;AAEvC,UAAI,SAAS;AACX,eAAO,aAAa,iBAAiB,OAAA;AAAA,MACvC;AAEA,UAAI,CAAC,WAAW;AACd,eAAO,aAAa,mBAAmB,OAAA;AAAA,MACzC;AAEA,UAAI,SAAS;AACX,eAAO,aAAa,gBAAgB,OAAA;AAAA,MACtC;AAEA,UAAI,KAAK;AACP,eAAO,aAAa,YAAY,GAAA;AAAA,MAClC;AAEA,UAAI,eAAe;AACjB,eAAO,aAAa,uBAAuB,MAAA;AAAA,MAC7C;AAEA,UAAI,aAAa;AACf,eAAO,aAAa,qBAAqB,MAAA;AAAA,MAC3C;AAEA,UAAI,YAAY;AACd,eAAO,aAAa,qBAAqB,MAAA;AAAA,MAC3C;AAEA,aAAO,UAAU,MAAA;AAIf,gBAAQ,OAAA;AACR,iBAAS;AAAA,MACX;AAQA,eAAS,KAAK,YAAY,MAAA;AAAA,IAC5B;AAEA,QAAI,aAAa,SAAS;AACxB,iBAAA;AAAA,IACF,OAAO;AACL,UAAI,yBAAyB,QAAQ;AACnC,cAAM,KAAK,OAAO,oBAAoB,UAAA;AACtC,gBAAQ,MAAA;AACN,iBAAO,mBAAmB,EAAA;AAC1B,kBAAQ,OAAA;AAAA,QACV,CAAA;AACA;AAAA,MACF;AACA,YAAM,YAAY,WAAW,YAAY,CAAA;AACzC,cAAQ,MAAA;AACN,qBAAa,SAAA;AACb,gBAAQ,OAAA;AAAA,MACV,CAAA;AACA;AAAA,IACF;AAEA,YAAQ,MAAA;AACN,cAAQ,OAAA;AAAA,IACV,CAAA;AAAA,EACF,CAAA;AAEA,SAAO;AACT,CAAA;AChGK,SAAS,WACd,oBACA,MAAqB;AAErB,MAAI,OAAO,WAAW,YAAa;AAEnC,MAAI;AACF,QAAI,OAAO,OAAO,OAAO;AACvB,UAAI,uBAAuB,QAAW;AACpC,eAAO,MAAM,MAAA;AAAA,MACf,WAAW,OAAO,uBAAuB,UAAU;AACjD,eAAO,MAAM,MAAM,oBAAoB,IAAA;AAAA,MACzC,OAAO;AACL,eAAO,MAAM,MAAM,kBAAA;AAAA,MACrB;AAAA,IACF,WAAW,MAAqB;AAAA,EAGlC,SAAS,OAAO;AAAA,EAIhB;AACF;AAKO,SAAS,cACd,gBACA,MAAqB;AAErB,MAAI,OAAO,WAAW,YAAa;AAEnC,MAAI;AACF,QAAI,OAAO,OAAO,UAAU;AAC1B,UAAI,OAAO,mBAAmB,UAAU;AACtC,eAAO,MAAM,SAAS,gBAAgB,IAAA;AAAA,MACxC,OAAO;AACL,eAAO,MAAM,SAAS,cAAA;AAAA,MACxB;AAAA,IACF,WAAW,MAAqB;AAAA,EAGlC,SAAS,OAAO;AAAA,EAIhB;AACF;;;;"}
|