UNPKG

use-tracking

Version:

Use Tracking is a custom React hook with a configurable Tracking component designed to enable simple and effective analytics and event tracking in all your Next.js applications.

1 lines 6.78 kB
{"version":3,"sources":["../src/constants/index.ts","../src/utils/getDataAttributes.ts","../src/utils/getMeaningfulTag.ts","../src/hooks/use-tracking.ts","../src/components/provider.tsx"],"sourcesContent":["export const IGNORE_PATTERNS = [\n // aria\n 'aria-',\n // class and associated\n 'class',\n 'height',\n 'width',\n 'style',\n // shadcn\n 'data-state',\n 'data-sidebar',\n]\n\nexport const MEANINGFUL_TAGS = ['A', 'BUTTON']\n","interface GetDataAttributesOptions {\n ignore?: string[]\n prefix?: string\n}\n\nexport function getDataAttributes(\n target: HTMLElement,\n { ignore = [], prefix }: GetDataAttributesOptions = {},\n): Record<string, string> {\n if (!target) return {}\n\n return Array.from(target.attributes).reduce(\n (acc, attr) => {\n if (ignore.some((i) => attr.name.startsWith(i))) return acc\n if (prefix && !attr.name.startsWith(prefix)) return acc\n return { ...acc, [attr.name]: attr.value }\n },\n {} as Record<string, string>,\n )\n}\n","interface GetMeaningfulTagOptions {\n meaningfulTags?: string[]\n target: HTMLElement | null\n}\n\nexport function getMeaningfulTag({\n meaningfulTags = [],\n target,\n}: GetMeaningfulTagOptions): {\n name: string\n target: HTMLElement\n} | null {\n if (!target) return null\n\n const renameTag = (tag: string) => (tag === 'A' ? 'link' : tag.toLowerCase())\n\n const isMeaningfulTag = (el: HTMLElement) => {\n return !meaningfulTags.length\n ? el\n : meaningfulTags.includes(el.tagName)\n ? el\n : (el.closest(meaningfulTags.join(',')) as HTMLElement | null)\n }\n\n const meaningfulTag = isMeaningfulTag(target)\n\n return meaningfulTag\n ? {\n name: renameTag(meaningfulTag.tagName),\n target: meaningfulTag,\n }\n : null\n}\n","import { IGNORE_PATTERNS, MEANINGFUL_TAGS } from '@/src/constants'\nimport { getDataAttributes, getMeaningfulTag } from '@/src/utils'\nimport { usePathname } from 'next/navigation'\nimport { useCallback, useEffect, useRef } from 'react'\n\nexport interface UseTrackingOptions {\n prefix?: string\n ignore?: string[]\n meaningfulTags?: string[]\n action?: (data: Record<string, string>) => void\n}\n\nexport function useTracking({\n prefix = '',\n ignore = IGNORE_PATTERNS,\n meaningfulTags = MEANINGFUL_TAGS,\n action,\n}: UseTrackingOptions = {}) {\n // if no action is provided, log to console in development\n if (!action && process.env.NODE_ENV === 'development') {\n action = (data) => console.log(data)\n }\n\n const url = usePathname()\n\n const sessionId = useRef(\n Array.from(crypto.getRandomValues(new Uint8Array(16)))\n .map((n) => n.toString(16))\n .join(''),\n )\n\n const trackPageView = useCallback(() => {\n action?.({\n sessionId: sessionId.current,\n url,\n event: 'pageview',\n timestamp: new Date().toISOString(),\n })\n }, [action, url])\n\n const trackClickEvent = useCallback(\n (e: MouseEvent) => {\n const target = e.target as HTMLElement\n\n const meaningfulTag = getMeaningfulTag({\n target,\n meaningfulTags,\n })\n\n if (!meaningfulTag) return\n\n const attributes = getDataAttributes(meaningfulTag.target, {\n ignore,\n prefix,\n })\n\n const eventData: Record<string, string> = {\n sessionId: sessionId.current,\n url,\n event: `${meaningfulTag.name}click`,\n timestamp: new Date().toISOString(),\n attributes: JSON.stringify(attributes),\n }\n\n return action?.(eventData)\n },\n [action, url, ignore, prefix],\n )\n\n useEffect(() => {\n trackPageView()\n }, [trackPageView])\n\n useEffect(() => {\n document.addEventListener('click', trackClickEvent)\n return () => {\n document.removeEventListener('click', trackClickEvent)\n }\n }, [trackClickEvent])\n\n return null\n}\n","import { useTracking, type UseTrackingOptions } from '@/src/hooks/use-tracking'\nimport React from 'react'\n\nexport function TrackingClientProvider({\n config,\n children,\n}: {\n config: UseTrackingOptions\n children?: React.ReactNode\n}) {\n useTracking(config)\n\n return <React.Fragment>{children}</React.Fragment>\n}\n"],"mappings":"AAAO,IAAMA,EAAkB,CAE7B,QAEA,QACA,SACA,QACA,QAEA,aACA,cACF,EAEaC,EAAkB,CAAC,IAAK,QAAQ,ECRtC,SAASC,EACdC,EACA,CAAE,OAAAC,EAAS,CAAC,EAAG,OAAAC,CAAO,EAA8B,CAAC,EAC7B,CACxB,OAAKF,EAEE,MAAM,KAAKA,EAAO,UAAU,EAAE,OACnC,CAACG,EAAKC,IACAH,EAAO,KAAMI,GAAMD,EAAK,KAAK,WAAWC,CAAC,CAAC,GAC1CH,GAAU,CAACE,EAAK,KAAK,WAAWF,CAAM,EAAUC,EAC7C,CAAE,GAAGA,EAAK,CAACC,EAAK,IAAI,EAAGA,EAAK,KAAM,EAE3C,CAAC,CACH,EAToB,CAAC,CAUvB,CCdO,SAASE,EAAiB,CAC/B,eAAAC,EAAiB,CAAC,EAClB,OAAAC,CACF,EAGS,CACP,GAAI,CAACA,EAAQ,OAAO,KAEpB,IAAMC,EAAaC,GAAiBA,IAAQ,IAAM,OAASA,EAAI,YAAY,EAUrEC,GARmBC,GACfL,EAAe,OAEnBA,EAAe,SAASK,EAAG,OAAO,EAChCA,EACCA,EAAG,QAAQL,EAAe,KAAK,GAAG,CAAC,EAHtCK,GAMgCJ,CAAM,EAE5C,OAAOG,EACH,CACE,KAAMF,EAAUE,EAAc,OAAO,EACrC,OAAQA,CACV,EACA,IACN,CC9BA,OAAS,eAAAE,MAAmB,kBAC5B,OAAS,eAAAC,EAAa,aAAAC,EAAW,UAAAC,MAAc,QASxC,SAASC,EAAY,CAC1B,OAAAC,EAAS,GACT,OAAAC,EAASC,EACT,eAAAC,EAAiBC,EACjB,OAAAC,CACF,EAAwB,CAAC,EAAG,CAEtB,CAACA,GAAU,QAAQ,IAAI,WAAa,gBACtCA,EAAUC,GAAS,QAAQ,IAAIA,CAAI,GAGrC,IAAMC,EAAMZ,EAAY,EAElBa,EAAYV,EAChB,MAAM,KAAK,OAAO,gBAAgB,IAAI,WAAW,EAAE,CAAC,CAAC,EAClD,IAAKW,GAAMA,EAAE,SAAS,EAAE,CAAC,EACzB,KAAK,EAAE,CACZ,EAEMC,EAAgBd,EAAY,IAAM,CACtCS,IAAS,CACP,UAAWG,EAAU,QACrB,IAAAD,EACA,MAAO,WACP,UAAW,IAAI,KAAK,EAAE,YAAY,CACpC,CAAC,CACH,EAAG,CAACF,EAAQE,CAAG,CAAC,EAEVI,EAAkBf,EACrBgB,GAAkB,CACjB,IAAMC,EAASD,EAAE,OAEXE,EAAgBC,EAAiB,CACrC,OAAAF,EACA,eAAAV,CACF,CAAC,EAED,GAAI,CAACW,EAAe,OAEpB,IAAME,EAAaC,EAAkBH,EAAc,OAAQ,CACzD,OAAAb,EACA,OAAAD,CACF,CAAC,EAEKkB,EAAoC,CACxC,UAAWV,EAAU,QACrB,IAAAD,EACA,MAAO,GAAGO,EAAc,IAAI,QAC5B,UAAW,IAAI,KAAK,EAAE,YAAY,EAClC,WAAY,KAAK,UAAUE,CAAU,CACvC,EAEA,OAAOX,IAASa,CAAS,CAC3B,EACA,CAACb,EAAQE,EAAKN,EAAQD,CAAM,CAC9B,EAEA,OAAAH,EAAU,IAAM,CACda,EAAc,CAChB,EAAG,CAACA,CAAa,CAAC,EAElBb,EAAU,KACR,SAAS,iBAAiB,QAASc,CAAe,EAC3C,IAAM,CACX,SAAS,oBAAoB,QAASA,CAAe,CACvD,GACC,CAACA,CAAe,CAAC,EAEb,IACT,CChFA,OAAOQ,MAAW,QAEX,SAASC,EAAuB,CACrC,OAAAC,EACA,SAAAC,CACF,EAGG,CACD,OAAAC,EAAYF,CAAM,EAEXF,EAAA,cAACA,EAAM,SAAN,KAAgBG,CAAS,CACnC","names":["IGNORE_PATTERNS","MEANINGFUL_TAGS","getDataAttributes","target","ignore","prefix","acc","attr","i","getMeaningfulTag","meaningfulTags","target","renameTag","tag","meaningfulTag","el","usePathname","useCallback","useEffect","useRef","useTracking","prefix","ignore","IGNORE_PATTERNS","meaningfulTags","MEANINGFUL_TAGS","action","data","url","sessionId","n","trackPageView","trackClickEvent","e","target","meaningfulTag","getMeaningfulTag","attributes","getDataAttributes","eventData","React","TrackingClientProvider","config","children","useTracking"]}