@jaseeey/vue-umami-plugin
Version:
A plugin designed for Vue 3 which enables the use of Umami Analytics
219 lines (218 loc) • 9.19 kB
TypeScript
/**
* Configuration for {@link VueUmamiPlugin}.
*
* `router` is typed as {@link UmamiRouterLike} rather than Vue Router's `Router` so this package never depends on (or
* pins) a specific `vue-router` version. Any object that matches the structural contract is accepted, including Vue
* Router instances and test doubles.
*/
export type UmamiPluginOptions = {
/**
* Umami website ID applied as `data-website-id` on the script tag. Required by the type. At runtime an empty or
* missing value skips installation and logs a console warning.
*/
websiteID: string;
/**
* URL of the Umami tracker script (cloud or self-hosted).
* @defaultValue `https://us.umami.is/script.js`
*/
scriptSrc?: string;
/**
* Optional router used for SPA page-view tracking via `afterEach`. Typically a Vue Router instance; see
* {@link UmamiRouterLike}. Omit when you track page views manually with {@link trackUmamiPageView} or rely only on
* Umami's built-in auto-tracking.
*/
router?: UmamiRouterLike;
/**
* When `true`, allow installation when `window.location.hostname` includes the substring `localhost` (for example
* `localhost` or `app.localhost`). Hostnames such as `127.0.0.1` are not matched by this check. Without this flag
* the plugin skips install on matching hosts because Umami typically rejects localhost traffic.
* @defaultValue `false`
*/
allowLocalhost?: boolean;
/**
* When `true`, sets `data-auto-track="true"` for Umami's built-in tracking. When a router is supplied, the plugin
* continues forwarding every router navigation to avoid missing browser history or hash changes. This can overlap
* with Umami's built-in tracking, so `false` is recommended when the router is the page-view source. Invalid
* non-boolean values fall back to `false` and are treated as an explicit option (so they win over
* `extraDataAttributes['data-auto-track']`).
* @defaultValue `false`
*/
autoTrack?: boolean;
/**
* When `true`, logs a console message after the tracker script loads successfully. Failed loads always warn
* regardless of this flag.
* @defaultValue `false`
*/
debug?: boolean;
/**
* Maximum number of track/identify calls kept while `window.umami` is unavailable. Oldest items are dropped when
* the limit is reached, including if installation lowers the cap below calls that are already queued. Must be a
* finite number `>= 1`; invalid values fall back to `100`.
* @defaultValue `100`
*/
maxQueuedEvents?: number;
/**
* Extra `data-*` attributes applied to the injected script after the defaults (for example `data-host-url`,
* `data-domains`, `data-performance`). `data-website-id` and the plugin marker attribute cannot be overridden.
* `data-auto-track` can only be set here when {@link UmamiPluginOptions.autoTrack} is not explicitly provided.
* Non-`data-*` keys are ignored.
* @defaultValue `{}`
*/
extraDataAttributes?: Record<string, string>;
};
/**
* Minimal route shape used for automatic page tracking.
*
* Only `fullPath` is read when a navigation is forwarded to Umami.
*/
export type UmamiRouteLike = {
/** Full path (including query and hash) used as the tracked page URL. */
fullPath: string;
};
/**
* Structural router contract for optional SPA page-view tracking.
*
* Intentionally not imported from `vue-router`: the plugin only needs `afterEach` and a route with `fullPath`.
* Structural typing keeps `vue-router` out of this package's dependency graph, avoids peer-dep version conflicts, and
* still accepts real Vue Router instances because they satisfy this shape.
*/
export type UmamiRouterLike = {
/**
* Registers a handler invoked after each navigation. The plugin only requires the `to` argument.
*/
afterEach: (handler: (to: UmamiRouteLike) => void) => unknown;
};
/** Custom event name passed to Umami's `track` API. */
export type UmamiTrackEvent = string;
/** Optional event payload object for {@link trackUmamiEvent}. */
export type UmamiTrackEventParams = object;
/** Optional session identifier string for {@link identifyUmamiSession}. */
export type UmamiTrackSessionIdentifier = string;
/** Session data object accepted by {@link identifyUmamiSession}. */
export type UmamiTrackSessionData = Record<string, unknown>;
/**
* Full page-view payload shape accepted by Umami's tracker.
*
* Consumers usually pass a partial object of this type to {@link trackUmamiPageView}. Omitted fields keep Umami's
* defaults for the current page.
*/
export type UmamiTrackPageViewOptions = {
/** Umami website ID for the page view (normally taken from the script tag). */
website: string;
/** Hostname reported with the page view. */
hostname?: string;
/** Browser language tag (for example `en-US`). */
language?: string;
/** Referring URL, when available. */
referrer?: string;
/** Screen resolution string (for example `1920x1080`). */
screen?: string;
/** Document title for the page view. */
title?: string;
/** Path or URL to record (for example `/checkout` or a full path with query). */
url?: string;
};
type UmamiTrackPayload = Partial<UmamiTrackPageViewOptions>;
type UmamiTrackModifier = (props: UmamiTrackPageViewOptions) => UmamiTrackPayload;
type UmamiTracker = {
track: {
(): void;
(payload: UmamiTrackPayload): void;
(eventName: string, eventData?: object): void;
(modifier: UmamiTrackModifier): void;
};
identify: {
(sessionData: UmamiTrackSessionData): void;
(id: string, sessionData?: UmamiTrackSessionData): void;
};
};
declare global {
interface Window {
umami?: UmamiTracker;
}
}
/**
* Creates a Vue plugin that injects the Umami tracker script and optionally wires SPA page-view tracking through a
* router.
*
* Installation is idempotent: repeated successful installs keep the existing tracker configuration and log a warning,
* but a new router is attached so separate Vue roots can track navigation. If the script fails to load, a later
* `install()` can retry (optionally with updated options). An empty or missing {@link UmamiPluginOptions.websiteID}
* skips installation with a warning. Tracking is skipped when
* `window.location.hostname` includes the substring `localhost` unless {@link UmamiPluginOptions.allowLocalhost} is
* `true`.
*
* @param options - Plugin configuration; see {@link UmamiPluginOptions}.
* @returns A Vue plugin object with an `install` method for `app.use(...)`.
*
* @example
* ```ts
* import { createApp } from 'vue';
* import { VueUmamiPlugin } from '@jaseeey/vue-umami-plugin';
* import router from './router';
*
* createApp(App)
* .use(VueUmamiPlugin({ websiteID: 'YOUR_ID', router }))
* .use(router)
* .mount('#app');
* ```
*/
export declare function VueUmamiPlugin(options: UmamiPluginOptions): {
install: () => void;
};
/**
* Tracks a page view, optionally overriding Umami's default payload fields such as `url`, `title`, or `referrer`.
*
* Useful when not using a router, or when you need a view outside normal navigation. If the tracker is not loaded yet,
* the call is queued (subject to {@link UmamiPluginOptions.maxQueuedEvents}).
*
* @param options - Partial page-view fields merged onto tracker defaults.
*
* @example
* ```ts
* trackUmamiPageView({ url: '/checkout', title: 'Checkout' });
* ```
*/
export declare function trackUmamiPageView(options?: Partial<UmamiTrackPageViewOptions>): void;
/**
* Tracks a named custom event with optional event data.
*
* If the tracker is not loaded yet, the call is queued (subject to {@link UmamiPluginOptions.maxQueuedEvents}).
*
* @param event - Event name reported to Umami.
* @param eventParams - Optional structured payload for the event.
*
* @example
* ```ts
* trackUmamiEvent('button-click', { buttonName: 'subscribe' });
* ```
*/
export declare function trackUmamiEvent(event: UmamiTrackEvent, eventParams?: UmamiTrackEventParams): void;
/**
* Identifies the current Umami session with arbitrary session data.
*
* If the tracker is not loaded yet, the call is queued (subject to {@link UmamiPluginOptions.maxQueuedEvents}).
*
* @param sessionData - Key/value data associated with the session.
*
* @example
* ```ts
* identifyUmamiSession({ userId: 'alice', plan: 'pro' });
* ```
*/
export declare function identifyUmamiSession(sessionData: UmamiTrackSessionData): void;
/**
* Identifies the current Umami session with an explicit session id and optional session data.
*
* If the tracker is not loaded yet, the call is queued (subject to {@link UmamiPluginOptions.maxQueuedEvents}).
*
* @param id - Custom session identifier.
* @param sessionData - Optional key/value data associated with the session.
*
* @example
* ```ts
* identifyUmamiSession('alice-123', { email: 'alice@example.com' });
* ```
*/
export declare function identifyUmamiSession(id: UmamiTrackSessionIdentifier, sessionData?: UmamiTrackSessionData): void;
export {};