diff --git a/src/tracker/index.test.ts b/src/tracker/index.test.ts new file mode 100644 index 000000000..2e2fab59e --- /dev/null +++ b/src/tracker/index.test.ts @@ -0,0 +1,38 @@ +import { afterEach, expect, test, vi } from 'vitest'; + +afterEach(() => { + delete (window as Window & { umami?: unknown }).umami; + delete (document as Document & { currentScript?: HTMLScriptElement }).currentScript; + delete (document as Document & { readyState?: DocumentReadyState }).readyState; + vi.unstubAllGlobals(); + vi.resetModules(); +}); + +test('identifies data-distinct-id before the initial page view', async () => { + const script = document.createElement('script'); + script.src = 'https://analytics.example.com/script.js'; + script.dataset.websiteId = 'website-id'; + script.dataset.distinctId = 'visitor-id'; + + Object.defineProperties(document, { + currentScript: { configurable: true, value: script }, + readyState: { configurable: true, value: 'complete' }, + }); + + const fetchMock = vi.fn().mockResolvedValue({ json: vi.fn().mockResolvedValue({}) }); + vi.stubGlobal('fetch', fetchMock); + + await import('./index'); + + await vi.waitFor(() => expect(fetchMock).toHaveBeenCalledTimes(2)); + const requests = fetchMock.mock.calls.map(([, init]) => JSON.parse(init.body)); + + expect(requests[0]).toMatchObject({ + type: 'identify', + payload: { id: 'visitor-id', website: 'website-id' }, + }); + expect(requests[1]).toMatchObject({ + type: 'event', + payload: { id: 'visitor-id', website: 'website-id' }, + }); +}); diff --git a/src/tracker/index.ts b/src/tracker/index.ts index 1789d3363..588136b00 100644 --- a/src/tracker/index.ts +++ b/src/tracker/index.ts @@ -241,6 +241,7 @@ type MetricEntry = PerformanceEntry & { const website = config('website-id'); const hostUrl = config('host-url'); const beforeSend = config('before-send'); + const distinctId = config('distinct-id') || undefined; const tag = config('tag') || undefined; const autoTrack = config('auto-track') !== _false; const dnt = config('do-not-track') === _true; @@ -641,9 +642,13 @@ type MetricEntry = PerformanceEntry & { let initialized = false; let disabled = false; let cache: string | undefined; - let identity: string | undefined; + let identity = distinctId; let flushPerformance: (() => void) | undefined; + if (distinctId) { + void identify(distinctId); + } + if (autoTrack && !trackingDisabled()) { if (document.readyState === 'complete') { init();