diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 53ee29cf..da1c7f04 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -14,6 +14,7 @@ import { version as i18nVersion } from '../../packages/i18n/package.json'; import { version as autoIconsVersion } from '../../packages/auto-icons/package.json'; import { version as unocssVersion } from '../../packages/unocss/package.json'; import { version as storageVersion } from '../../packages/storage/package.json'; +import { version as analyticsVersion } from '../../packages/analytics/package.json'; const title = 'Next-gen Web Extension Framework'; const titleSuffix = ' – WXT'; @@ -23,6 +24,14 @@ const ogTitle = `${title}${titleSuffix}`; const ogUrl = 'https://wxt.dev'; const ogImage = 'https://wxt.dev/social-preview.png'; +const otherPackages = { + analytics: analyticsVersion, + 'auto-icons': autoIconsVersion, + i18n: i18nVersion, + storage: storageVersion, + unocss: unocssVersion, +}; + // https://vitepress.dev/reference/site-config export default defineConfig({ titleTemplate: `:title${titleSuffix}`, @@ -97,12 +106,12 @@ export default defineConfig({ 'https://github.com/wxt-dev/wxt/blob/main/packages/wxt/CHANGELOG.md', ), ]), - navItem('Other Packages', [ - navItem(`@wxt-dev/storage — ${storageVersion}`, '/storage'), - navItem(`@wxt-dev/auto-icons — ${autoIconsVersion}`, '/auto-icons'), - navItem(`@wxt-dev/i18n — ${i18nVersion}`, '/i18n'), - navItem(`@wxt-dev/unocss — ${unocssVersion}`, '/unocss'), - ]), + navItem( + 'Other Packages', + Object.entries(otherPackages).map(([name, version]) => + navItem(`@wxt-dev/${name} — ${version}`, `/${name}`), + ), + ), ]), ], diff --git a/packages/analytics/README.md b/packages/analytics/README.md index f3c7b953..aaa300f0 100644 --- a/packages/analytics/README.md +++ b/packages/analytics/README.md @@ -172,3 +172,98 @@ export default defineAppConfig({ ``` Example `AnalyticsProvider` implementations can be found at [`./modules/analytics/providers`](https://github.com/wxt-dev/wxt/tree/main/packages/analytics/modules/analytics/providers). + +## User Properties + +User ID and properties are stored in `browser.storage.local`. To change this or customize where these values are stored, use the `userId` and `userProperties` config: + +```ts +// app.config.ts +import { storage } from 'wxt/storage'; + +export default defineAppConfig({ + analytics: { + userId: storage.defineItem('local:custom-user-id-key'), + userProperties: storage.defineItem('local:custom-user-properties-key'), + }, +}); +``` + +To set the values at runtime, use the `identify` function: + +```ts +await analytics.identify(userId, userProperties); +``` + +Alternatively, a common pattern is to use a random string as the user ID. This keeps the actual user information private, while still providing useful metrics in your analytics platform. This can be done very easily using WXT's storage API: + +```ts +// app.config.ts +import { storage } from 'wxt/storage'; + +export default defineAppConfig({ + analytics: { + userId: storage.defineItem('local:custom-user-id-key', { + init: () => crypto.randomUUID(), + }), + }, +}); +``` + +If you aren't using `wxt` or `@wxt-dev/storage`, you can define custom implementations for the `userId` and `userProperties` config: + +```ts +const analytics = createAnalytics({ + userId: { + getValue: () => ..., + setValue: (userId) => ..., + } +}) +``` + +## Auto-track UI events + +Call `analytics.autoTrack(container)` to automatically track UI events so you don't have to manually add them. Currently it: + +- Tracks clicks to elements inside the `container` + +In your extension's HTML pages, you'll want to call it with `document`: + +```ts +analytics.autoTrack(document); +``` + +But in content scripts, you usually only care about interactions with your own UI: + +```ts +const ui = createIntegratedUi({ + // ... + onMount(container) { + analytics.autoTrack(container); + }, +}); +ui.mount(); +``` + +### Enabling/Disabling + +By default, **analytics is disabled**. You can configure how the value is stored (and change the default value) via the `enabled` config: + +```ts +// app.config.ts +import { storage } from 'wxt/storage'; + +export default defineAppConfig({ + analytics: { + enabled: storage.defineItem('local:analytics-enabled', { + fallback: true, + }), + }, +}); +``` + +At runtime, you can call `setEnabled` to change the value: + +```ts +analytics.setEnabled(true); +``` diff --git a/packages/analytics/modules/analytics/types.ts b/packages/analytics/modules/analytics/types.ts index 9a6d3502..d14d59f8 100644 --- a/packages/analytics/modules/analytics/types.ts +++ b/packages/analytics/modules/analytics/types.ts @@ -1,13 +1,13 @@ export interface Analytics { - /** Report a page change */ + /** Report a page change. */ page: (url: string) => void; - /** Report a custom event */ + /** Report a custom event. */ track: (eventName: string, eventProperties?: Record) => void; - /** Save information about the user */ + /** Save information about the user. */ identify: (userId: string, userProperties?: Record) => void; /** Automatically setup and track user interactions, returning a function to remove any listeners that were setup. */ autoTrack: (root: Document | ShadowRoot | Element) => () => void; - /** Calls `config.enabled.setValue` */ + /** Calls `config.enabled.setValue`. */ setEnabled: (enabled: boolean) => void; } @@ -21,19 +21,20 @@ export interface AnalyticsConfig { */ debug?: boolean; /** - * Extension version, defaults to `browser.runtime.getManifest().version`. + * Your extension's version, reported alongside events. + * @default browser.runtime.getManifest().version`. */ version?: string; /** - * Configure how the enabled flag is persisted. Defaults to using `""` in local extension storage. + * Configure how the enabled flag is persisted. Defaults to using `browser.storage.local`. */ enabled?: AnalyticsStorageItem; /** - * Configure how the user Id is persisted + * Configure how the user Id is persisted. Defaults to using `browser.storage.local`. */ userId?: AnalyticsStorageItem; /** - * Configure how user properties are persisted + * Configure how user properties are persisted. Defaults to using `browser.storage.local`. */ userProperties?: AnalyticsStorageItem>; } @@ -47,11 +48,11 @@ export type AnalyticsProvider = ( analytics: Analytics, config: AnalyticsConfig, ) => { - /** Upload a page view event */ + /** Upload a page view event. */ page: (event: AnalyticsPageViewEvent) => Promise; - /** Upload a custom event */ + /** Upload a custom event. */ track: (event: AnalyticsTrackEvent) => Promise; - /** Upload information about the user */ + /** Upload information about the user. */ identify: (event: BaseAnalyticsEvent) => Promise; }; @@ -64,11 +65,11 @@ export interface BaseAnalyticsEvent { } export interface AnalyticsEventMetadata { - /** Identifier of the session the event was fired from */ + /** Identifier of the session the event was fired from. */ sessionId: number | undefined; - /** `Date.now()` of when the event was reported */ + /** `Date.now()` of when the event was reported. */ timestamp: number; - /** `"1920x1080"` */ + /** Ex: `"1920x1080"`. */ screen: string | undefined; /** `document.referrer` */ referrer: string | undefined;