Files
klz-cables.com/lib/services/analytics/umami-analytics-service.ts
Marc Mintel 72711c74ba
Some checks failed
Build & Deploy KLZ Cables / deploy (push) Failing after 13m20s
umami
2026-01-24 22:03:06 +01:00

111 lines
3.1 KiB
TypeScript

import type { AnalyticsEventProperties, AnalyticsService } from './analytics-service';
/**
* Type definition for the Umami global object.
*
* This represents the `window.umami` object that the Umami script exposes.
* The `track` function can accept either an event name or a URL.
*/
type UmamiGlobal = {
track?: (eventOrUrl: string, props?: AnalyticsEventProperties) => void;
};
/**
* Configuration options for UmamiAnalyticsService.
*
* @property enabled - Whether analytics are enabled
*/
export type UmamiAnalyticsServiceOptions = {
enabled: boolean;
};
/**
* Umami Analytics Service Implementation.
*
* This service implements the AnalyticsService interface for Umami analytics.
* It provides type-safe event tracking and pageview tracking.
*
* @example
* ```typescript
* // Service creation (usually done by create-services.ts)
* const service = new UmamiAnalyticsService({ enabled: true });
*
* // Track events
* service.track('button_click', { button_id: 'cta' });
* service.trackPageview('/products/123');
* ```
*
* @example
* ```typescript
* // Using through the service layer (recommended)
* import { getAppServices } from '@/lib/services/create-services';
*
* const services = getAppServices();
* services.analytics.track('product_add_to_cart', {
* product_id: '123',
* price: 99.99,
* });
* ```
*/
export class UmamiAnalyticsService implements AnalyticsService {
constructor(private readonly options: UmamiAnalyticsServiceOptions) {}
/**
* Track a custom event with optional properties.
*
* This method checks if analytics are enabled and if we're in a browser environment
* before attempting to track the event.
*
* @param eventName - The name of the event to track
* @param props - Optional event properties
*
* @example
* ```typescript
* service.track('product_add_to_cart', {
* product_id: '123',
* product_name: 'Cable',
* price: 99.99,
* quantity: 1,
* });
* ```
*/
track(eventName: string, props?: AnalyticsEventProperties) {
if (!this.options.enabled) return;
if (typeof window === 'undefined') return;
const umami = (window as unknown as { umami?: UmamiGlobal }).umami;
umami?.track?.(eventName, props);
}
/**
* Track a pageview.
*
* This method checks if analytics are enabled and if we're in a browser environment
* before attempting to track the pageview.
*
* Umami treats `track(url)` as a pageview override, so we can use the same
* `track` function for both events and pageviews.
*
* @param url - The URL to track (defaults to current location)
*
* @example
* ```typescript
* // Track current page
* service.trackPageview();
*
* // Track custom URL
* service.trackPageview('/products/123?category=cables');
* ```
*/
trackPageview(url?: string) {
if (!this.options.enabled) return;
if (typeof window === 'undefined') return;
const umami = (window as unknown as { umami?: UmamiGlobal }).umami;
// Umami treats `track(url)` as a pageview override.
if (url) umami?.track?.(url);
else umami?.track?.(window.location.pathname + window.location.search);
}
}