diff --git a/.prettierrc b/.prettierrc index e698378..290db2d 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,6 +1,8 @@ { "trailingComma": "es5", - "tabWidth": 4, + "bracketSameLine": true, "semi": true, - "singleQuote": true + "singleQuote": true, + "endOfLine": "lf", + "printWidth": 120 } diff --git a/lib/mixpanel/context.test.tsx b/lib/mixpanel/context.test.tsx index 78181fc..bda2403 100644 --- a/lib/mixpanel/context.test.tsx +++ b/lib/mixpanel/context.test.tsx @@ -2,196 +2,173 @@ // @ts-nocheck test file contains web apis that are not available in node environment for typescript import { describe, expect, test, vi } from 'vitest'; -import { - fireEvent, - render, - renderHook, - RenderOptions, -} from '@testing-library/react'; +import { fireEvent, render, renderHook, RenderOptions } from '@testing-library/react'; import React, { useEffect } from 'react'; import { MixpanelProvider, useMixpanelContext } from './context.tsx'; import { WebTrackingService } from './tracking/WebTrackingService.ts'; describe('MixpanelContext', () => { - const eventApiClient = vi.fn(() => Promise.resolve()); - - const ContextWrapper = ({ - children, - defaultEventContext, - }: { - children: React.ReactNode; - defaultEventContext: MixpanelEvent; - }) => ( - - {children} - - ); - - const renderWithMixpanelProvider = ( - ui: React.ReactElement, - options?: Omit - ) => { - return render(ui, { - wrapper: (props) => ( - - ), - ...options?.testingLibraryOptions, - }); - }; - - function TrackEventTestingComponent({ - defaultEventContext, - }: { - defaultEventContext?: MixpanelEvent['context']; - }) { - const { trackEvent, setEventContext } = useMixpanelContext(); - - useEffect(() => { - if (defaultEventContext) { - setEventContext(defaultEventContext); - } - }, [defaultEventContext]); - - return ( - - ); - } - - function TrackPageView() { - const { trackPageView } = useMixpanelContext(); - - useEffect(() => { - trackPageView({ - data: { - title: 'Example', - pathname: '/product/1', - route: '/product/:id', - }, - }); - }, []); - - return null; - } - - test('provides expected context with trackEvent function', () => { - const { result } = renderHook(() => useMixpanelContext(), { - wrapper: ContextWrapper, - }); - - expect(result.current).toHaveProperty('trackEvent'); - expect(typeof result.current.trackEvent).toBe('function'); - - expect(result.current).toHaveProperty('trackPageView'); - expect(typeof result.current.trackPageView).toBe('function'); + const eventApiClient = vi.fn(() => Promise.resolve()); + + const ContextWrapper = ({ + children, + defaultEventContext, + }: { + children: React.ReactNode; + defaultEventContext: MixpanelEvent; + }) => ( + + {children} + + ); + + const renderWithMixpanelProvider = (ui: React.ReactElement, options?: Omit) => { + return render(ui, { + wrapper: (props) => , + ...options?.testingLibraryOptions, }); + }; - test('trackEvent sends correct data to api client', () => { - const { getByText } = renderWithMixpanelProvider( - - ); + function TrackEventTestingComponent({ defaultEventContext }: { defaultEventContext?: MixpanelEvent['context'] }) { + const { trackEvent, setEventContext } = useMixpanelContext(); - fireEvent.click(getByText('button')); + useEffect(() => { + if (defaultEventContext) { + setEventContext(defaultEventContext); + } + }, [defaultEventContext]); - expect(eventApiClient).toHaveBeenCalledWith({ + return ( + + ); + } + + function TrackPageView() { + const { trackPageView } = useMixpanelContext(); + + useEffect(() => { + trackPageView({ + data: { + title: 'Example', + pathname: '/product/1', + route: '/product/:id', + }, + }); + }, []); + + return null; + } + + test('provides expected context with trackEvent function', () => { + const { result } = renderHook(() => useMixpanelContext(), { + wrapper: ContextWrapper, }); - test('provider can extend the default context for event tracking with provider prop', () => { - const defaultEventContext = { - href: 'https://example.com', - pathname: '/example', - audience: 'Consumer', - }; + expect(result.current).toHaveProperty('trackEvent'); + expect(typeof result.current.trackEvent).toBe('function'); - const { getByText } = renderWithMixpanelProvider( - , - { - contextWrapperProps: { defaultEventContext }, - } - ); + expect(result.current).toHaveProperty('trackPageView'); + expect(typeof result.current.trackPageView).toBe('function'); + }); - fireEvent.click(getByText('button')); + test('trackEvent sends correct data to api client', () => { + const { getByText } = renderWithMixpanelProvider(); - expect(eventApiClient).toHaveBeenCalledWith({ - name: 'event name', - context: { - title: 'Page title', - href: 'https://example.com', - pathname: '/example', - pwa: false, - audience: 'Consumer', - }, - data: { - productId: '123', - }, - }); - }); + fireEvent.click(getByText('button')); - test('Default event context can be extended from a child component', () => { - const defaultEventContext = { - href: 'https://example.com', - pathname: '/example', - audience: 'Consumer', - }; + expect(eventApiClient).toHaveBeenCalledWith({ + name: 'event name', + context: { + title: 'Page title', + pathname: '/', + pwa: false, + }, + data: { + productId: '123', + }, + }); + }); - const { getByText } = renderWithMixpanelProvider( - - ); + test('provider can extend the default context for event tracking with provider prop', () => { + const defaultEventContext = { + href: 'https://example.com', + pathname: '/example', + audience: 'Consumer', + }; - fireEvent.click(getByText('button')); + const { getByText } = renderWithMixpanelProvider(, { + contextWrapperProps: { defaultEventContext }, + }); - expect(eventApiClient).toHaveBeenCalledWith({ - name: 'event name', - context: { - title: 'Page title', - href: 'https://example.com', - pathname: '/example', - pwa: false, - audience: 'Consumer', - }, - data: { - productId: '123', - }, - }); + fireEvent.click(getByText('button')); + + expect(eventApiClient).toHaveBeenCalledWith({ + name: 'event name', + context: { + title: 'Page title', + href: 'https://example.com', + pathname: '/example', + pwa: false, + audience: 'Consumer', + }, + data: { + productId: '123', + }, }); + }); + + test('Default event context can be extended from a child component', () => { + const defaultEventContext = { + href: 'https://example.com', + pathname: '/example', + audience: 'Consumer', + }; + + const { getByText } = renderWithMixpanelProvider( + + ); - test('trackPageView sends correct data to api client', () => { - renderWithMixpanelProvider(); - - expect(eventApiClient).toHaveBeenCalledWith({ - name: 'Page view', - context: { - pwa: false, - }, - data: { - title: 'Example', - pathname: '/product/1', - route: '/product/:id', - }, - }); + fireEvent.click(getByText('button')); + + expect(eventApiClient).toHaveBeenCalledWith({ + name: 'event name', + context: { + title: 'Page title', + href: 'https://example.com', + pathname: '/example', + pwa: false, + audience: 'Consumer', + }, + data: { + productId: '123', + }, + }); + }); + + test('trackPageView sends correct data to api client', () => { + renderWithMixpanelProvider(); + + expect(eventApiClient).toHaveBeenCalledWith({ + name: 'Page view', + context: { + pwa: false, + }, + data: { + title: 'Example', + pathname: '/product/1', + route: '/product/:id', + }, }); + }); }); diff --git a/lib/mixpanel/context.tsx b/lib/mixpanel/context.tsx index 99a1950..cab2404 100644 --- a/lib/mixpanel/context.tsx +++ b/lib/mixpanel/context.tsx @@ -1,106 +1,83 @@ 'use client'; -import React, { - createContext, - useCallback, - useContext, - useEffect, - useState, -} from 'react'; +import React, { createContext, useCallback, useContext, useEffect, useState } from 'react'; import { writeUtmParamsToSessionStorage } from './web/utils.ts'; import { TrackingService } from './tracking/TrackingService.ts'; -import { - WebMixpanelEvent, - WebMixpanelPageViewEvent, -} from './types/webTypes.ts'; -import { - MobileMixpanelEvent, - MobileMixpanelPageViewEvent, -} from './types/mobileTypes.ts'; +import { WebMixpanelEvent, WebMixpanelPageViewEvent } from './types/webTypes.ts'; +import { MobileMixpanelEvent, MobileMixpanelPageViewEvent } from './types/mobileTypes.ts'; interface MixpanelContextProps { - trackEvent: (event: WebMixpanelEvent | MobileMixpanelEvent) => void; - trackPageView: ( - event: WebMixpanelPageViewEvent | MobileMixpanelPageViewEvent - ) => void; - setEventContext: ( - context: WebMixpanelEvent['context'] | MobileMixpanelEvent['context'] - ) => void; + trackEvent: (event: WebMixpanelEvent | MobileMixpanelEvent) => void; + trackPageView: (event: WebMixpanelPageViewEvent | MobileMixpanelPageViewEvent) => void; + setEventContext: (context: WebMixpanelEvent['context'] | MobileMixpanelEvent['context']) => void; } interface MixpanelProviderProps { - children: React.ReactNode; - trackingService: TrackingService; - defaultEventContext?: - | WebMixpanelEvent['context'] - | MobileMixpanelEvent['context']; + children: React.ReactNode; + trackingService: TrackingService; + defaultEventContext?: WebMixpanelEvent['context'] | MobileMixpanelEvent['context']; } const MixpanelContext = createContext(null); export function useMixpanelContext() { - const context = useContext(MixpanelContext); + const context = useContext(MixpanelContext); - if (!context) { - throw new Error(' not found'); - } + if (!context) { + throw new Error(' not found'); + } - return context; + return context; } -export function MixpanelProvider({ - children, - trackingService, - defaultEventContext, -}: MixpanelProviderProps) { - const [eventContext, setEventContext] = useState< - WebMixpanelEvent['context'] | MobileMixpanelEvent['context'] - >(defaultEventContext || {}); +export function MixpanelProvider({ children, trackingService, defaultEventContext }: MixpanelProviderProps) { + const [eventContext, setEventContext] = useState( + defaultEventContext || {} + ); - const trackEvent = useCallback( - (event: WebMixpanelEvent | MobileMixpanelEvent) => { - trackingService.trackEvent({ - ...event, - context: { - ...eventContext, - ...event.context, - }, - }); + const trackEvent = useCallback( + (event: WebMixpanelEvent | MobileMixpanelEvent) => { + trackingService.trackEvent({ + ...event, + context: { + ...eventContext, + ...event.context, }, - [trackingService, eventContext] - ); + }); + }, + [trackingService, eventContext] + ); - const trackPageView = useCallback( - (event: WebMixpanelPageViewEvent | MobileMixpanelPageViewEvent) => { - trackingService.trackPageView({ - ...event, - context: { - ...eventContext, - ...event.context, - }, - }); + const trackPageView = useCallback( + (event: WebMixpanelPageViewEvent | MobileMixpanelPageViewEvent) => { + trackingService.trackPageView({ + ...event, + context: { + ...eventContext, + ...event.context, }, - [trackingService, eventContext] - ); + }); + }, + [trackingService, eventContext] + ); - useEffect(() => { - // Only run on Web / Client - if (typeof window === 'undefined') { - return; - } + useEffect(() => { + // Only run on Web / Client + if (typeof window === 'undefined') { + return; + } - writeUtmParamsToSessionStorage(window.location.search); - }, []); + writeUtmParamsToSessionStorage(window.location.search); + }, []); - return ( - - {children} - - ); + return ( + + {children} + + ); } diff --git a/lib/mixpanel/tracking/MobileTrackingService.test.ts b/lib/mixpanel/tracking/MobileTrackingService.test.ts index eb66291..27d4630 100644 --- a/lib/mixpanel/tracking/MobileTrackingService.test.ts +++ b/lib/mixpanel/tracking/MobileTrackingService.test.ts @@ -1,49 +1,46 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { MobileTrackingService } from './MobileTrackingService'; -import { - MobileMixpanelEvent, - MobileMixpanelPageViewEvent, -} from '../types/mobileTypes'; +import { MobileMixpanelEvent, MobileMixpanelPageViewEvent } from '../types/mobileTypes'; describe('MobileTrackingService', () => { - const mockEventApiClient = vi.fn(() => Promise.resolve()); - let service: MobileTrackingService; - let mockEvent: MobileMixpanelEvent; - let mockPageViewEvent: MobileMixpanelPageViewEvent; + const mockEventApiClient = vi.fn(() => Promise.resolve()); + let service: MobileTrackingService; + let mockEvent: MobileMixpanelEvent; + let mockPageViewEvent: MobileMixpanelPageViewEvent; - beforeEach(() => { - service = new MobileTrackingService(mockEventApiClient); - // Setup mock data - mockEvent = { - name: 'Test Event', - context: { screenName: 'HomeScreen', route: '/home' }, - data: { info: 'test' }, - }; + beforeEach(() => { + service = new MobileTrackingService(mockEventApiClient); + // Setup mock data + mockEvent = { + name: 'Test Event', + context: { screenName: 'HomeScreen', route: '/home' }, + data: { info: 'test' }, + }; - mockPageViewEvent = { - context: { utm_source: 'google' }, - data: { title: 'Home Page', route: '/home', audience: 'users' }, - }; - }); + mockPageViewEvent = { + context: { utm_source: 'google' }, + data: { title: 'Home Page', route: '/home', audience: 'users' }, + }; + }); - afterEach(() => { - vi.restoreAllMocks(); - }); + afterEach(() => { + vi.restoreAllMocks(); + }); - it('should successfully track an event', async () => { - await service.trackEvent(mockEvent); - expect(mockEventApiClient).toHaveBeenCalledWith({ - ...mockEvent, - context: { ...mockEvent.context }, - }); + it('should successfully track an event', async () => { + await service.trackEvent(mockEvent); + expect(mockEventApiClient).toHaveBeenCalledWith({ + ...mockEvent, + context: { ...mockEvent.context }, }); + }); - it('should successfully track a page view', async () => { - await service.trackPageView(mockPageViewEvent); - expect(mockEventApiClient).toHaveBeenCalledWith({ - ...mockPageViewEvent, - name: 'Page view', - context: { ...mockPageViewEvent.context }, - }); + it('should successfully track a page view', async () => { + await service.trackPageView(mockPageViewEvent); + expect(mockEventApiClient).toHaveBeenCalledWith({ + ...mockPageViewEvent, + name: 'Page view', + context: { ...mockPageViewEvent.context }, }); + }); }); diff --git a/lib/mixpanel/tracking/MobileTrackingService.ts b/lib/mixpanel/tracking/MobileTrackingService.ts index 2d077df..efaa695 100644 --- a/lib/mixpanel/tracking/MobileTrackingService.ts +++ b/lib/mixpanel/tracking/MobileTrackingService.ts @@ -1,36 +1,33 @@ import { TrackingService } from './TrackingService.ts'; -import { - MobileMixpanelEvent, - MobileMixpanelPageViewEvent, -} from '../types/mobileTypes.ts'; +import { MobileMixpanelEvent, MobileMixpanelPageViewEvent } from '../types/mobileTypes.ts'; interface EventApiClient { - (args: MobileMixpanelEvent | MobileMixpanelPageViewEvent): Promise; + (args: MobileMixpanelEvent | MobileMixpanelPageViewEvent): Promise; } export class MobileTrackingService implements TrackingService { - private eventApiClient: EventApiClient; + private eventApiClient: EventApiClient; - constructor(eventApiClient: EventApiClient) { - this.eventApiClient = eventApiClient; - } + constructor(eventApiClient: EventApiClient) { + this.eventApiClient = eventApiClient; + } - trackEvent(event: MobileMixpanelEvent): void { - this.eventApiClient({ - ...event, - context: { - ...event.context, - }, - }).catch((e) => console.error('Failed to track event:', e)); - } + trackEvent(event: MobileMixpanelEvent): void { + this.eventApiClient({ + ...event, + context: { + ...event.context, + }, + }).catch((e) => console.error('Failed to track event:', e)); + } - trackPageView(event: MobileMixpanelPageViewEvent): void { - this.eventApiClient({ - ...event, - name: 'Page view', - context: { - ...event.context, - }, - }).catch((e) => console.error('Failed to track page view:', e)); - } + trackPageView(event: MobileMixpanelPageViewEvent): void { + this.eventApiClient({ + ...event, + name: 'Page view', + context: { + ...event.context, + }, + }).catch((e) => console.error('Failed to track page view:', e)); + } } diff --git a/lib/mixpanel/tracking/TrackingService.ts b/lib/mixpanel/tracking/TrackingService.ts index 28dc2bf..b908587 100644 --- a/lib/mixpanel/tracking/TrackingService.ts +++ b/lib/mixpanel/tracking/TrackingService.ts @@ -1,15 +1,7 @@ -import { - WebMixpanelEvent, - WebMixpanelPageViewEvent, -} from '../types/webTypes.ts'; -import { - MobileMixpanelEvent, - MobileMixpanelPageViewEvent, -} from '../types/mobileTypes.ts'; +import { WebMixpanelEvent, WebMixpanelPageViewEvent } from '../types/webTypes.ts'; +import { MobileMixpanelEvent, MobileMixpanelPageViewEvent } from '../types/mobileTypes.ts'; export interface TrackingService { - trackEvent(event: WebMixpanelEvent | MobileMixpanelEvent): void; - trackPageView( - event: WebMixpanelPageViewEvent | MobileMixpanelPageViewEvent - ): void; + trackEvent(event: WebMixpanelEvent | MobileMixpanelEvent): void; + trackPageView(event: WebMixpanelPageViewEvent | MobileMixpanelPageViewEvent): void; } diff --git a/lib/mixpanel/tracking/WebTrackingService.test.ts b/lib/mixpanel/tracking/WebTrackingService.test.ts index 9c30b91..6a75af4 100644 --- a/lib/mixpanel/tracking/WebTrackingService.test.ts +++ b/lib/mixpanel/tracking/WebTrackingService.test.ts @@ -7,63 +7,63 @@ import { WebMixpanelEvent } from '../types/webTypes'; import { extractUtmParams, isStandalonePWA } from '../web/utils'; vi.mock('../web/utils', () => ({ - extractUtmParams: vi.fn(), - isStandalonePWA: vi.fn(), + extractUtmParams: vi.fn(), + isStandalonePWA: vi.fn(), })); describe('WebTrackingService', () => { - const mockEventApiClient = vi.fn(() => Promise.resolve()); - let service: WebTrackingService; + const mockEventApiClient = vi.fn(() => Promise.resolve()); + let service: WebTrackingService; - // Setup to simulate browser environment - global.window = Object.create(window); - const url = 'http://example.com?utm_source=test_source'; - Object.defineProperty(window, 'location', { - value: { - search: url.split('?')[1], - pathname: '/test', - }, - }); + // Setup to simulate browser environment + global.window = Object.create(window); + const url = 'http://example.com?utm_source=test_source'; + Object.defineProperty(window, 'location', { + value: { + search: url.split('?')[1], + pathname: '/test', + }, + }); - global.document = { - title: 'Test Page', - }; + global.document = { + title: 'Test Page', + }; - beforeEach(() => { - service = new WebTrackingService(mockEventApiClient); - (extractUtmParams as vi.Mock).mockReturnValue({ - utm_source: 'test_source', - }); - (isStandalonePWA as vi.Mock).mockReturnValue(true); + beforeEach(() => { + service = new WebTrackingService(mockEventApiClient); + (extractUtmParams as vi.Mock).mockReturnValue({ + utm_source: 'test_source', }); + (isStandalonePWA as vi.Mock).mockReturnValue(true); + }); - afterEach(() => { - vi.restoreAllMocks(); - }); + afterEach(() => { + vi.restoreAllMocks(); + }); - it('should track an event successfully', async () => { - const event: WebMixpanelEvent = { - name: 'Test Event', - context: { additional: 'data' }, - }; + it('should track an event successfully', async () => { + const event: WebMixpanelEvent = { + name: 'Test Event', + context: { additional: 'data' }, + }; - await service.trackEvent(event); - expect(mockEventApiClient).toHaveBeenCalledWith({ - ...event, - context: { - title: 'Test Page', - pathname: '/test', - pwa: true, - utm_source: 'test_source', - additional: 'data', - }, - }); + await service.trackEvent(event); + expect(mockEventApiClient).toHaveBeenCalledWith({ + ...event, + context: { + title: 'Test Page', + pathname: '/test', + pwa: true, + utm_source: 'test_source', + additional: 'data', + }, }); + }); - it('should not track an event if window is undefined', async () => { - delete global.window; - const event: WebMixpanelEvent = { name: 'Test Event' }; - await service.trackEvent(event); - expect(mockEventApiClient).not.toHaveBeenCalled(); - }); + it('should not track an event if window is undefined', async () => { + delete global.window; + const event: WebMixpanelEvent = { name: 'Test Event' }; + await service.trackEvent(event); + expect(mockEventApiClient).not.toHaveBeenCalled(); + }); }); diff --git a/lib/mixpanel/tracking/WebTrackingService.ts b/lib/mixpanel/tracking/WebTrackingService.ts index de83891..71f728b 100644 --- a/lib/mixpanel/tracking/WebTrackingService.ts +++ b/lib/mixpanel/tracking/WebTrackingService.ts @@ -3,50 +3,50 @@ import { extractUtmParams, isStandalonePWA } from '../web/utils.ts'; import { WebMixpanelEvent, WebMixpanelPageViewEvent } from '../types/webTypes.ts'; interface EventApiClient { - (args: WebMixpanelEvent | WebMixpanelPageViewEvent): Promise; + (args: WebMixpanelEvent | WebMixpanelPageViewEvent): Promise; } export class WebTrackingService implements TrackingService { - private eventApiClient: EventApiClient; + private eventApiClient: EventApiClient; - constructor(eventApiClient: EventApiClient) { - this.eventApiClient = eventApiClient; - } + constructor(eventApiClient: EventApiClient) { + this.eventApiClient = eventApiClient; + } - trackEvent(event: WebMixpanelEvent): void { - if (typeof window === 'undefined') { - return; - } - - const utmParams = extractUtmParams(window.location.search); - - this.eventApiClient({ - ...event, - context: { - title: document.title, - pathname: window.location.pathname, - pwa: isStandalonePWA(), - ...utmParams, - ...event.context, - }, - }).catch((e) => console.error('Failed to track event:', e)); + trackEvent(event: WebMixpanelEvent): void { + if (typeof window === 'undefined') { + return; } - trackPageView(event: WebMixpanelPageViewEvent): void { - if (typeof window === 'undefined') { - return; - } - - const utmParams = extractUtmParams(window.location.search); - - this.eventApiClient({ - ...event, - name: 'Page view', - context: { - pwa: isStandalonePWA(), - ...utmParams, - ...event.context, - }, - }).catch((e) => console.error('Failed to track page view:', e)); + const utmParams = extractUtmParams(window.location.search); + + this.eventApiClient({ + ...event, + context: { + title: document.title, + pathname: window.location.pathname, + pwa: isStandalonePWA(), + ...utmParams, + ...event.context, + }, + }).catch((e) => console.error('Failed to track event:', e)); + } + + trackPageView(event: WebMixpanelPageViewEvent): void { + if (typeof window === 'undefined') { + return; } + + const utmParams = extractUtmParams(window.location.search); + + this.eventApiClient({ + ...event, + name: 'Page view', + context: { + pwa: isStandalonePWA(), + ...utmParams, + ...event.context, + }, + }).catch((e) => console.error('Failed to track page view:', e)); + } } diff --git a/lib/mixpanel/types/baseTypes.ts b/lib/mixpanel/types/baseTypes.ts index fd37b2d..8775adf 100644 --- a/lib/mixpanel/types/baseTypes.ts +++ b/lib/mixpanel/types/baseTypes.ts @@ -1,28 +1,28 @@ export interface BaseEventContext { - utm_source?: string; - utm_medium?: string; - utm_campaign?: string; - utm_content?: string; - utm_term?: string; - [key: string]: unknown; + utm_source?: string; + utm_medium?: string; + utm_campaign?: string; + utm_content?: string; + utm_term?: string; + [key: string]: unknown; } export interface BaseEventData { - [key: string]: unknown; + [key: string]: unknown; } export interface MixpanelEventContext extends BaseEventContext { - title?: string; - audience?: string; - section?: string; + title?: string; + audience?: string; + section?: string; } export interface MixpanelBaseEventData extends BaseEventData { - audience?: string; + audience?: string; } export interface BaseMixpanelEvent { - name?: string; - context?: BaseEventContext; - data?: BaseEventData; + name?: string; + context?: BaseEventContext; + data?: BaseEventData; } diff --git a/lib/mixpanel/types/mobileTypes.ts b/lib/mixpanel/types/mobileTypes.ts index 3d3f293..ed9ec3a 100644 --- a/lib/mixpanel/types/mobileTypes.ts +++ b/lib/mixpanel/types/mobileTypes.ts @@ -1,22 +1,22 @@ import { - BaseEventContext, - BaseEventData, - BaseMixpanelEvent, - MixpanelBaseEventData, - MixpanelEventContext, + BaseEventContext, + BaseEventData, + BaseMixpanelEvent, + MixpanelBaseEventData, + MixpanelEventContext, } from './baseTypes.ts'; export interface MobileMixpanelEvent extends BaseMixpanelEvent { - context?: { - screenName?: string; - route?: string; - } & MixpanelEventContext; - data?: BaseEventData; + context?: { + screenName?: string; + route?: string; + } & MixpanelEventContext; + data?: BaseEventData; } export interface MobileMixpanelPageViewEvent { - context?: BaseEventContext; - data: { - pathname?: string; - } & MixpanelBaseEventData; + context?: BaseEventContext; + data: { + pathname?: string; + } & MixpanelBaseEventData; } diff --git a/lib/mixpanel/types/webTypes.ts b/lib/mixpanel/types/webTypes.ts index 690f47b..d5259c4 100644 --- a/lib/mixpanel/types/webTypes.ts +++ b/lib/mixpanel/types/webTypes.ts @@ -1,9 +1,9 @@ import { - BaseEventContext, - BaseEventData, - BaseMixpanelEvent, - MixpanelBaseEventData, - MixpanelEventContext, + BaseEventContext, + BaseEventData, + BaseMixpanelEvent, + MixpanelBaseEventData, + MixpanelEventContext, } from './baseTypes.ts'; /** @@ -33,13 +33,13 @@ import { * } */ export interface WebMixpanelEvent extends BaseMixpanelEvent { - context?: { - pathname?: string; - href?: string; - route?: string; - pwa?: boolean; - } & MixpanelEventContext; - data?: BaseEventData; + context?: { + pathname?: string; + href?: string; + route?: string; + pwa?: boolean; + } & MixpanelEventContext; + data?: BaseEventData; } /** @@ -67,13 +67,13 @@ export interface WebMixpanelEvent extends BaseMixpanelEvent { *} */ export interface WebMixpanelPageViewEvent { - context?: { - pwa?: boolean; - } & BaseEventContext; - data: { - title: string; - pathname: string; - href: string; - route: string; - } & MixpanelBaseEventData; + context?: { + pwa?: boolean; + } & BaseEventContext; + data: { + title: string; + pathname: string; + href: string; + route: string; + } & MixpanelBaseEventData; } diff --git a/lib/mixpanel/web/utils.test.ts b/lib/mixpanel/web/utils.test.ts index c381e22..abb30c2 100644 --- a/lib/mixpanel/web/utils.test.ts +++ b/lib/mixpanel/web/utils.test.ts @@ -2,33 +2,33 @@ import { afterEach, describe, expect, test } from 'vitest'; import { extractUtmParams, writeUtmParamsToSessionStorage } from './utils.ts'; describe('UTM tags', () => { - const urlContainingUTMParams = new URL( - 'https://example.com?utm_source=source&utm_medium=medium&utm_campaign=campaign&utm_content=content&utm_term=term' - ); + const urlContainingUTMParams = new URL( + 'https://example.com?utm_source=source&utm_medium=medium&utm_campaign=campaign&utm_content=content&utm_term=term' + ); - test('extracting utm tags from url', () => { - const result = extractUtmParams(urlContainingUTMParams.search); + test('extracting utm tags from url', () => { + const result = extractUtmParams(urlContainingUTMParams.search); - expect(result).toEqual({ - utm_source: 'source', - utm_medium: 'medium', - utm_campaign: 'campaign', - utm_content: 'content', - utm_term: 'term', - }); + expect(result).toEqual({ + utm_source: 'source', + utm_medium: 'medium', + utm_campaign: 'campaign', + utm_content: 'content', + utm_term: 'term', }); + }); - test('utm tags are saved in session storage', () => { - writeUtmParamsToSessionStorage(urlContainingUTMParams.search); + test('utm tags are saved in session storage', () => { + writeUtmParamsToSessionStorage(urlContainingUTMParams.search); - expect(sessionStorage.getItem('utm_source')).toBe('source'); - expect(sessionStorage.getItem('utm_medium')).toBe('medium'); - expect(sessionStorage.getItem('utm_campaign')).toBe('campaign'); - expect(sessionStorage.getItem('utm_content')).toBe('content'); - expect(sessionStorage.getItem('utm_term')).toBe('term'); - }); + expect(sessionStorage.getItem('utm_source')).toBe('source'); + expect(sessionStorage.getItem('utm_medium')).toBe('medium'); + expect(sessionStorage.getItem('utm_campaign')).toBe('campaign'); + expect(sessionStorage.getItem('utm_content')).toBe('content'); + expect(sessionStorage.getItem('utm_term')).toBe('term'); + }); - afterEach(() => { - sessionStorage.clear(); - }); + afterEach(() => { + sessionStorage.clear(); + }); }); diff --git a/lib/mixpanel/web/utils.ts b/lib/mixpanel/web/utils.ts index c11f6f1..e178ee3 100644 --- a/lib/mixpanel/web/utils.ts +++ b/lib/mixpanel/web/utils.ts @@ -1,49 +1,26 @@ export const isStandalonePWA = () => - typeof window !== 'undefined' - ? window.matchMedia('(display-mode: standalone)').matches - : false; + typeof window !== 'undefined' ? window.matchMedia('(display-mode: standalone)').matches : false; export const extractUtmParams = (paramsString: string) => { - const searchParams = new URLSearchParams(paramsString); + const searchParams = new URLSearchParams(paramsString); - return { - utm_source: - searchParams.get('utm_source') || - sessionStorage.getItem('utm_source') || - undefined, - utm_medium: - searchParams.get('utm_medium') || - sessionStorage.getItem('utm_medium') || - undefined, - utm_campaign: - searchParams.get('utm_campaign') || - sessionStorage.getItem('utm_campaign') || - undefined, - utm_content: - searchParams.get('utm_content') || - sessionStorage.getItem('utm_content') || - undefined, - utm_term: - searchParams.get('utm_term') || - sessionStorage.getItem('utm_term') || - undefined, - }; + return { + utm_source: searchParams.get('utm_source') || sessionStorage.getItem('utm_source') || undefined, + utm_medium: searchParams.get('utm_medium') || sessionStorage.getItem('utm_medium') || undefined, + utm_campaign: searchParams.get('utm_campaign') || sessionStorage.getItem('utm_campaign') || undefined, + utm_content: searchParams.get('utm_content') || sessionStorage.getItem('utm_content') || undefined, + utm_term: searchParams.get('utm_term') || sessionStorage.getItem('utm_term') || undefined, + }; }; export const writeUtmParamsToSessionStorage = (paramsString: string) => { - const searchParams = new URLSearchParams(paramsString); + const searchParams = new URLSearchParams(paramsString); - const utmSourceKeys = [ - 'utm_source', - 'utm_medium', - 'utm_campaign', - 'utm_content', - 'utm_term', - ]; + const utmSourceKeys = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term']; - utmSourceKeys.forEach((key) => { - if (searchParams.has(key)) { - sessionStorage.setItem(key, searchParams.get(key)); - } - }); + utmSourceKeys.forEach((key) => { + if (searchParams.has(key)) { + sessionStorage.setItem(key, searchParams.get(key)); + } + }); };