mytart 0.5.2 â 0.6.1
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 +62 -2
- package/dist/index.d.mts +59 -3
- package/dist/index.d.ts +59 -3
- package/dist/index.js +120 -0
- package/dist/index.mjs +119 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -6,11 +6,12 @@
|
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
|
-
- ð **
|
|
9
|
+
- ð **8 providers out of the box**: Google Analytics 4, Mixpanel, Segment, Amplitude, Plausible, PostHog, Meta Pixel, Microsoft Clarity
|
|
10
10
|
- ð **Universal**: works in Node.js, browsers, and any JS framework (Next.js, Remix, Astro, SvelteKit, etc.)
|
|
11
11
|
- ð· **TypeScript-first**: precise typings, object-parameter style for great DX
|
|
12
12
|
- ðĶ **Dual ESM/CJS output**: works with `import` and `require`
|
|
13
13
|
- ðŠķ **Lightweight**: direct HTTP via axios, no SDK overhead
|
|
14
|
+
- ðĪ **Bot filtering**: optionally ignore bots and crawlers via [ua-parser-js](https://github.com/nicolevanderhoeven/ua-parser-js)
|
|
14
15
|
- â
**Node.js âĨ 18**
|
|
15
16
|
|
|
16
17
|
## Installation
|
|
@@ -253,6 +254,64 @@ await provider.updatePixelConsent(true); // fbq('consent', 'grant')
|
|
|
253
254
|
await provider.updatePixelConsent(false); // fbq('consent', 'revoke')
|
|
254
255
|
```
|
|
255
256
|
|
|
257
|
+
### Microsoft Clarity
|
|
258
|
+
|
|
259
|
+
[Microsoft Clarity](https://clarity.microsoft.com/) is a free behavioral analytics tool that provides session recordings, heatmaps, and insights. Clarity is **browser-only** â there is no server mode.
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
{
|
|
263
|
+
provider: 'clarity',
|
|
264
|
+
projectId: 'YOUR_PROJECT_ID',
|
|
265
|
+
enabled: true,
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
When enabled:
|
|
270
|
+
|
|
271
|
+
- The official `https://www.clarity.ms/tag/{projectId}` script is loaded once on the first `track()`, `identify()`, or `page()` call
|
|
272
|
+
- `track()` fires `clarity('event', eventName)` and sets each property as a custom tag via `clarity('set', key, value)`
|
|
273
|
+
- `identify()` calls `clarity('identify', userId)` with an optional friendly name from `traits.name`, and sets remaining traits as custom tags
|
|
274
|
+
- `page()` fires a `PageView` event and sets `pageUrl`, `pageName`, and `referrer` as custom tags
|
|
275
|
+
- SSR-safe: silently succeeds when `window` is undefined
|
|
276
|
+
|
|
277
|
+
#### Cookie consent
|
|
278
|
+
|
|
279
|
+
By default Clarity operates in cookieless mode. To enable cookie-based tracking, set `cookie: true`:
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
{
|
|
283
|
+
provider: 'clarity',
|
|
284
|
+
projectId: 'YOUR_PROJECT_ID',
|
|
285
|
+
cookie: true,
|
|
286
|
+
enabled: true,
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
This calls `clarity('consent')` during initialisation so Clarity can set cookies for more accurate session tracking.
|
|
291
|
+
|
|
292
|
+
## Bot Filtering
|
|
293
|
+
|
|
294
|
+
Set `ignoreBots: true` at the top level to silently drop all `track()`, `identify()`, and `page()` calls when the visitor is a known bot or crawler. Detection is powered by [`ua-parser-js`](https://github.com/nicolevanderhoeven/ua-parser-js)'s `isBot()` function.
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
const analytics = new Mytart({
|
|
298
|
+
ignoreBots: true,
|
|
299
|
+
providers: [
|
|
300
|
+
{ provider: 'google-analytics', measurementId: 'G-XXXXXXXXXX', enabled: true },
|
|
301
|
+
{ provider: 'segment', writeKey: 'YOUR_KEY', enabled: true },
|
|
302
|
+
],
|
|
303
|
+
});
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
When a bot is detected, all methods return an empty `TrackResult[]` array â no events are dispatched to any provider.
|
|
307
|
+
|
|
308
|
+
The User-Agent is read from:
|
|
309
|
+
|
|
310
|
+
1. `context.userAgent` if supplied in the `track()` call
|
|
311
|
+
2. `navigator.userAgent` in browser environments
|
|
312
|
+
|
|
313
|
+
If no User-Agent is available (e.g. server-side without `context.userAgent`), the call proceeds normally.
|
|
314
|
+
|
|
256
315
|
## API Reference
|
|
257
316
|
|
|
258
317
|
### `new Mytart(config: MytartConfig)`
|
|
@@ -263,6 +322,7 @@ interface MytartConfig {
|
|
|
263
322
|
defaultUserId?: string; // applied to every track/page call if no userId given
|
|
264
323
|
defaultAnonymousId?: string; // applied to every track/page call if no anonymousId given
|
|
265
324
|
debug?: boolean;
|
|
325
|
+
ignoreBots?: boolean; // when true, silently drops all tracking calls from known bots/crawlers
|
|
266
326
|
}
|
|
267
327
|
```
|
|
268
328
|
|
|
@@ -373,7 +433,7 @@ import type {
|
|
|
373
433
|
TrackResult, MytartError, EventContext, ProviderName, GoogleAnalyticsAppType,
|
|
374
434
|
GoogleAnalyticsConfig, ConsentSettings, ConsentState, MixpanelConfig, SegmentConfig,
|
|
375
435
|
AmplitudeConfig, PlausibleConfig, PostHogConfig, MetaPixelConfig, MetaPixelAppType,
|
|
376
|
-
MetaPixelAdvancedMatching,
|
|
436
|
+
MetaPixelAdvancedMatching, ClarityConfig,
|
|
377
437
|
} from 'mytart';
|
|
378
438
|
```
|
|
379
439
|
|
package/dist/index.d.mts
CHANGED
|
@@ -35,7 +35,7 @@ interface ConsentSettings {
|
|
|
35
35
|
/** Controls storage for security purposes (e.g. authentication). */
|
|
36
36
|
security_storage?: ConsentState;
|
|
37
37
|
}
|
|
38
|
-
type ProviderName = 'google-analytics' | 'mixpanel' | 'segment' | 'amplitude' | 'plausible' | 'posthog' | 'meta-pixel';
|
|
38
|
+
type ProviderName = 'google-analytics' | 'mixpanel' | 'segment' | 'amplitude' | 'plausible' | 'posthog' | 'meta-pixel' | 'clarity';
|
|
39
39
|
type GoogleAnalyticsAppType = 'browser' | 'server';
|
|
40
40
|
interface GoogleAnalyticsConfig extends BaseProviderConfig {
|
|
41
41
|
provider: 'google-analytics';
|
|
@@ -180,12 +180,34 @@ interface MetaPixelConfig extends BaseProviderConfig {
|
|
|
180
180
|
/** Enable Meta Pixel debug mode (`fbq('set', 'debug', true)`). */
|
|
181
181
|
debug?: boolean;
|
|
182
182
|
}
|
|
183
|
-
|
|
183
|
+
interface ClarityConfig extends BaseProviderConfig {
|
|
184
|
+
provider: 'clarity';
|
|
185
|
+
/** The Clarity project ID (from the Clarity dashboard). */
|
|
186
|
+
projectId: string;
|
|
187
|
+
/**
|
|
188
|
+
* Enable Clarity cookie consent mode. When `true`, calls
|
|
189
|
+
* `clarity('consent')` after initialisation so Clarity sets cookies.
|
|
190
|
+
* When omitted or `false`, Clarity operates in cookieless mode.
|
|
191
|
+
*/
|
|
192
|
+
cookie?: boolean;
|
|
193
|
+
}
|
|
194
|
+
type ProviderConfig = GoogleAnalyticsConfig | MixpanelConfig | SegmentConfig | AmplitudeConfig | PlausibleConfig | PostHogConfig | MetaPixelConfig | ClarityConfig;
|
|
184
195
|
interface MytartConfig {
|
|
185
196
|
providers: ProviderConfig[];
|
|
186
197
|
defaultUserId?: string;
|
|
187
198
|
defaultAnonymousId?: string;
|
|
188
199
|
debug?: boolean;
|
|
200
|
+
/**
|
|
201
|
+
* When `true`, silently drops all `track`, `identify`, and `page` calls
|
|
202
|
+
* if the visitor's User-Agent belongs to a known bot or crawler.
|
|
203
|
+
*
|
|
204
|
+
* Detection uses `isBot()` from `ua-parser-js`. The User-Agent is read
|
|
205
|
+
* from `context.userAgent` (if supplied) or `navigator.userAgent` in
|
|
206
|
+
* browser environments.
|
|
207
|
+
*
|
|
208
|
+
* Defaults to `false` (bots are tracked like any other visitor).
|
|
209
|
+
*/
|
|
210
|
+
ignoreBots?: boolean;
|
|
189
211
|
}
|
|
190
212
|
interface EventContext {
|
|
191
213
|
ip?: string;
|
|
@@ -238,6 +260,11 @@ declare class Mytart {
|
|
|
238
260
|
private readonly providers;
|
|
239
261
|
private readonly config;
|
|
240
262
|
constructor(config: MytartConfig);
|
|
263
|
+
/**
|
|
264
|
+
* Returns `true` when `ignoreBots` is enabled and the given (or detected)
|
|
265
|
+
* User-Agent belongs to a known bot or crawler.
|
|
266
|
+
*/
|
|
267
|
+
private isBotRequest;
|
|
241
268
|
track(options: TrackOptions): Promise<TrackResult[]>;
|
|
242
269
|
identify(options: IdentifyOptions): Promise<TrackResult[]>;
|
|
243
270
|
page(options: PageOptions): Promise<TrackResult[]>;
|
|
@@ -470,4 +497,33 @@ declare class MetaPixelProvider extends BaseProvider {
|
|
|
470
497
|
page(options: PageOptions): Promise<TrackResult>;
|
|
471
498
|
}
|
|
472
499
|
|
|
473
|
-
|
|
500
|
+
declare global {
|
|
501
|
+
interface Window {
|
|
502
|
+
clarity: ClarityFn & {
|
|
503
|
+
q?: unknown[][];
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
type ClarityFn = (...args: unknown[]) => void;
|
|
508
|
+
declare class ClarityProvider extends BaseProvider {
|
|
509
|
+
readonly name = "clarity";
|
|
510
|
+
private readonly config;
|
|
511
|
+
private clarityReady;
|
|
512
|
+
constructor(config: ClarityConfig);
|
|
513
|
+
/**
|
|
514
|
+
* Injects the official Clarity tracking snippet. Mirrors:
|
|
515
|
+
*
|
|
516
|
+
* (function(c,l,a,r,i,t,y){
|
|
517
|
+
* c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
|
|
518
|
+
* t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
|
|
519
|
+
* y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
|
|
520
|
+
* })(window, document, "clarity", "script", "PROJECT_ID");
|
|
521
|
+
*/
|
|
522
|
+
private initClarity;
|
|
523
|
+
private ensureClarity;
|
|
524
|
+
track(options: TrackOptions): Promise<TrackResult>;
|
|
525
|
+
identify(options: IdentifyOptions): Promise<TrackResult>;
|
|
526
|
+
page(options: PageOptions): Promise<TrackResult>;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
export { type AmplitudeConfig, AmplitudeProvider, BaseProvider, type BaseProviderConfig, type ClarityConfig, ClarityProvider, type ConsentSettings, type ConsentState, type EventContext, type GoogleAnalyticsAppType, type GoogleAnalyticsConfig, GoogleAnalyticsProvider, type IdentifyOptions, type MetaPixelAdvancedMatching, type MetaPixelAppType, type MetaPixelConfig, MetaPixelProvider, type MixpanelConfig, MixpanelProvider, Mytart, type MytartConfig, type MytartError, type PageOptions, type PlausibleConfig, PlausibleProvider, type PostHogConfig, PostHogProvider, type ProviderConfig, type ProviderName, type SegmentConfig, SegmentProvider, type TrackOptions, type TrackResult };
|
package/dist/index.d.ts
CHANGED
|
@@ -35,7 +35,7 @@ interface ConsentSettings {
|
|
|
35
35
|
/** Controls storage for security purposes (e.g. authentication). */
|
|
36
36
|
security_storage?: ConsentState;
|
|
37
37
|
}
|
|
38
|
-
type ProviderName = 'google-analytics' | 'mixpanel' | 'segment' | 'amplitude' | 'plausible' | 'posthog' | 'meta-pixel';
|
|
38
|
+
type ProviderName = 'google-analytics' | 'mixpanel' | 'segment' | 'amplitude' | 'plausible' | 'posthog' | 'meta-pixel' | 'clarity';
|
|
39
39
|
type GoogleAnalyticsAppType = 'browser' | 'server';
|
|
40
40
|
interface GoogleAnalyticsConfig extends BaseProviderConfig {
|
|
41
41
|
provider: 'google-analytics';
|
|
@@ -180,12 +180,34 @@ interface MetaPixelConfig extends BaseProviderConfig {
|
|
|
180
180
|
/** Enable Meta Pixel debug mode (`fbq('set', 'debug', true)`). */
|
|
181
181
|
debug?: boolean;
|
|
182
182
|
}
|
|
183
|
-
|
|
183
|
+
interface ClarityConfig extends BaseProviderConfig {
|
|
184
|
+
provider: 'clarity';
|
|
185
|
+
/** The Clarity project ID (from the Clarity dashboard). */
|
|
186
|
+
projectId: string;
|
|
187
|
+
/**
|
|
188
|
+
* Enable Clarity cookie consent mode. When `true`, calls
|
|
189
|
+
* `clarity('consent')` after initialisation so Clarity sets cookies.
|
|
190
|
+
* When omitted or `false`, Clarity operates in cookieless mode.
|
|
191
|
+
*/
|
|
192
|
+
cookie?: boolean;
|
|
193
|
+
}
|
|
194
|
+
type ProviderConfig = GoogleAnalyticsConfig | MixpanelConfig | SegmentConfig | AmplitudeConfig | PlausibleConfig | PostHogConfig | MetaPixelConfig | ClarityConfig;
|
|
184
195
|
interface MytartConfig {
|
|
185
196
|
providers: ProviderConfig[];
|
|
186
197
|
defaultUserId?: string;
|
|
187
198
|
defaultAnonymousId?: string;
|
|
188
199
|
debug?: boolean;
|
|
200
|
+
/**
|
|
201
|
+
* When `true`, silently drops all `track`, `identify`, and `page` calls
|
|
202
|
+
* if the visitor's User-Agent belongs to a known bot or crawler.
|
|
203
|
+
*
|
|
204
|
+
* Detection uses `isBot()` from `ua-parser-js`. The User-Agent is read
|
|
205
|
+
* from `context.userAgent` (if supplied) or `navigator.userAgent` in
|
|
206
|
+
* browser environments.
|
|
207
|
+
*
|
|
208
|
+
* Defaults to `false` (bots are tracked like any other visitor).
|
|
209
|
+
*/
|
|
210
|
+
ignoreBots?: boolean;
|
|
189
211
|
}
|
|
190
212
|
interface EventContext {
|
|
191
213
|
ip?: string;
|
|
@@ -238,6 +260,11 @@ declare class Mytart {
|
|
|
238
260
|
private readonly providers;
|
|
239
261
|
private readonly config;
|
|
240
262
|
constructor(config: MytartConfig);
|
|
263
|
+
/**
|
|
264
|
+
* Returns `true` when `ignoreBots` is enabled and the given (or detected)
|
|
265
|
+
* User-Agent belongs to a known bot or crawler.
|
|
266
|
+
*/
|
|
267
|
+
private isBotRequest;
|
|
241
268
|
track(options: TrackOptions): Promise<TrackResult[]>;
|
|
242
269
|
identify(options: IdentifyOptions): Promise<TrackResult[]>;
|
|
243
270
|
page(options: PageOptions): Promise<TrackResult[]>;
|
|
@@ -470,4 +497,33 @@ declare class MetaPixelProvider extends BaseProvider {
|
|
|
470
497
|
page(options: PageOptions): Promise<TrackResult>;
|
|
471
498
|
}
|
|
472
499
|
|
|
473
|
-
|
|
500
|
+
declare global {
|
|
501
|
+
interface Window {
|
|
502
|
+
clarity: ClarityFn & {
|
|
503
|
+
q?: unknown[][];
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
type ClarityFn = (...args: unknown[]) => void;
|
|
508
|
+
declare class ClarityProvider extends BaseProvider {
|
|
509
|
+
readonly name = "clarity";
|
|
510
|
+
private readonly config;
|
|
511
|
+
private clarityReady;
|
|
512
|
+
constructor(config: ClarityConfig);
|
|
513
|
+
/**
|
|
514
|
+
* Injects the official Clarity tracking snippet. Mirrors:
|
|
515
|
+
*
|
|
516
|
+
* (function(c,l,a,r,i,t,y){
|
|
517
|
+
* c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
|
|
518
|
+
* t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
|
|
519
|
+
* y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
|
|
520
|
+
* })(window, document, "clarity", "script", "PROJECT_ID");
|
|
521
|
+
*/
|
|
522
|
+
private initClarity;
|
|
523
|
+
private ensureClarity;
|
|
524
|
+
track(options: TrackOptions): Promise<TrackResult>;
|
|
525
|
+
identify(options: IdentifyOptions): Promise<TrackResult>;
|
|
526
|
+
page(options: PageOptions): Promise<TrackResult>;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
export { type AmplitudeConfig, AmplitudeProvider, BaseProvider, type BaseProviderConfig, type ClarityConfig, ClarityProvider, type ConsentSettings, type ConsentState, type EventContext, type GoogleAnalyticsAppType, type GoogleAnalyticsConfig, GoogleAnalyticsProvider, type IdentifyOptions, type MetaPixelAdvancedMatching, type MetaPixelAppType, type MetaPixelConfig, MetaPixelProvider, type MixpanelConfig, MixpanelProvider, Mytart, type MytartConfig, type MytartError, type PageOptions, type PlausibleConfig, PlausibleProvider, type PostHogConfig, PostHogProvider, type ProviderConfig, type ProviderName, type SegmentConfig, SegmentProvider, type TrackOptions, type TrackResult };
|
package/dist/index.js
CHANGED
|
@@ -32,6 +32,7 @@ var index_exports = {};
|
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
AmplitudeProvider: () => AmplitudeProvider,
|
|
34
34
|
BaseProvider: () => BaseProvider,
|
|
35
|
+
ClarityProvider: () => ClarityProvider,
|
|
35
36
|
GoogleAnalyticsProvider: () => GoogleAnalyticsProvider,
|
|
36
37
|
MetaPixelProvider: () => MetaPixelProvider,
|
|
37
38
|
MixpanelProvider: () => MixpanelProvider,
|
|
@@ -42,6 +43,9 @@ __export(index_exports, {
|
|
|
42
43
|
});
|
|
43
44
|
module.exports = __toCommonJS(index_exports);
|
|
44
45
|
|
|
46
|
+
// src/mytart.ts
|
|
47
|
+
var import_bot_detection = require("ua-parser-js/bot-detection");
|
|
48
|
+
|
|
45
49
|
// src/providers/base.ts
|
|
46
50
|
var BaseProvider = class {
|
|
47
51
|
/**
|
|
@@ -1092,6 +1096,107 @@ var MetaPixelProvider = class extends BaseProvider {
|
|
|
1092
1096
|
}
|
|
1093
1097
|
};
|
|
1094
1098
|
|
|
1099
|
+
// src/providers/clarity.ts
|
|
1100
|
+
var CLARITY_SCRIPT_BASE = "https://www.clarity.ms/tag/";
|
|
1101
|
+
var ClarityProvider = class extends BaseProvider {
|
|
1102
|
+
constructor(config) {
|
|
1103
|
+
super();
|
|
1104
|
+
this.name = "clarity";
|
|
1105
|
+
this.clarityReady = null;
|
|
1106
|
+
this.config = config;
|
|
1107
|
+
}
|
|
1108
|
+
/**
|
|
1109
|
+
* Injects the official Clarity tracking snippet. Mirrors:
|
|
1110
|
+
*
|
|
1111
|
+
* (function(c,l,a,r,i,t,y){
|
|
1112
|
+
* c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
|
|
1113
|
+
* t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
|
|
1114
|
+
* y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
|
|
1115
|
+
* })(window, document, "clarity", "script", "PROJECT_ID");
|
|
1116
|
+
*/
|
|
1117
|
+
initClarity() {
|
|
1118
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
1119
|
+
return Promise.resolve();
|
|
1120
|
+
}
|
|
1121
|
+
if (!window.clarity) {
|
|
1122
|
+
const q = [];
|
|
1123
|
+
const fn = function clarity(...args) {
|
|
1124
|
+
q.push(args);
|
|
1125
|
+
};
|
|
1126
|
+
fn.q = q;
|
|
1127
|
+
window.clarity = fn;
|
|
1128
|
+
}
|
|
1129
|
+
if (this.config.cookie) {
|
|
1130
|
+
window.clarity("consent");
|
|
1131
|
+
}
|
|
1132
|
+
return new Promise((resolve) => {
|
|
1133
|
+
const script = document.createElement("script");
|
|
1134
|
+
script.async = true;
|
|
1135
|
+
script.src = CLARITY_SCRIPT_BASE + this.config.projectId;
|
|
1136
|
+
script.onload = () => resolve();
|
|
1137
|
+
script.onerror = () => resolve();
|
|
1138
|
+
document.head.appendChild(script);
|
|
1139
|
+
});
|
|
1140
|
+
}
|
|
1141
|
+
ensureClarity() {
|
|
1142
|
+
if (!this.clarityReady) {
|
|
1143
|
+
this.clarityReady = this.initClarity();
|
|
1144
|
+
}
|
|
1145
|
+
return this.clarityReady;
|
|
1146
|
+
}
|
|
1147
|
+
async track(options) {
|
|
1148
|
+
if (typeof window === "undefined") {
|
|
1149
|
+
return this.buildSuccess(200);
|
|
1150
|
+
}
|
|
1151
|
+
await this.ensureClarity();
|
|
1152
|
+
window.clarity("event", options.event);
|
|
1153
|
+
if (options.properties) {
|
|
1154
|
+
for (const [key, value] of Object.entries(options.properties)) {
|
|
1155
|
+
window.clarity("set", key, String(value));
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
return this.buildSuccess(200);
|
|
1159
|
+
}
|
|
1160
|
+
async identify(options) {
|
|
1161
|
+
if (typeof window === "undefined") {
|
|
1162
|
+
return this.buildSuccess(200);
|
|
1163
|
+
}
|
|
1164
|
+
await this.ensureClarity();
|
|
1165
|
+
const friendlyName = options.traits?.name ?? void 0;
|
|
1166
|
+
window.clarity("identify", options.userId, void 0, void 0, friendlyName);
|
|
1167
|
+
if (options.traits) {
|
|
1168
|
+
for (const [key, value] of Object.entries(options.traits)) {
|
|
1169
|
+
if (key !== "name") {
|
|
1170
|
+
window.clarity("set", key, String(value));
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
return this.buildSuccess(200);
|
|
1175
|
+
}
|
|
1176
|
+
async page(options) {
|
|
1177
|
+
if (typeof window === "undefined") {
|
|
1178
|
+
return this.buildSuccess(200);
|
|
1179
|
+
}
|
|
1180
|
+
await this.ensureClarity();
|
|
1181
|
+
window.clarity("event", "PageView");
|
|
1182
|
+
if (options.url) {
|
|
1183
|
+
window.clarity("set", "pageUrl", options.url);
|
|
1184
|
+
}
|
|
1185
|
+
if (options.name) {
|
|
1186
|
+
window.clarity("set", "pageName", options.name);
|
|
1187
|
+
}
|
|
1188
|
+
if (options.referrer) {
|
|
1189
|
+
window.clarity("set", "referrer", options.referrer);
|
|
1190
|
+
}
|
|
1191
|
+
if (options.properties) {
|
|
1192
|
+
for (const [key, value] of Object.entries(options.properties)) {
|
|
1193
|
+
window.clarity("set", key, String(value));
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
return this.buildSuccess(200);
|
|
1197
|
+
}
|
|
1198
|
+
};
|
|
1199
|
+
|
|
1095
1200
|
// src/mytart.ts
|
|
1096
1201
|
function createProvider(config) {
|
|
1097
1202
|
switch (config.provider) {
|
|
@@ -1109,6 +1214,8 @@ function createProvider(config) {
|
|
|
1109
1214
|
return new PostHogProvider(config);
|
|
1110
1215
|
case "meta-pixel":
|
|
1111
1216
|
return new MetaPixelProvider(config);
|
|
1217
|
+
case "clarity":
|
|
1218
|
+
return new ClarityProvider(config);
|
|
1112
1219
|
default: {
|
|
1113
1220
|
const exhaustive = config;
|
|
1114
1221
|
throw new Error(`Unknown provider: ${exhaustive.provider}`);
|
|
@@ -1120,7 +1227,17 @@ var Mytart = class {
|
|
|
1120
1227
|
this.config = config;
|
|
1121
1228
|
this.providers = config.providers.filter((c) => c.enabled === true).map(createProvider);
|
|
1122
1229
|
}
|
|
1230
|
+
/**
|
|
1231
|
+
* Returns `true` when `ignoreBots` is enabled and the given (or detected)
|
|
1232
|
+
* User-Agent belongs to a known bot or crawler.
|
|
1233
|
+
*/
|
|
1234
|
+
isBotRequest(userAgent) {
|
|
1235
|
+
if (!this.config.ignoreBots) return false;
|
|
1236
|
+
const ua = userAgent ?? (typeof navigator !== "undefined" ? navigator.userAgent : void 0);
|
|
1237
|
+
return ua ? (0, import_bot_detection.isBot)(ua) : false;
|
|
1238
|
+
}
|
|
1123
1239
|
async track(options) {
|
|
1240
|
+
if (this.isBotRequest(options.context?.userAgent)) return [];
|
|
1124
1241
|
const enriched = {
|
|
1125
1242
|
userId: this.config.defaultUserId,
|
|
1126
1243
|
anonymousId: this.config.defaultAnonymousId,
|
|
@@ -1129,9 +1246,11 @@ var Mytart = class {
|
|
|
1129
1246
|
return Promise.all(this.providers.map((p) => p.track(enriched)));
|
|
1130
1247
|
}
|
|
1131
1248
|
async identify(options) {
|
|
1249
|
+
if (this.isBotRequest()) return [];
|
|
1132
1250
|
return Promise.all(this.providers.map((p) => p.identify(options)));
|
|
1133
1251
|
}
|
|
1134
1252
|
async page(options) {
|
|
1253
|
+
if (this.isBotRequest()) return [];
|
|
1135
1254
|
const enriched = {
|
|
1136
1255
|
userId: this.config.defaultUserId,
|
|
1137
1256
|
anonymousId: this.config.defaultAnonymousId,
|
|
@@ -1169,6 +1288,7 @@ var Mytart = class {
|
|
|
1169
1288
|
0 && (module.exports = {
|
|
1170
1289
|
AmplitudeProvider,
|
|
1171
1290
|
BaseProvider,
|
|
1291
|
+
ClarityProvider,
|
|
1172
1292
|
GoogleAnalyticsProvider,
|
|
1173
1293
|
MetaPixelProvider,
|
|
1174
1294
|
MixpanelProvider,
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// src/mytart.ts
|
|
2
|
+
import { isBot } from "ua-parser-js/bot-detection";
|
|
3
|
+
|
|
1
4
|
// src/providers/base.ts
|
|
2
5
|
var BaseProvider = class {
|
|
3
6
|
/**
|
|
@@ -1048,6 +1051,107 @@ var MetaPixelProvider = class extends BaseProvider {
|
|
|
1048
1051
|
}
|
|
1049
1052
|
};
|
|
1050
1053
|
|
|
1054
|
+
// src/providers/clarity.ts
|
|
1055
|
+
var CLARITY_SCRIPT_BASE = "https://www.clarity.ms/tag/";
|
|
1056
|
+
var ClarityProvider = class extends BaseProvider {
|
|
1057
|
+
constructor(config) {
|
|
1058
|
+
super();
|
|
1059
|
+
this.name = "clarity";
|
|
1060
|
+
this.clarityReady = null;
|
|
1061
|
+
this.config = config;
|
|
1062
|
+
}
|
|
1063
|
+
/**
|
|
1064
|
+
* Injects the official Clarity tracking snippet. Mirrors:
|
|
1065
|
+
*
|
|
1066
|
+
* (function(c,l,a,r,i,t,y){
|
|
1067
|
+
* c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
|
|
1068
|
+
* t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
|
|
1069
|
+
* y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
|
|
1070
|
+
* })(window, document, "clarity", "script", "PROJECT_ID");
|
|
1071
|
+
*/
|
|
1072
|
+
initClarity() {
|
|
1073
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
1074
|
+
return Promise.resolve();
|
|
1075
|
+
}
|
|
1076
|
+
if (!window.clarity) {
|
|
1077
|
+
const q = [];
|
|
1078
|
+
const fn = function clarity(...args) {
|
|
1079
|
+
q.push(args);
|
|
1080
|
+
};
|
|
1081
|
+
fn.q = q;
|
|
1082
|
+
window.clarity = fn;
|
|
1083
|
+
}
|
|
1084
|
+
if (this.config.cookie) {
|
|
1085
|
+
window.clarity("consent");
|
|
1086
|
+
}
|
|
1087
|
+
return new Promise((resolve) => {
|
|
1088
|
+
const script = document.createElement("script");
|
|
1089
|
+
script.async = true;
|
|
1090
|
+
script.src = CLARITY_SCRIPT_BASE + this.config.projectId;
|
|
1091
|
+
script.onload = () => resolve();
|
|
1092
|
+
script.onerror = () => resolve();
|
|
1093
|
+
document.head.appendChild(script);
|
|
1094
|
+
});
|
|
1095
|
+
}
|
|
1096
|
+
ensureClarity() {
|
|
1097
|
+
if (!this.clarityReady) {
|
|
1098
|
+
this.clarityReady = this.initClarity();
|
|
1099
|
+
}
|
|
1100
|
+
return this.clarityReady;
|
|
1101
|
+
}
|
|
1102
|
+
async track(options) {
|
|
1103
|
+
if (typeof window === "undefined") {
|
|
1104
|
+
return this.buildSuccess(200);
|
|
1105
|
+
}
|
|
1106
|
+
await this.ensureClarity();
|
|
1107
|
+
window.clarity("event", options.event);
|
|
1108
|
+
if (options.properties) {
|
|
1109
|
+
for (const [key, value] of Object.entries(options.properties)) {
|
|
1110
|
+
window.clarity("set", key, String(value));
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
return this.buildSuccess(200);
|
|
1114
|
+
}
|
|
1115
|
+
async identify(options) {
|
|
1116
|
+
if (typeof window === "undefined") {
|
|
1117
|
+
return this.buildSuccess(200);
|
|
1118
|
+
}
|
|
1119
|
+
await this.ensureClarity();
|
|
1120
|
+
const friendlyName = options.traits?.name ?? void 0;
|
|
1121
|
+
window.clarity("identify", options.userId, void 0, void 0, friendlyName);
|
|
1122
|
+
if (options.traits) {
|
|
1123
|
+
for (const [key, value] of Object.entries(options.traits)) {
|
|
1124
|
+
if (key !== "name") {
|
|
1125
|
+
window.clarity("set", key, String(value));
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
return this.buildSuccess(200);
|
|
1130
|
+
}
|
|
1131
|
+
async page(options) {
|
|
1132
|
+
if (typeof window === "undefined") {
|
|
1133
|
+
return this.buildSuccess(200);
|
|
1134
|
+
}
|
|
1135
|
+
await this.ensureClarity();
|
|
1136
|
+
window.clarity("event", "PageView");
|
|
1137
|
+
if (options.url) {
|
|
1138
|
+
window.clarity("set", "pageUrl", options.url);
|
|
1139
|
+
}
|
|
1140
|
+
if (options.name) {
|
|
1141
|
+
window.clarity("set", "pageName", options.name);
|
|
1142
|
+
}
|
|
1143
|
+
if (options.referrer) {
|
|
1144
|
+
window.clarity("set", "referrer", options.referrer);
|
|
1145
|
+
}
|
|
1146
|
+
if (options.properties) {
|
|
1147
|
+
for (const [key, value] of Object.entries(options.properties)) {
|
|
1148
|
+
window.clarity("set", key, String(value));
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
return this.buildSuccess(200);
|
|
1152
|
+
}
|
|
1153
|
+
};
|
|
1154
|
+
|
|
1051
1155
|
// src/mytart.ts
|
|
1052
1156
|
function createProvider(config) {
|
|
1053
1157
|
switch (config.provider) {
|
|
@@ -1065,6 +1169,8 @@ function createProvider(config) {
|
|
|
1065
1169
|
return new PostHogProvider(config);
|
|
1066
1170
|
case "meta-pixel":
|
|
1067
1171
|
return new MetaPixelProvider(config);
|
|
1172
|
+
case "clarity":
|
|
1173
|
+
return new ClarityProvider(config);
|
|
1068
1174
|
default: {
|
|
1069
1175
|
const exhaustive = config;
|
|
1070
1176
|
throw new Error(`Unknown provider: ${exhaustive.provider}`);
|
|
@@ -1076,7 +1182,17 @@ var Mytart = class {
|
|
|
1076
1182
|
this.config = config;
|
|
1077
1183
|
this.providers = config.providers.filter((c) => c.enabled === true).map(createProvider);
|
|
1078
1184
|
}
|
|
1185
|
+
/**
|
|
1186
|
+
* Returns `true` when `ignoreBots` is enabled and the given (or detected)
|
|
1187
|
+
* User-Agent belongs to a known bot or crawler.
|
|
1188
|
+
*/
|
|
1189
|
+
isBotRequest(userAgent) {
|
|
1190
|
+
if (!this.config.ignoreBots) return false;
|
|
1191
|
+
const ua = userAgent ?? (typeof navigator !== "undefined" ? navigator.userAgent : void 0);
|
|
1192
|
+
return ua ? isBot(ua) : false;
|
|
1193
|
+
}
|
|
1079
1194
|
async track(options) {
|
|
1195
|
+
if (this.isBotRequest(options.context?.userAgent)) return [];
|
|
1080
1196
|
const enriched = {
|
|
1081
1197
|
userId: this.config.defaultUserId,
|
|
1082
1198
|
anonymousId: this.config.defaultAnonymousId,
|
|
@@ -1085,9 +1201,11 @@ var Mytart = class {
|
|
|
1085
1201
|
return Promise.all(this.providers.map((p) => p.track(enriched)));
|
|
1086
1202
|
}
|
|
1087
1203
|
async identify(options) {
|
|
1204
|
+
if (this.isBotRequest()) return [];
|
|
1088
1205
|
return Promise.all(this.providers.map((p) => p.identify(options)));
|
|
1089
1206
|
}
|
|
1090
1207
|
async page(options) {
|
|
1208
|
+
if (this.isBotRequest()) return [];
|
|
1091
1209
|
const enriched = {
|
|
1092
1210
|
userId: this.config.defaultUserId,
|
|
1093
1211
|
anonymousId: this.config.defaultAnonymousId,
|
|
@@ -1124,6 +1242,7 @@ var Mytart = class {
|
|
|
1124
1242
|
export {
|
|
1125
1243
|
AmplitudeProvider,
|
|
1126
1244
|
BaseProvider,
|
|
1245
|
+
ClarityProvider,
|
|
1127
1246
|
GoogleAnalyticsProvider,
|
|
1128
1247
|
MetaPixelProvider,
|
|
1129
1248
|
MixpanelProvider,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mytart",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Multi-Yield Tracking & Analytics Relay Tool â framework-agnostic analytics for any project",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"analytics",
|
|
@@ -35,7 +35,8 @@
|
|
|
35
35
|
"node": ">=18"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"axios": "^1.7.0"
|
|
38
|
+
"axios": "^1.7.0",
|
|
39
|
+
"ua-parser-js": "^2.0.9"
|
|
39
40
|
},
|
|
40
41
|
"devDependencies": {
|
|
41
42
|
"@types/jest": "^29.5.0",
|