@shware/analytics 10.0.0 → 10.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/next/index.cjs +2 -1
- package/dist/next/index.cjs.map +1 -1
- package/dist/next/index.d.cts +11 -1
- package/dist/next/index.d.cts.map +1 -1
- package/dist/next/index.d.mts +11 -1
- package/dist/next/index.d.mts.map +1 -1
- package/dist/next/index.mjs +2 -1
- package/dist/next/index.mjs.map +1 -1
- package/dist/tanstack/analytics.cjs +2 -1
- package/dist/tanstack/analytics.cjs.map +1 -1
- package/dist/tanstack/analytics.d.cts +11 -1
- package/dist/tanstack/analytics.d.cts.map +1 -1
- package/dist/tanstack/analytics.d.mts +11 -1
- package/dist/tanstack/analytics.d.mts.map +1 -1
- package/dist/tanstack/analytics.mjs +2 -1
- package/dist/tanstack/analytics.mjs.map +1 -1
- package/dist/tanstack/middleware.cjs +13 -1
- package/dist/tanstack/middleware.cjs.map +1 -1
- package/dist/tanstack/middleware.d.cts +5 -3
- package/dist/tanstack/middleware.d.cts.map +1 -1
- package/dist/tanstack/middleware.d.mts +5 -3
- package/dist/tanstack/middleware.d.mts.map +1 -1
- package/dist/tanstack/middleware.mjs +13 -1
- package/dist/tanstack/middleware.mjs.map +1 -1
- package/dist/third-parties/index.d.cts +1 -1
- package/dist/third-parties/index.d.mts +1 -1
- package/package.json +1 -1
package/dist/next/index.cjs
CHANGED
|
@@ -23,7 +23,7 @@ function PageViews() {
|
|
|
23
23
|
require_hooks_use_web_analytics.useWebAnalytics(pathname, searchParams.toString());
|
|
24
24
|
return null;
|
|
25
25
|
}
|
|
26
|
-
function Analytics({ gaId, gaSrc, nonce, debugMode, metaPixelId, hotjarId, redditPixelId, linkedInPartnerId, uetTagId, uetCustomerId, facebookAppId, reportWebVitals = true }) {
|
|
26
|
+
function Analytics({ gaId, gaSrc, nonce, debugMode, metaPixelId, hotjarId, redditPixelId, linkedInPartnerId, uetTagId, uetCustomerId, uetConsent = { ad_storage: "granted" }, facebookAppId, reportWebVitals = true }) {
|
|
27
27
|
require_hooks_use_outbound_click_analytics.useOutboundClickAnalytics();
|
|
28
28
|
require_hooks_use_uet_id_sync.useUETIdSync(uetCustomerId);
|
|
29
29
|
(0, next_web_vitals.useReportWebVitals)((metric) => {
|
|
@@ -134,6 +134,7 @@ function Analytics({ gaId, gaSrc, nonce, debugMode, metaPixelId, hotjarId, reddi
|
|
|
134
134
|
dangerouslySetInnerHTML: { __html: `
|
|
135
135
|
(function (w, d, t, u, o) {
|
|
136
136
|
w[u] = w[u] || [], o.ts = (new Date).getTime();
|
|
137
|
+
${uetConsent ? `w[u].push("consent", "default", ${JSON.stringify(uetConsent)});` : ""}
|
|
137
138
|
var n = d.createElement(t);
|
|
138
139
|
n.src = "https://bat.bing.net/bat.js?ti=" + o.ti + ("uetq" != u ? "&q=" + u : ""),
|
|
139
140
|
n.async = 1, n.onload = n.onreadystatechange = function() {
|
package/dist/next/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["usePathname","useSearchParams","Suspense","Script"],"sources":["../../src/next/index.tsx"],"sourcesContent":["'use client';\n\nimport { usePathname, useSearchParams } from 'next/navigation';\nimport Script from 'next/script';\nimport { useReportWebVitals } from 'next/web-vitals';\nimport { Suspense } from 'react';\nimport { useOutboundClickAnalytics } from '../hooks/use-outbound-click-analytics';\nimport { useUETIdSync } from '../hooks/use-uet-id-sync';\nimport { useWebAnalytics } from '../hooks/use-web-analytics';\nimport type { PixelId as MetaPixelId } from '../track/fbq';\nimport type { GaId, GtmId } from '../track/gtag';\nimport { track } from '../track/index';\nimport type { PixelId as RedditPixelId } from '../track/rdt';\n\ninterface Props {\n gaId?: GaId;\n gaSrc?: string;\n gtmId?: GtmId;\n hotjarId?: `${number}`;\n metaPixelId?: MetaPixelId;\n redditPixelId?: RedditPixelId;\n linkedInPartnerId?: `${number}`;\n /** Microsoft Advertising UET tag id. The tag reports page loads itself (`enableAutoSpaTracking`). */\n uetTagId?: `${number}`;\n /** Microsoft Advertising customer id (`cid` in the ads UI's URLs): enables the Conversions API's ID Sync pixel. */\n uetCustomerId?: `${number}`;\n facebookAppId?: string;\n nonce?: string;\n debugMode?: boolean;\n reportWebVitals?: boolean;\n}\n\n/**\n * Its own component under a Suspense boundary: `useSearchParams` in a statically rendered route\n * bails the whole tree out to client rendering unless something above it suspends, and Next\n * fails the build for a page that lets it. The boundary is here so a host does not have to know.\n */\nfunction PageViews() {\n const pathname = usePathname();\n const searchParams = useSearchParams();\n useWebAnalytics(pathname, searchParams.toString());\n return null;\n}\n\nexport function Analytics({\n gaId,\n gaSrc,\n nonce,\n debugMode,\n metaPixelId,\n hotjarId,\n redditPixelId,\n linkedInPartnerId,\n uetTagId,\n uetCustomerId,\n facebookAppId,\n reportWebVitals = true,\n}: Props) {\n useOutboundClickAnalytics();\n useUETIdSync(uetCustomerId);\n\n useReportWebVitals((metric) => {\n if (!reportWebVitals) return;\n const properties = {\n value: metric.delta,\n metric_id: metric.id,\n metric_value: metric.value,\n metric_delta: metric.delta,\n metric_rating: metric.rating,\n metric_navigation_type: metric.navigationType,\n non_interaction: true, // avoids affecting bounce rate.\n };\n track(metric.name, properties);\n });\n\n return (\n <>\n <Suspense fallback={null}>\n <PageViews />\n </Suspense>\n {facebookAppId && <meta property=\"fb:app_id\" content={facebookAppId} />}\n {gaId && (\n <>\n <Script\n id=\"gtag\"\n nonce={nonce}\n src={gaSrc ?? `https://www.googletagmanager.com/gtag/js?id=${gaId}`}\n />\n <Script\n nonce={nonce}\n id=\"gtag-init\"\n dangerouslySetInnerHTML={{\n __html: `\n window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('config', '${gaId}'${debugMode ? \" ,{ 'debug_mode': true }\" : ''});\n `,\n }}\n />\n </>\n )}\n {metaPixelId && (\n <Script\n id=\"meta-pixel\"\n strategy=\"afterInteractive\"\n dangerouslySetInnerHTML={{\n __html: `\n !(function (f, b, e, v, n, t, s) {\n if (f.fbq) return;\n n = f.fbq = function () {\n n.callMethod ? n.callMethod.apply(n, arguments) : n.queue.push(arguments);\n };\n if (!f._fbq) f._fbq = n;\n n.push = n;\n n.loaded = !0;\n n.version = '2.0';\n n.queue = [];\n t = b.createElement(e);\n t.async = !0;\n t.src = v;\n s = b.getElementsByTagName(e)[0];\n s.parentNode.insertBefore(t, s);\n })(window, document, 'script', 'https://connect.facebook.net/en_US/fbevents.js');\n fbq('init', '${metaPixelId}');\n fbq('track', 'PageView');`,\n }}\n />\n )}\n {redditPixelId && (\n <Script\n id=\"reddit-pixel\"\n strategy=\"afterInteractive\"\n dangerouslySetInnerHTML={{\n __html: `\n !function(w,d) {\n if(!w.rdt) {\n var p = w.rdt = function() {\n p.sendEvent ? p.sendEvent.apply(p,arguments) : p.callQueue.push(arguments)\n };\n p.callQueue = [];\n var t = d.createElement(\"script\");\n t.src = \"https://www.redditstatic.com/ads/pixel.js\";\n t.async = !0;\n var s = d.getElementsByTagName(\"script\")[0];\n s.parentNode.insertBefore(t,s)\n }\n }(window, document);\n rdt('init', '${redditPixelId}');\n rdt('track', 'PageVisit');`,\n }}\n />\n )}\n {linkedInPartnerId && (\n <Script\n id=\"linkedin-insight-tag\"\n strategy=\"afterInteractive\"\n dangerouslySetInnerHTML={{\n __html: `\n _linkedin_partner_id = \"${linkedInPartnerId}\";\n window._linkedin_data_partner_ids = window._linkedin_data_partner_ids || [];\n window._linkedin_data_partner_ids.push(_linkedin_partner_id);\n\n (function(l) {\n if (!l){\n window.lintrk = function(a,b){ \n window.lintrk.q.push([a,b])\n };\n window.lintrk.q=[]\n }\n var s = document.getElementsByTagName(\"script\")[0];\n var b = document.createElement(\"script\");\n b.type = \"text/javascript\";b.async = true;\n b.src = \"https://snap.licdn.com/li.lms-analytics/insight.min.js\";\n s.parentNode.insertBefore(b, s);\n })(window.lintrk);\n `,\n }}\n />\n )}\n {uetTagId && (\n <Script\n strategy=\"afterInteractive\"\n id=\"uet-tag\"\n dangerouslySetInnerHTML={{\n __html: `\n (function (w, d, t, u, o) {\n w[u] = w[u] || [], o.ts = (new Date).getTime();\n var n = d.createElement(t);\n n.src = \"https://bat.bing.net/bat.js?ti=\" + o.ti + (\"uetq\" != u ? \"&q=\" + u : \"\"),\n n.async = 1, n.onload = n.onreadystatechange = function() {\n var s = this.readyState;\n s && \"loaded\" !== s && \"complete\" !== s ||\n (o.q = w[u], w[u] = new UET(o), w[u].push(\"pageLoad\"),\n n.onload = n.onreadystatechange = null)\n };\n var i = d.getElementsByTagName(t)[0];\n i.parentNode.insertBefore(n, i);\n })(window, document, \"script\", \"uetq\", {\n ti: \"${uetTagId}\",\n enableAutoSpaTracking: true\n });\n `,\n }}\n />\n )}\n {hotjarId && (\n <Script\n id=\"hotjar\"\n strategy=\"afterInteractive\"\n dangerouslySetInnerHTML={{\n __html: `\n (function(h,o,t,j,a,r){\n h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};\n h._hjSettings={hjid:${hotjarId},hjsv:6};\n a=o.getElementsByTagName('head')[0];\n r=o.createElement('script');r.async=1;\n r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;\n a.appendChild(r);\n })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');\n `,\n }}\n />\n )}\n </>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAqCA,SAAS,YAAY;CACnB,MAAM,YAAA,GAAWA,gBAAAA,YAAAA,CAAY;CAC7B,MAAM,gBAAA,GAAeC,gBAAAA,gBAAAA,CAAgB;CACrC,gCAAA,gBAAgB,UAAU,aAAa,SAAS,CAAC;CACjD,OAAO;AACT;AAEA,SAAgB,UAAU,EACxB,MACA,OACA,OACA,WACA,aACA,UACA,eACA,mBACA,UACA,eACA,eACA,kBAAkB,QACV;CACR,2CAAA,0BAA0B;CAC1B,8BAAA,aAAa,aAAa;CAE1B,CAAA,GAAA,gBAAA,mBAAA,EAAoB,WAAW;EAC7B,IAAI,CAAC,iBAAiB;EACtB,MAAM,aAAa;GACjB,OAAO,OAAO;GACd,WAAW,OAAO;GAClB,cAAc,OAAO;GACrB,cAAc,OAAO;GACrB,eAAe,OAAO;GACtB,wBAAwB,OAAO;GAC/B,iBAAiB;EACnB;EACA,oBAAA,MAAM,OAAO,MAAM,UAAU;CAC/B,CAAC;CAED,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA;EACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,MAAAA,UAAD;GAAU,UAAU;GAClB,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,WAAD,CAAY,CAAA;EACJ,CAAA;EACT,iBAAiB,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;GAAM,UAAS;GAAY,SAAS;EAAgB,CAAA;EACrE,QACC,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,YAAAA,SAAD;GACE,IAAG;GACI;GACP,KAAK,SAAS,+CAA+C;EAC9D,CAAA,GACD,iBAAA,GAAA,kBAAA,IAAA,CAACA,YAAAA,SAAD;GACS;GACP,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;;gCAIU,KAAK,GAAG,YAAY,6BAA6B,GAAG;cAExE;EACD,CAAA,CACD,EAAA,CAAA;EAEH,eACC,iBAAA,GAAA,kBAAA,IAAA,CAACA,YAAAA,SAAD;GACE,IAAG;GACH,UAAS;GACT,yBAAyB,EACvB,QAAQ;;;;;;;;;;;;;;;;;2BAiBO,YAAY;uCAE7B;EACD,CAAA;EAEF,iBACC,iBAAA,GAAA,kBAAA,IAAA,CAACA,YAAAA,SAAD;GACE,IAAG;GACH,UAAS;GACT,yBAAyB,EACvB,QAAQ;;;;;;;;;;;;;;2BAcO,cAAc;wCAE/B;EACD,CAAA;EAEF,qBACC,iBAAA,GAAA,kBAAA,IAAA,CAACA,YAAAA,SAAD;GACE,IAAG;GACH,UAAS;GACT,yBAAyB,EACvB,QAAQ;wCACoB,kBAAkB;;;;;;;;;;;;;;;;;gBAkBhD;EACD,CAAA;EAEF,YACC,iBAAA,GAAA,kBAAA,IAAA,CAACA,YAAAA,SAAD;GACE,UAAS;GACT,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;;;;;;;;;;;;uBAcG,SAAS;;;cAItB;EACD,CAAA;EAEF,YACC,iBAAA,GAAA,kBAAA,IAAA,CAACA,YAAAA,SAAD;GACE,IAAG;GACH,UAAS;GACT,yBAAyB,EACvB,QAAQ;;;oCAGgB,SAAS;;;;;;cAOnC;EACD,CAAA;CAEH,EAAA,CAAA;AAEN"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["usePathname","useSearchParams","Suspense","Script"],"sources":["../../src/next/index.tsx"],"sourcesContent":["'use client';\n\nimport { usePathname, useSearchParams } from 'next/navigation';\nimport Script from 'next/script';\nimport { useReportWebVitals } from 'next/web-vitals';\nimport { Suspense } from 'react';\nimport { useOutboundClickAnalytics } from '../hooks/use-outbound-click-analytics';\nimport { useUETIdSync } from '../hooks/use-uet-id-sync';\nimport { useWebAnalytics } from '../hooks/use-web-analytics';\nimport type { PixelId as MetaPixelId } from '../track/fbq';\nimport type { GaId, GtmId } from '../track/gtag';\nimport { track } from '../track/index';\nimport type { PixelId as RedditPixelId } from '../track/rdt';\nimport type { UETConsent } from '../track/uetq';\n\ninterface Props {\n gaId?: GaId;\n gaSrc?: string;\n gtmId?: GtmId;\n hotjarId?: `${number}`;\n metaPixelId?: MetaPixelId;\n redditPixelId?: RedditPixelId;\n linkedInPartnerId?: `${number}`;\n /** Microsoft Advertising UET tag id. The tag reports page loads itself (`enableAutoSpaTracking`). */\n uetTagId?: `${number}`;\n /** Microsoft Advertising customer id (`cid` in the ads UI's URLs): enables the Conversions API's ID Sync pixel. */\n uetCustomerId?: `${number}`;\n /**\n * UET consent mode default, pushed inside the tag snippet so bat.js reads it before the first\n * page load. Defaults to `ad_storage: granted`, which is how the tag behaves without a signal,\n * so Microsoft stops flagging EEA/UK/CH events as missing consent. Sites with a consent banner\n * pass `{ ad_storage: 'denied' }` and send `update` with `setUETConsent` when the visitor\n * decides; `false` pushes no default.\n * https://help.ads.microsoft.com/#apex/ads/en/60119/1\n */\n uetConsent?: UETConsent | false;\n facebookAppId?: string;\n nonce?: string;\n debugMode?: boolean;\n reportWebVitals?: boolean;\n}\n\n/**\n * Its own component under a Suspense boundary: `useSearchParams` in a statically rendered route\n * bails the whole tree out to client rendering unless something above it suspends, and Next\n * fails the build for a page that lets it. The boundary is here so a host does not have to know.\n */\nfunction PageViews() {\n const pathname = usePathname();\n const searchParams = useSearchParams();\n useWebAnalytics(pathname, searchParams.toString());\n return null;\n}\n\nexport function Analytics({\n gaId,\n gaSrc,\n nonce,\n debugMode,\n metaPixelId,\n hotjarId,\n redditPixelId,\n linkedInPartnerId,\n uetTagId,\n uetCustomerId,\n uetConsent = { ad_storage: 'granted' },\n facebookAppId,\n reportWebVitals = true,\n}: Props) {\n useOutboundClickAnalytics();\n useUETIdSync(uetCustomerId);\n\n useReportWebVitals((metric) => {\n if (!reportWebVitals) return;\n const properties = {\n value: metric.delta,\n metric_id: metric.id,\n metric_value: metric.value,\n metric_delta: metric.delta,\n metric_rating: metric.rating,\n metric_navigation_type: metric.navigationType,\n non_interaction: true, // avoids affecting bounce rate.\n };\n track(metric.name, properties);\n });\n\n return (\n <>\n <Suspense fallback={null}>\n <PageViews />\n </Suspense>\n {facebookAppId && <meta property=\"fb:app_id\" content={facebookAppId} />}\n {gaId && (\n <>\n <Script\n id=\"gtag\"\n nonce={nonce}\n src={gaSrc ?? `https://www.googletagmanager.com/gtag/js?id=${gaId}`}\n />\n <Script\n nonce={nonce}\n id=\"gtag-init\"\n dangerouslySetInnerHTML={{\n __html: `\n window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('config', '${gaId}'${debugMode ? \" ,{ 'debug_mode': true }\" : ''});\n `,\n }}\n />\n </>\n )}\n {metaPixelId && (\n <Script\n id=\"meta-pixel\"\n strategy=\"afterInteractive\"\n dangerouslySetInnerHTML={{\n __html: `\n !(function (f, b, e, v, n, t, s) {\n if (f.fbq) return;\n n = f.fbq = function () {\n n.callMethod ? n.callMethod.apply(n, arguments) : n.queue.push(arguments);\n };\n if (!f._fbq) f._fbq = n;\n n.push = n;\n n.loaded = !0;\n n.version = '2.0';\n n.queue = [];\n t = b.createElement(e);\n t.async = !0;\n t.src = v;\n s = b.getElementsByTagName(e)[0];\n s.parentNode.insertBefore(t, s);\n })(window, document, 'script', 'https://connect.facebook.net/en_US/fbevents.js');\n fbq('init', '${metaPixelId}');\n fbq('track', 'PageView');`,\n }}\n />\n )}\n {redditPixelId && (\n <Script\n id=\"reddit-pixel\"\n strategy=\"afterInteractive\"\n dangerouslySetInnerHTML={{\n __html: `\n !function(w,d) {\n if(!w.rdt) {\n var p = w.rdt = function() {\n p.sendEvent ? p.sendEvent.apply(p,arguments) : p.callQueue.push(arguments)\n };\n p.callQueue = [];\n var t = d.createElement(\"script\");\n t.src = \"https://www.redditstatic.com/ads/pixel.js\";\n t.async = !0;\n var s = d.getElementsByTagName(\"script\")[0];\n s.parentNode.insertBefore(t,s)\n }\n }(window, document);\n rdt('init', '${redditPixelId}');\n rdt('track', 'PageVisit');`,\n }}\n />\n )}\n {linkedInPartnerId && (\n <Script\n id=\"linkedin-insight-tag\"\n strategy=\"afterInteractive\"\n dangerouslySetInnerHTML={{\n __html: `\n _linkedin_partner_id = \"${linkedInPartnerId}\";\n window._linkedin_data_partner_ids = window._linkedin_data_partner_ids || [];\n window._linkedin_data_partner_ids.push(_linkedin_partner_id);\n\n (function(l) {\n if (!l){\n window.lintrk = function(a,b){ \n window.lintrk.q.push([a,b])\n };\n window.lintrk.q=[]\n }\n var s = document.getElementsByTagName(\"script\")[0];\n var b = document.createElement(\"script\");\n b.type = \"text/javascript\";b.async = true;\n b.src = \"https://snap.licdn.com/li.lms-analytics/insight.min.js\";\n s.parentNode.insertBefore(b, s);\n })(window.lintrk);\n `,\n }}\n />\n )}\n {uetTagId && (\n <Script\n strategy=\"afterInteractive\"\n id=\"uet-tag\"\n dangerouslySetInnerHTML={{\n __html: `\n (function (w, d, t, u, o) {\n w[u] = w[u] || [], o.ts = (new Date).getTime();\n ${uetConsent ? `w[u].push(\"consent\", \"default\", ${JSON.stringify(uetConsent)});` : ''}\n var n = d.createElement(t);\n n.src = \"https://bat.bing.net/bat.js?ti=\" + o.ti + (\"uetq\" != u ? \"&q=\" + u : \"\"),\n n.async = 1, n.onload = n.onreadystatechange = function() {\n var s = this.readyState;\n s && \"loaded\" !== s && \"complete\" !== s ||\n (o.q = w[u], w[u] = new UET(o), w[u].push(\"pageLoad\"),\n n.onload = n.onreadystatechange = null)\n };\n var i = d.getElementsByTagName(t)[0];\n i.parentNode.insertBefore(n, i);\n })(window, document, \"script\", \"uetq\", {\n ti: \"${uetTagId}\",\n enableAutoSpaTracking: true\n });\n `,\n }}\n />\n )}\n {hotjarId && (\n <Script\n id=\"hotjar\"\n strategy=\"afterInteractive\"\n dangerouslySetInnerHTML={{\n __html: `\n (function(h,o,t,j,a,r){\n h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};\n h._hjSettings={hjid:${hotjarId},hjsv:6};\n a=o.getElementsByTagName('head')[0];\n r=o.createElement('script');r.async=1;\n r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;\n a.appendChild(r);\n })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');\n `,\n }}\n />\n )}\n </>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA+CA,SAAS,YAAY;CACnB,MAAM,YAAA,GAAWA,gBAAAA,YAAAA,CAAY;CAC7B,MAAM,gBAAA,GAAeC,gBAAAA,gBAAAA,CAAgB;CACrC,gCAAA,gBAAgB,UAAU,aAAa,SAAS,CAAC;CACjD,OAAO;AACT;AAEA,SAAgB,UAAU,EACxB,MACA,OACA,OACA,WACA,aACA,UACA,eACA,mBACA,UACA,eACA,aAAa,EAAE,YAAY,UAAU,GACrC,eACA,kBAAkB,QACV;CACR,2CAAA,0BAA0B;CAC1B,8BAAA,aAAa,aAAa;CAE1B,CAAA,GAAA,gBAAA,mBAAA,EAAoB,WAAW;EAC7B,IAAI,CAAC,iBAAiB;EACtB,MAAM,aAAa;GACjB,OAAO,OAAO;GACd,WAAW,OAAO;GAClB,cAAc,OAAO;GACrB,cAAc,OAAO;GACrB,eAAe,OAAO;GACtB,wBAAwB,OAAO;GAC/B,iBAAiB;EACnB;EACA,oBAAA,MAAM,OAAO,MAAM,UAAU;CAC/B,CAAC;CAED,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA;EACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,MAAAA,UAAD;GAAU,UAAU;GAClB,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,WAAD,CAAY,CAAA;EACJ,CAAA;EACT,iBAAiB,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;GAAM,UAAS;GAAY,SAAS;EAAgB,CAAA;EACrE,QACC,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,YAAAA,SAAD;GACE,IAAG;GACI;GACP,KAAK,SAAS,+CAA+C;EAC9D,CAAA,GACD,iBAAA,GAAA,kBAAA,IAAA,CAACA,YAAAA,SAAD;GACS;GACP,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;;gCAIU,KAAK,GAAG,YAAY,6BAA6B,GAAG;cAExE;EACD,CAAA,CACD,EAAA,CAAA;EAEH,eACC,iBAAA,GAAA,kBAAA,IAAA,CAACA,YAAAA,SAAD;GACE,IAAG;GACH,UAAS;GACT,yBAAyB,EACvB,QAAQ;;;;;;;;;;;;;;;;;2BAiBO,YAAY;uCAE7B;EACD,CAAA;EAEF,iBACC,iBAAA,GAAA,kBAAA,IAAA,CAACA,YAAAA,SAAD;GACE,IAAG;GACH,UAAS;GACT,yBAAyB,EACvB,QAAQ;;;;;;;;;;;;;;2BAcO,cAAc;wCAE/B;EACD,CAAA;EAEF,qBACC,iBAAA,GAAA,kBAAA,IAAA,CAACA,YAAAA,SAAD;GACE,IAAG;GACH,UAAS;GACT,yBAAyB,EACvB,QAAQ;wCACoB,kBAAkB;;;;;;;;;;;;;;;;;gBAkBhD;EACD,CAAA;EAEF,YACC,iBAAA,GAAA,kBAAA,IAAA,CAACA,YAAAA,SAAD;GACE,UAAS;GACT,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;kBAGF,aAAa,mCAAmC,KAAK,UAAU,UAAU,EAAE,MAAM,GAAG;;;;;;;;;;;;uBAY/E,SAAS;;;cAItB;EACD,CAAA;EAEF,YACC,iBAAA,GAAA,kBAAA,IAAA,CAACA,YAAAA,SAAD;GACE,IAAG;GACH,UAAS;GACT,yBAAyB,EACvB,QAAQ;;;oCAGgB,SAAS;;;;;;cAOnC;EACD,CAAA;CAEH,EAAA,CAAA;AAEN"}
|
package/dist/next/index.d.cts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { GaId, GtmId } from "../track/gtag.cjs";
|
|
2
2
|
import { PixelId } from "../track/fbq.cjs";
|
|
3
3
|
import { PixelId as PixelId$1 } from "../track/rdt.cjs";
|
|
4
|
+
import { UETConsent } from "../track/uetq.cjs";
|
|
4
5
|
//#region src/next/index.d.ts
|
|
5
6
|
interface Props {
|
|
6
7
|
gaId?: GaId;
|
|
@@ -14,11 +15,20 @@ interface Props {
|
|
|
14
15
|
uetTagId?: `${number}`;
|
|
15
16
|
/** Microsoft Advertising customer id (`cid` in the ads UI's URLs): enables the Conversions API's ID Sync pixel. */
|
|
16
17
|
uetCustomerId?: `${number}`;
|
|
18
|
+
/**
|
|
19
|
+
* UET consent mode default, pushed inside the tag snippet so bat.js reads it before the first
|
|
20
|
+
* page load. Defaults to `ad_storage: granted`, which is how the tag behaves without a signal,
|
|
21
|
+
* so Microsoft stops flagging EEA/UK/CH events as missing consent. Sites with a consent banner
|
|
22
|
+
* pass `{ ad_storage: 'denied' }` and send `update` with `setUETConsent` when the visitor
|
|
23
|
+
* decides; `false` pushes no default.
|
|
24
|
+
* https://help.ads.microsoft.com/#apex/ads/en/60119/1
|
|
25
|
+
*/
|
|
26
|
+
uetConsent?: UETConsent | false;
|
|
17
27
|
facebookAppId?: string;
|
|
18
28
|
nonce?: string;
|
|
19
29
|
debugMode?: boolean;
|
|
20
30
|
reportWebVitals?: boolean;
|
|
21
31
|
}
|
|
22
|
-
export declare function Analytics({ gaId, gaSrc, nonce, debugMode, metaPixelId, hotjarId, redditPixelId, linkedInPartnerId, uetTagId, uetCustomerId, facebookAppId, reportWebVitals }: Props): import("react").JSX.Element;
|
|
32
|
+
export declare function Analytics({ gaId, gaSrc, nonce, debugMode, metaPixelId, hotjarId, redditPixelId, linkedInPartnerId, uetTagId, uetCustomerId, uetConsent, facebookAppId, reportWebVitals }: Props): import("react").JSX.Element;
|
|
23
33
|
//#endregion
|
|
24
34
|
//# sourceMappingURL=index.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":["MetaPixelId","RedditPixelId"],"sources":["../../src/next/index.tsx"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":["MetaPixelId","RedditPixelId"],"sources":["../../src/next/index.tsx"],"mappings":";;;;;UAeU;EACR,OAAO;EACP;EACA,QAAQ;EACR;EACA,cAAcA;EACd,gBAAgBC;EAChB;;EAEA;;EAEA;;;;;;;;;EASA,aAAa;EACb;EACA;EACA;EACA;;wBAec,YACd,MACA,OACA,OACA,WACA,aACA,UACA,eACA,mBACA,UACA,eACA,YACA,eACA,mBACC,wBAAK,IAAA"}
|
package/dist/next/index.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { GaId, GtmId } from "../track/gtag.mjs";
|
|
2
2
|
import { PixelId } from "../track/fbq.mjs";
|
|
3
3
|
import { PixelId as PixelId$1 } from "../track/rdt.mjs";
|
|
4
|
+
import { UETConsent } from "../track/uetq.mjs";
|
|
4
5
|
//#region src/next/index.d.ts
|
|
5
6
|
interface Props {
|
|
6
7
|
gaId?: GaId;
|
|
@@ -14,11 +15,20 @@ interface Props {
|
|
|
14
15
|
uetTagId?: `${number}`;
|
|
15
16
|
/** Microsoft Advertising customer id (`cid` in the ads UI's URLs): enables the Conversions API's ID Sync pixel. */
|
|
16
17
|
uetCustomerId?: `${number}`;
|
|
18
|
+
/**
|
|
19
|
+
* UET consent mode default, pushed inside the tag snippet so bat.js reads it before the first
|
|
20
|
+
* page load. Defaults to `ad_storage: granted`, which is how the tag behaves without a signal,
|
|
21
|
+
* so Microsoft stops flagging EEA/UK/CH events as missing consent. Sites with a consent banner
|
|
22
|
+
* pass `{ ad_storage: 'denied' }` and send `update` with `setUETConsent` when the visitor
|
|
23
|
+
* decides; `false` pushes no default.
|
|
24
|
+
* https://help.ads.microsoft.com/#apex/ads/en/60119/1
|
|
25
|
+
*/
|
|
26
|
+
uetConsent?: UETConsent | false;
|
|
17
27
|
facebookAppId?: string;
|
|
18
28
|
nonce?: string;
|
|
19
29
|
debugMode?: boolean;
|
|
20
30
|
reportWebVitals?: boolean;
|
|
21
31
|
}
|
|
22
|
-
export declare function Analytics({ gaId, gaSrc, nonce, debugMode, metaPixelId, hotjarId, redditPixelId, linkedInPartnerId, uetTagId, uetCustomerId, facebookAppId, reportWebVitals }: Props): import("react").JSX.Element;
|
|
32
|
+
export declare function Analytics({ gaId, gaSrc, nonce, debugMode, metaPixelId, hotjarId, redditPixelId, linkedInPartnerId, uetTagId, uetCustomerId, uetConsent, facebookAppId, reportWebVitals }: Props): import("react").JSX.Element;
|
|
23
33
|
//#endregion
|
|
24
34
|
//# sourceMappingURL=index.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":["MetaPixelId","RedditPixelId"],"sources":["../../src/next/index.tsx"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":["MetaPixelId","RedditPixelId"],"sources":["../../src/next/index.tsx"],"mappings":";;;;;UAeU;EACR,OAAO;EACP;EACA,QAAQ;EACR;EACA,cAAcA;EACd,gBAAgBC;EAChB;;EAEA;;EAEA;;;;;;;;;EASA,aAAa;EACb;EACA;EACA;EACA;;wBAec,YACd,MACA,OACA,OACA,WACA,aACA,UACA,eACA,mBACA,UACA,eACA,YACA,eACA,mBACC,wBAAK,IAAA"}
|
package/dist/next/index.mjs
CHANGED
|
@@ -20,7 +20,7 @@ function PageViews() {
|
|
|
20
20
|
useWebAnalytics(pathname, searchParams.toString());
|
|
21
21
|
return null;
|
|
22
22
|
}
|
|
23
|
-
function Analytics({ gaId, gaSrc, nonce, debugMode, metaPixelId, hotjarId, redditPixelId, linkedInPartnerId, uetTagId, uetCustomerId, facebookAppId, reportWebVitals = true }) {
|
|
23
|
+
function Analytics({ gaId, gaSrc, nonce, debugMode, metaPixelId, hotjarId, redditPixelId, linkedInPartnerId, uetTagId, uetCustomerId, uetConsent = { ad_storage: "granted" }, facebookAppId, reportWebVitals = true }) {
|
|
24
24
|
useOutboundClickAnalytics();
|
|
25
25
|
useUETIdSync(uetCustomerId);
|
|
26
26
|
useReportWebVitals((metric) => {
|
|
@@ -131,6 +131,7 @@ function Analytics({ gaId, gaSrc, nonce, debugMode, metaPixelId, hotjarId, reddi
|
|
|
131
131
|
dangerouslySetInnerHTML: { __html: `
|
|
132
132
|
(function (w, d, t, u, o) {
|
|
133
133
|
w[u] = w[u] || [], o.ts = (new Date).getTime();
|
|
134
|
+
${uetConsent ? `w[u].push("consent", "default", ${JSON.stringify(uetConsent)});` : ""}
|
|
134
135
|
var n = d.createElement(t);
|
|
135
136
|
n.src = "https://bat.bing.net/bat.js?ti=" + o.ti + ("uetq" != u ? "&q=" + u : ""),
|
|
136
137
|
n.async = 1, n.onload = n.onreadystatechange = function() {
|
package/dist/next/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/next/index.tsx"],"sourcesContent":["'use client';\n\nimport { usePathname, useSearchParams } from 'next/navigation';\nimport Script from 'next/script';\nimport { useReportWebVitals } from 'next/web-vitals';\nimport { Suspense } from 'react';\nimport { useOutboundClickAnalytics } from '../hooks/use-outbound-click-analytics';\nimport { useUETIdSync } from '../hooks/use-uet-id-sync';\nimport { useWebAnalytics } from '../hooks/use-web-analytics';\nimport type { PixelId as MetaPixelId } from '../track/fbq';\nimport type { GaId, GtmId } from '../track/gtag';\nimport { track } from '../track/index';\nimport type { PixelId as RedditPixelId } from '../track/rdt';\n\ninterface Props {\n gaId?: GaId;\n gaSrc?: string;\n gtmId?: GtmId;\n hotjarId?: `${number}`;\n metaPixelId?: MetaPixelId;\n redditPixelId?: RedditPixelId;\n linkedInPartnerId?: `${number}`;\n /** Microsoft Advertising UET tag id. The tag reports page loads itself (`enableAutoSpaTracking`). */\n uetTagId?: `${number}`;\n /** Microsoft Advertising customer id (`cid` in the ads UI's URLs): enables the Conversions API's ID Sync pixel. */\n uetCustomerId?: `${number}`;\n facebookAppId?: string;\n nonce?: string;\n debugMode?: boolean;\n reportWebVitals?: boolean;\n}\n\n/**\n * Its own component under a Suspense boundary: `useSearchParams` in a statically rendered route\n * bails the whole tree out to client rendering unless something above it suspends, and Next\n * fails the build for a page that lets it. The boundary is here so a host does not have to know.\n */\nfunction PageViews() {\n const pathname = usePathname();\n const searchParams = useSearchParams();\n useWebAnalytics(pathname, searchParams.toString());\n return null;\n}\n\nexport function Analytics({\n gaId,\n gaSrc,\n nonce,\n debugMode,\n metaPixelId,\n hotjarId,\n redditPixelId,\n linkedInPartnerId,\n uetTagId,\n uetCustomerId,\n facebookAppId,\n reportWebVitals = true,\n}: Props) {\n useOutboundClickAnalytics();\n useUETIdSync(uetCustomerId);\n\n useReportWebVitals((metric) => {\n if (!reportWebVitals) return;\n const properties = {\n value: metric.delta,\n metric_id: metric.id,\n metric_value: metric.value,\n metric_delta: metric.delta,\n metric_rating: metric.rating,\n metric_navigation_type: metric.navigationType,\n non_interaction: true, // avoids affecting bounce rate.\n };\n track(metric.name, properties);\n });\n\n return (\n <>\n <Suspense fallback={null}>\n <PageViews />\n </Suspense>\n {facebookAppId && <meta property=\"fb:app_id\" content={facebookAppId} />}\n {gaId && (\n <>\n <Script\n id=\"gtag\"\n nonce={nonce}\n src={gaSrc ?? `https://www.googletagmanager.com/gtag/js?id=${gaId}`}\n />\n <Script\n nonce={nonce}\n id=\"gtag-init\"\n dangerouslySetInnerHTML={{\n __html: `\n window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('config', '${gaId}'${debugMode ? \" ,{ 'debug_mode': true }\" : ''});\n `,\n }}\n />\n </>\n )}\n {metaPixelId && (\n <Script\n id=\"meta-pixel\"\n strategy=\"afterInteractive\"\n dangerouslySetInnerHTML={{\n __html: `\n !(function (f, b, e, v, n, t, s) {\n if (f.fbq) return;\n n = f.fbq = function () {\n n.callMethod ? n.callMethod.apply(n, arguments) : n.queue.push(arguments);\n };\n if (!f._fbq) f._fbq = n;\n n.push = n;\n n.loaded = !0;\n n.version = '2.0';\n n.queue = [];\n t = b.createElement(e);\n t.async = !0;\n t.src = v;\n s = b.getElementsByTagName(e)[0];\n s.parentNode.insertBefore(t, s);\n })(window, document, 'script', 'https://connect.facebook.net/en_US/fbevents.js');\n fbq('init', '${metaPixelId}');\n fbq('track', 'PageView');`,\n }}\n />\n )}\n {redditPixelId && (\n <Script\n id=\"reddit-pixel\"\n strategy=\"afterInteractive\"\n dangerouslySetInnerHTML={{\n __html: `\n !function(w,d) {\n if(!w.rdt) {\n var p = w.rdt = function() {\n p.sendEvent ? p.sendEvent.apply(p,arguments) : p.callQueue.push(arguments)\n };\n p.callQueue = [];\n var t = d.createElement(\"script\");\n t.src = \"https://www.redditstatic.com/ads/pixel.js\";\n t.async = !0;\n var s = d.getElementsByTagName(\"script\")[0];\n s.parentNode.insertBefore(t,s)\n }\n }(window, document);\n rdt('init', '${redditPixelId}');\n rdt('track', 'PageVisit');`,\n }}\n />\n )}\n {linkedInPartnerId && (\n <Script\n id=\"linkedin-insight-tag\"\n strategy=\"afterInteractive\"\n dangerouslySetInnerHTML={{\n __html: `\n _linkedin_partner_id = \"${linkedInPartnerId}\";\n window._linkedin_data_partner_ids = window._linkedin_data_partner_ids || [];\n window._linkedin_data_partner_ids.push(_linkedin_partner_id);\n\n (function(l) {\n if (!l){\n window.lintrk = function(a,b){ \n window.lintrk.q.push([a,b])\n };\n window.lintrk.q=[]\n }\n var s = document.getElementsByTagName(\"script\")[0];\n var b = document.createElement(\"script\");\n b.type = \"text/javascript\";b.async = true;\n b.src = \"https://snap.licdn.com/li.lms-analytics/insight.min.js\";\n s.parentNode.insertBefore(b, s);\n })(window.lintrk);\n `,\n }}\n />\n )}\n {uetTagId && (\n <Script\n strategy=\"afterInteractive\"\n id=\"uet-tag\"\n dangerouslySetInnerHTML={{\n __html: `\n (function (w, d, t, u, o) {\n w[u] = w[u] || [], o.ts = (new Date).getTime();\n var n = d.createElement(t);\n n.src = \"https://bat.bing.net/bat.js?ti=\" + o.ti + (\"uetq\" != u ? \"&q=\" + u : \"\"),\n n.async = 1, n.onload = n.onreadystatechange = function() {\n var s = this.readyState;\n s && \"loaded\" !== s && \"complete\" !== s ||\n (o.q = w[u], w[u] = new UET(o), w[u].push(\"pageLoad\"),\n n.onload = n.onreadystatechange = null)\n };\n var i = d.getElementsByTagName(t)[0];\n i.parentNode.insertBefore(n, i);\n })(window, document, \"script\", \"uetq\", {\n ti: \"${uetTagId}\",\n enableAutoSpaTracking: true\n });\n `,\n }}\n />\n )}\n {hotjarId && (\n <Script\n id=\"hotjar\"\n strategy=\"afterInteractive\"\n dangerouslySetInnerHTML={{\n __html: `\n (function(h,o,t,j,a,r){\n h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};\n h._hjSettings={hjid:${hotjarId},hjsv:6};\n a=o.getElementsByTagName('head')[0];\n r=o.createElement('script');r.async=1;\n r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;\n a.appendChild(r);\n })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');\n `,\n }}\n />\n )}\n </>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAqCA,SAAS,YAAY;CACnB,MAAM,WAAW,YAAY;CAC7B,MAAM,eAAe,gBAAgB;CACrC,gBAAgB,UAAU,aAAa,SAAS,CAAC;CACjD,OAAO;AACT;AAEA,SAAgB,UAAU,EACxB,MACA,OACA,OACA,WACA,aACA,UACA,eACA,mBACA,UACA,eACA,eACA,kBAAkB,QACV;CACR,0BAA0B;CAC1B,aAAa,aAAa;CAE1B,oBAAoB,WAAW;EAC7B,IAAI,CAAC,iBAAiB;EACtB,MAAM,aAAa;GACjB,OAAO,OAAO;GACd,WAAW,OAAO;GAClB,cAAc,OAAO;GACrB,cAAc,OAAO;GACrB,eAAe,OAAO;GACtB,wBAAwB,OAAO;GAC/B,iBAAiB;EACnB;EACA,MAAM,OAAO,MAAM,UAAU;CAC/B,CAAC;CAED,OACE,qBAAA,UAAA,EAAA,UAAA;EACE,oBAAC,UAAD;GAAU,UAAU;GAClB,UAAA,oBAAC,WAAD,CAAY,CAAA;EACJ,CAAA;EACT,iBAAiB,oBAAC,QAAD;GAAM,UAAS;GAAY,SAAS;EAAgB,CAAA;EACrE,QACC,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,QAAD;GACE,IAAG;GACI;GACP,KAAK,SAAS,+CAA+C;EAC9D,CAAA,GACD,oBAAC,QAAD;GACS;GACP,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;;gCAIU,KAAK,GAAG,YAAY,6BAA6B,GAAG;cAExE;EACD,CAAA,CACD,EAAA,CAAA;EAEH,eACC,oBAAC,QAAD;GACE,IAAG;GACH,UAAS;GACT,yBAAyB,EACvB,QAAQ;;;;;;;;;;;;;;;;;2BAiBO,YAAY;uCAE7B;EACD,CAAA;EAEF,iBACC,oBAAC,QAAD;GACE,IAAG;GACH,UAAS;GACT,yBAAyB,EACvB,QAAQ;;;;;;;;;;;;;;2BAcO,cAAc;wCAE/B;EACD,CAAA;EAEF,qBACC,oBAAC,QAAD;GACE,IAAG;GACH,UAAS;GACT,yBAAyB,EACvB,QAAQ;wCACoB,kBAAkB;;;;;;;;;;;;;;;;;gBAkBhD;EACD,CAAA;EAEF,YACC,oBAAC,QAAD;GACE,UAAS;GACT,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;;;;;;;;;;;;uBAcG,SAAS;;;cAItB;EACD,CAAA;EAEF,YACC,oBAAC,QAAD;GACE,IAAG;GACH,UAAS;GACT,yBAAyB,EACvB,QAAQ;;;oCAGgB,SAAS;;;;;;cAOnC;EACD,CAAA;CAEH,EAAA,CAAA;AAEN"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/next/index.tsx"],"sourcesContent":["'use client';\n\nimport { usePathname, useSearchParams } from 'next/navigation';\nimport Script from 'next/script';\nimport { useReportWebVitals } from 'next/web-vitals';\nimport { Suspense } from 'react';\nimport { useOutboundClickAnalytics } from '../hooks/use-outbound-click-analytics';\nimport { useUETIdSync } from '../hooks/use-uet-id-sync';\nimport { useWebAnalytics } from '../hooks/use-web-analytics';\nimport type { PixelId as MetaPixelId } from '../track/fbq';\nimport type { GaId, GtmId } from '../track/gtag';\nimport { track } from '../track/index';\nimport type { PixelId as RedditPixelId } from '../track/rdt';\nimport type { UETConsent } from '../track/uetq';\n\ninterface Props {\n gaId?: GaId;\n gaSrc?: string;\n gtmId?: GtmId;\n hotjarId?: `${number}`;\n metaPixelId?: MetaPixelId;\n redditPixelId?: RedditPixelId;\n linkedInPartnerId?: `${number}`;\n /** Microsoft Advertising UET tag id. The tag reports page loads itself (`enableAutoSpaTracking`). */\n uetTagId?: `${number}`;\n /** Microsoft Advertising customer id (`cid` in the ads UI's URLs): enables the Conversions API's ID Sync pixel. */\n uetCustomerId?: `${number}`;\n /**\n * UET consent mode default, pushed inside the tag snippet so bat.js reads it before the first\n * page load. Defaults to `ad_storage: granted`, which is how the tag behaves without a signal,\n * so Microsoft stops flagging EEA/UK/CH events as missing consent. Sites with a consent banner\n * pass `{ ad_storage: 'denied' }` and send `update` with `setUETConsent` when the visitor\n * decides; `false` pushes no default.\n * https://help.ads.microsoft.com/#apex/ads/en/60119/1\n */\n uetConsent?: UETConsent | false;\n facebookAppId?: string;\n nonce?: string;\n debugMode?: boolean;\n reportWebVitals?: boolean;\n}\n\n/**\n * Its own component under a Suspense boundary: `useSearchParams` in a statically rendered route\n * bails the whole tree out to client rendering unless something above it suspends, and Next\n * fails the build for a page that lets it. The boundary is here so a host does not have to know.\n */\nfunction PageViews() {\n const pathname = usePathname();\n const searchParams = useSearchParams();\n useWebAnalytics(pathname, searchParams.toString());\n return null;\n}\n\nexport function Analytics({\n gaId,\n gaSrc,\n nonce,\n debugMode,\n metaPixelId,\n hotjarId,\n redditPixelId,\n linkedInPartnerId,\n uetTagId,\n uetCustomerId,\n uetConsent = { ad_storage: 'granted' },\n facebookAppId,\n reportWebVitals = true,\n}: Props) {\n useOutboundClickAnalytics();\n useUETIdSync(uetCustomerId);\n\n useReportWebVitals((metric) => {\n if (!reportWebVitals) return;\n const properties = {\n value: metric.delta,\n metric_id: metric.id,\n metric_value: metric.value,\n metric_delta: metric.delta,\n metric_rating: metric.rating,\n metric_navigation_type: metric.navigationType,\n non_interaction: true, // avoids affecting bounce rate.\n };\n track(metric.name, properties);\n });\n\n return (\n <>\n <Suspense fallback={null}>\n <PageViews />\n </Suspense>\n {facebookAppId && <meta property=\"fb:app_id\" content={facebookAppId} />}\n {gaId && (\n <>\n <Script\n id=\"gtag\"\n nonce={nonce}\n src={gaSrc ?? `https://www.googletagmanager.com/gtag/js?id=${gaId}`}\n />\n <Script\n nonce={nonce}\n id=\"gtag-init\"\n dangerouslySetInnerHTML={{\n __html: `\n window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('config', '${gaId}'${debugMode ? \" ,{ 'debug_mode': true }\" : ''});\n `,\n }}\n />\n </>\n )}\n {metaPixelId && (\n <Script\n id=\"meta-pixel\"\n strategy=\"afterInteractive\"\n dangerouslySetInnerHTML={{\n __html: `\n !(function (f, b, e, v, n, t, s) {\n if (f.fbq) return;\n n = f.fbq = function () {\n n.callMethod ? n.callMethod.apply(n, arguments) : n.queue.push(arguments);\n };\n if (!f._fbq) f._fbq = n;\n n.push = n;\n n.loaded = !0;\n n.version = '2.0';\n n.queue = [];\n t = b.createElement(e);\n t.async = !0;\n t.src = v;\n s = b.getElementsByTagName(e)[0];\n s.parentNode.insertBefore(t, s);\n })(window, document, 'script', 'https://connect.facebook.net/en_US/fbevents.js');\n fbq('init', '${metaPixelId}');\n fbq('track', 'PageView');`,\n }}\n />\n )}\n {redditPixelId && (\n <Script\n id=\"reddit-pixel\"\n strategy=\"afterInteractive\"\n dangerouslySetInnerHTML={{\n __html: `\n !function(w,d) {\n if(!w.rdt) {\n var p = w.rdt = function() {\n p.sendEvent ? p.sendEvent.apply(p,arguments) : p.callQueue.push(arguments)\n };\n p.callQueue = [];\n var t = d.createElement(\"script\");\n t.src = \"https://www.redditstatic.com/ads/pixel.js\";\n t.async = !0;\n var s = d.getElementsByTagName(\"script\")[0];\n s.parentNode.insertBefore(t,s)\n }\n }(window, document);\n rdt('init', '${redditPixelId}');\n rdt('track', 'PageVisit');`,\n }}\n />\n )}\n {linkedInPartnerId && (\n <Script\n id=\"linkedin-insight-tag\"\n strategy=\"afterInteractive\"\n dangerouslySetInnerHTML={{\n __html: `\n _linkedin_partner_id = \"${linkedInPartnerId}\";\n window._linkedin_data_partner_ids = window._linkedin_data_partner_ids || [];\n window._linkedin_data_partner_ids.push(_linkedin_partner_id);\n\n (function(l) {\n if (!l){\n window.lintrk = function(a,b){ \n window.lintrk.q.push([a,b])\n };\n window.lintrk.q=[]\n }\n var s = document.getElementsByTagName(\"script\")[0];\n var b = document.createElement(\"script\");\n b.type = \"text/javascript\";b.async = true;\n b.src = \"https://snap.licdn.com/li.lms-analytics/insight.min.js\";\n s.parentNode.insertBefore(b, s);\n })(window.lintrk);\n `,\n }}\n />\n )}\n {uetTagId && (\n <Script\n strategy=\"afterInteractive\"\n id=\"uet-tag\"\n dangerouslySetInnerHTML={{\n __html: `\n (function (w, d, t, u, o) {\n w[u] = w[u] || [], o.ts = (new Date).getTime();\n ${uetConsent ? `w[u].push(\"consent\", \"default\", ${JSON.stringify(uetConsent)});` : ''}\n var n = d.createElement(t);\n n.src = \"https://bat.bing.net/bat.js?ti=\" + o.ti + (\"uetq\" != u ? \"&q=\" + u : \"\"),\n n.async = 1, n.onload = n.onreadystatechange = function() {\n var s = this.readyState;\n s && \"loaded\" !== s && \"complete\" !== s ||\n (o.q = w[u], w[u] = new UET(o), w[u].push(\"pageLoad\"),\n n.onload = n.onreadystatechange = null)\n };\n var i = d.getElementsByTagName(t)[0];\n i.parentNode.insertBefore(n, i);\n })(window, document, \"script\", \"uetq\", {\n ti: \"${uetTagId}\",\n enableAutoSpaTracking: true\n });\n `,\n }}\n />\n )}\n {hotjarId && (\n <Script\n id=\"hotjar\"\n strategy=\"afterInteractive\"\n dangerouslySetInnerHTML={{\n __html: `\n (function(h,o,t,j,a,r){\n h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};\n h._hjSettings={hjid:${hotjarId},hjsv:6};\n a=o.getElementsByTagName('head')[0];\n r=o.createElement('script');r.async=1;\n r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;\n a.appendChild(r);\n })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');\n `,\n }}\n />\n )}\n </>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA+CA,SAAS,YAAY;CACnB,MAAM,WAAW,YAAY;CAC7B,MAAM,eAAe,gBAAgB;CACrC,gBAAgB,UAAU,aAAa,SAAS,CAAC;CACjD,OAAO;AACT;AAEA,SAAgB,UAAU,EACxB,MACA,OACA,OACA,WACA,aACA,UACA,eACA,mBACA,UACA,eACA,aAAa,EAAE,YAAY,UAAU,GACrC,eACA,kBAAkB,QACV;CACR,0BAA0B;CAC1B,aAAa,aAAa;CAE1B,oBAAoB,WAAW;EAC7B,IAAI,CAAC,iBAAiB;EACtB,MAAM,aAAa;GACjB,OAAO,OAAO;GACd,WAAW,OAAO;GAClB,cAAc,OAAO;GACrB,cAAc,OAAO;GACrB,eAAe,OAAO;GACtB,wBAAwB,OAAO;GAC/B,iBAAiB;EACnB;EACA,MAAM,OAAO,MAAM,UAAU;CAC/B,CAAC;CAED,OACE,qBAAA,UAAA,EAAA,UAAA;EACE,oBAAC,UAAD;GAAU,UAAU;GAClB,UAAA,oBAAC,WAAD,CAAY,CAAA;EACJ,CAAA;EACT,iBAAiB,oBAAC,QAAD;GAAM,UAAS;GAAY,SAAS;EAAgB,CAAA;EACrE,QACC,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,QAAD;GACE,IAAG;GACI;GACP,KAAK,SAAS,+CAA+C;EAC9D,CAAA,GACD,oBAAC,QAAD;GACS;GACP,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;;gCAIU,KAAK,GAAG,YAAY,6BAA6B,GAAG;cAExE;EACD,CAAA,CACD,EAAA,CAAA;EAEH,eACC,oBAAC,QAAD;GACE,IAAG;GACH,UAAS;GACT,yBAAyB,EACvB,QAAQ;;;;;;;;;;;;;;;;;2BAiBO,YAAY;uCAE7B;EACD,CAAA;EAEF,iBACC,oBAAC,QAAD;GACE,IAAG;GACH,UAAS;GACT,yBAAyB,EACvB,QAAQ;;;;;;;;;;;;;;2BAcO,cAAc;wCAE/B;EACD,CAAA;EAEF,qBACC,oBAAC,QAAD;GACE,IAAG;GACH,UAAS;GACT,yBAAyB,EACvB,QAAQ;wCACoB,kBAAkB;;;;;;;;;;;;;;;;;gBAkBhD;EACD,CAAA;EAEF,YACC,oBAAC,QAAD;GACE,UAAS;GACT,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;kBAGF,aAAa,mCAAmC,KAAK,UAAU,UAAU,EAAE,MAAM,GAAG;;;;;;;;;;;;uBAY/E,SAAS;;;cAItB;EACD,CAAA;EAEF,YACC,oBAAC,QAAD;GACE,IAAG;GACH,UAAS;GACT,yBAAyB,EACvB,QAAQ;;;oCAGgB,SAAS;;;;;;cAOnC;EACD,CAAA;CAEH,EAAA,CAAA;AAEN"}
|
|
@@ -7,7 +7,7 @@ const require_hooks_use_web_analytics = require("../hooks/use-web-analytics.cjs"
|
|
|
7
7
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
8
8
|
let _tanstack_react_router = require("@tanstack/react-router");
|
|
9
9
|
//#region src/tanstack/analytics.tsx
|
|
10
|
-
function Analytics({ gaId, gaSrc, nonce, debugMode, metaPixelId, openaiPixelId, redditPixelId, linkedInPartnerId, uetTagId, uetCustomerId, hotjarId, facebookAppId, reportWebVitals = true }) {
|
|
10
|
+
function Analytics({ gaId, gaSrc, nonce, debugMode, metaPixelId, openaiPixelId, redditPixelId, linkedInPartnerId, uetTagId, uetCustomerId, uetConsent = { ad_storage: "granted" }, hotjarId, facebookAppId, reportWebVitals = true }) {
|
|
11
11
|
const { pathname, searchStr } = (0, _tanstack_react_router.useLocation)();
|
|
12
12
|
require_hooks_use_web_analytics.useWebAnalytics(pathname, searchStr);
|
|
13
13
|
require_hooks_use_outbound_click_analytics.useOutboundClickAnalytics();
|
|
@@ -140,6 +140,7 @@ function Analytics({ gaId, gaSrc, nonce, debugMode, metaPixelId, openaiPixelId,
|
|
|
140
140
|
dangerouslySetInnerHTML: { __html: `
|
|
141
141
|
(function (w, d, t, u, o) {
|
|
142
142
|
w[u] = w[u] || [], o.ts = (new Date).getTime();
|
|
143
|
+
${uetConsent ? `w[u].push("consent", "default", ${JSON.stringify(uetConsent)});` : ""}
|
|
143
144
|
var n = d.createElement(t);
|
|
144
145
|
n.src = "https://bat.bing.net/bat.js?ti=" + o.ti + ("uetq" != u ? "&q=" + u : ""),
|
|
145
146
|
n.async = 1, n.onload = n.onreadystatechange = function() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analytics.cjs","names":["useLocation"],"sources":["../../src/tanstack/analytics.tsx"],"sourcesContent":["import { useLocation } from '@tanstack/react-router';\nimport { useOutboundClickAnalytics } from '../hooks/use-outbound-click-analytics';\nimport { useReportWebVitals } from '../hooks/use-report-web-vitals';\nimport { useUETIdSync } from '../hooks/use-uet-id-sync';\nimport { useWebAnalytics } from '../hooks/use-web-analytics';\nimport type { PixelId as MetaPixelId } from '../track/fbq';\nimport type { GaId, GtmId } from '../track/gtag';\nimport { track } from '../track/index';\nimport type { PixelId as RedditPixelId } from '../track/rdt';\n\ninterface Props {\n gaId?: GaId;\n gaSrc?: string;\n gtmId?: GtmId;\n metaPixelId?: MetaPixelId;\n openaiPixelId?: string;\n redditPixelId?: RedditPixelId;\n linkedInPartnerId?: `${number}`;\n /** Microsoft Advertising UET tag id. The tag reports page loads itself (`enableAutoSpaTracking`). */\n uetTagId?: `${number}`;\n /** Microsoft Advertising customer id (`cid` in the ads UI's URLs): enables the Conversions API's ID Sync pixel. */\n uetCustomerId?: `${number}`;\n hotjarId?: `${number}`;\n facebookAppId?: string;\n nonce?: string;\n debugMode?: boolean;\n reportWebVitals?: boolean;\n}\n\nexport function Analytics({\n gaId,\n gaSrc,\n nonce,\n debugMode,\n metaPixelId,\n openaiPixelId,\n redditPixelId,\n linkedInPartnerId,\n uetTagId,\n uetCustomerId,\n hotjarId,\n facebookAppId,\n reportWebVitals = true,\n}: Props) {\n const { pathname, searchStr } = useLocation();\n useWebAnalytics(pathname, searchStr);\n useOutboundClickAnalytics();\n useUETIdSync(uetCustomerId);\n\n useReportWebVitals((metric) => {\n if (!reportWebVitals) return;\n const properties = {\n value: metric.delta,\n metric_id: metric.id,\n metric_value: metric.value,\n metric_delta: metric.delta,\n metric_rating: metric.rating,\n metric_navigation_type: metric.navigationType,\n non_interaction: true, // avoids affecting bounce rate.\n };\n track(metric.name, properties);\n });\n\n return (\n <>\n {facebookAppId && <meta property=\"fb:app_id\" content={facebookAppId} />}\n {gaId && (\n <>\n <script\n async\n id=\"gtag\"\n nonce={nonce}\n src={gaSrc ?? `https://www.googletagmanager.com/gtag/js?id=${gaId}`}\n />\n <script\n async\n nonce={nonce}\n id=\"gtag-init\"\n dangerouslySetInnerHTML={{\n __html: `\n window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('config', '${gaId}'${debugMode ? \" ,{ 'debug_mode': true }\" : ''});\n `,\n }}\n />\n </>\n )}\n {metaPixelId && (\n <script\n async\n id=\"meta-pixel\"\n dangerouslySetInnerHTML={{\n __html: `\n !(function (f, b, e, v, n, t, s) {\n if (f.fbq) return;\n n = f.fbq = function () {\n n.callMethod ? n.callMethod.apply(n, arguments) : n.queue.push(arguments);\n };\n if (!f._fbq) f._fbq = n;\n n.push = n;\n n.loaded = !0;\n n.version = '2.0';\n n.queue = [];\n t = b.createElement(e);\n t.async = !0;\n t.src = v;\n s = b.getElementsByTagName(e)[0];\n s.parentNode.insertBefore(t, s);\n })(window, document, 'script', 'https://connect.facebook.net/en_US/fbevents.js');\n fbq('init', '${metaPixelId}');\n fbq('track', 'PageView');`,\n }}\n />\n )}\n {openaiPixelId && (\n <script\n async\n id=\"openai-pixel\"\n dangerouslySetInnerHTML={{\n __html: `\n (function (w, d, s, u) {\n if (w.oaiq) return;\n var q = function () {\n q.q.push(arguments);\n };\n q.q = [];\n w.oaiq = q;\n var js = d.createElement(s);\n js.async = true;\n js.src = u;\n var f = d.getElementsByTagName(s)[0];\n f.parentNode.insertBefore(js, f);\n })(window, document, \"script\", \"https://bzrcdn.openai.com/sdk/oaiq.min.js\");\n\n oaiq(\"init\", { pixelId: \"${openaiPixelId}\" });\n oaiq(\"measure\", \"page_viewed\", { type: \"contents\" });\n `,\n }}\n />\n )}\n {redditPixelId && (\n <script\n async\n id=\"reddit-pixel\"\n dangerouslySetInnerHTML={{\n __html: `\n !function(w,d) {\n if(!w.rdt) {\n var p = w.rdt = function() {\n p.sendEvent ? p.sendEvent.apply(p,arguments) : p.callQueue.push(arguments)\n };\n p.callQueue = [];\n var t = d.createElement(\"script\");\n t.src = \"https://www.redditstatic.com/ads/pixel.js\";\n t.async = !0;\n var s = d.getElementsByTagName(\"script\")[0];\n s.parentNode.insertBefore(t,s)\n }\n }(window, document);\n rdt('init', '${redditPixelId}');\n rdt('track', 'PageVisit');`,\n }}\n />\n )}\n {linkedInPartnerId && (\n <script\n async\n id=\"linkedin-insight-tag\"\n dangerouslySetInnerHTML={{\n __html: `\n _linkedin_partner_id = \"${linkedInPartnerId}\";\n window._linkedin_data_partner_ids = window._linkedin_data_partner_ids || [];\n window._linkedin_data_partner_ids.push(_linkedin_partner_id);\n\n (function(l) {\n if (!l){\n window.lintrk = function(a,b){\n window.lintrk.q.push([a,b])\n };\n window.lintrk.q=[]\n }\n var s = document.getElementsByTagName(\"script\")[0];\n var b = document.createElement(\"script\");\n b.type = \"text/javascript\";b.async = true;\n b.src = \"https://snap.licdn.com/li.lms-analytics/insight.min.js\";\n s.parentNode.insertBefore(b, s);\n })(window.lintrk);\n `,\n }}\n />\n )}\n {uetTagId && (\n <script\n async\n id=\"uet-tag\"\n dangerouslySetInnerHTML={{\n __html: `\n (function (w, d, t, u, o) {\n w[u] = w[u] || [], o.ts = (new Date).getTime();\n var n = d.createElement(t);\n n.src = \"https://bat.bing.net/bat.js?ti=\" + o.ti + (\"uetq\" != u ? \"&q=\" + u : \"\"),\n n.async = 1, n.onload = n.onreadystatechange = function() {\n var s = this.readyState;\n s && \"loaded\" !== s && \"complete\" !== s ||\n (o.q = w[u], w[u] = new UET(o), w[u].push(\"pageLoad\"),\n n.onload = n.onreadystatechange = null)\n };\n var i = d.getElementsByTagName(t)[0];\n i.parentNode.insertBefore(n, i);\n })(window, document, \"script\", \"uetq\", {\n ti: \"${uetTagId}\",\n enableAutoSpaTracking: true\n });\n `,\n }}\n />\n )}\n {hotjarId && (\n <script\n async\n id=\"hotjar\"\n dangerouslySetInnerHTML={{\n __html: `\n (function(h,o,t,j,a,r){\n h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};\n h._hjSettings={hjid:${hotjarId},hjsv:6};\n a=o.getElementsByTagName('head')[0];\n r=o.createElement('script');r.async=1;\n r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;\n a.appendChild(r);\n })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');\n `,\n }}\n />\n )}\n </>\n );\n}\n"],"mappings":";;;;;;;;;AA6BA,SAAgB,UAAU,EACxB,MACA,OACA,OACA,WACA,aACA,eACA,eACA,mBACA,UACA,eACA,UACA,eACA,kBAAkB,QACV;CACR,MAAM,EAAE,UAAU,eAAA,GAAcA,uBAAAA,YAAAA,CAAY;CAC5C,gCAAA,gBAAgB,UAAU,SAAS;CACnC,2CAAA,0BAA0B;CAC1B,8BAAA,aAAa,aAAa;CAE1B,oCAAA,oBAAoB,WAAW;EAC7B,IAAI,CAAC,iBAAiB;EACtB,MAAM,aAAa;GACjB,OAAO,OAAO;GACd,WAAW,OAAO;GAClB,cAAc,OAAO;GACrB,cAAc,OAAO;GACrB,eAAe,OAAO;GACtB,wBAAwB,OAAO;GAC/B,iBAAiB;EACnB;EACA,oBAAA,MAAM,OAAO,MAAM,UAAU;CAC/B,CAAC;CAED,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA;EACG,iBAAiB,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;GAAM,UAAS;GAAY,SAAS;EAAgB,CAAA;EACrE,QACC,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;GACE,OAAA;GACA,IAAG;GACI;GACP,KAAK,SAAS,+CAA+C;EAC9D,CAAA,GACD,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;GACE,OAAA;GACO;GACP,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;;gCAIU,KAAK,GAAG,YAAY,6BAA6B,GAAG;cAExE;EACD,CAAA,CACD,EAAA,CAAA;EAEH,eACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;GACE,OAAA;GACA,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;;;;;;;;;;;;;;;2BAiBO,YAAY;uCAE7B;EACD,CAAA;EAEF,iBACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;GACE,OAAA;GACA,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;;;;;;;;;;;;;2CAeuB,cAAc;;cAG/C;EACD,CAAA;EAEF,iBACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;GACE,OAAA;GACA,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;;;;;;;;;;;;2BAcO,cAAc;wCAE/B;EACD,CAAA;EAEF,qBACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;GACE,OAAA;GACA,IAAG;GACH,yBAAyB,EACvB,QAAQ;sCACkB,kBAAkB;;;;;;;;;;;;;;;;;cAkB9C;EACD,CAAA;EAEF,YACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;GACE,OAAA;GACA,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;;;;;;;;;;;;uBAcG,SAAS;;;cAItB;EACD,CAAA;EAEF,YACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;GACE,OAAA;GACA,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;oCAGgB,SAAS;;;;;;cAOnC;EACD,CAAA;CAEH,EAAA,CAAA;AAEN"}
|
|
1
|
+
{"version":3,"file":"analytics.cjs","names":["useLocation"],"sources":["../../src/tanstack/analytics.tsx"],"sourcesContent":["import { useLocation } from '@tanstack/react-router';\nimport { useOutboundClickAnalytics } from '../hooks/use-outbound-click-analytics';\nimport { useReportWebVitals } from '../hooks/use-report-web-vitals';\nimport { useUETIdSync } from '../hooks/use-uet-id-sync';\nimport { useWebAnalytics } from '../hooks/use-web-analytics';\nimport type { PixelId as MetaPixelId } from '../track/fbq';\nimport type { GaId, GtmId } from '../track/gtag';\nimport { track } from '../track/index';\nimport type { PixelId as RedditPixelId } from '../track/rdt';\nimport type { UETConsent } from '../track/uetq';\n\ninterface Props {\n gaId?: GaId;\n gaSrc?: string;\n gtmId?: GtmId;\n metaPixelId?: MetaPixelId;\n openaiPixelId?: string;\n redditPixelId?: RedditPixelId;\n linkedInPartnerId?: `${number}`;\n /** Microsoft Advertising UET tag id. The tag reports page loads itself (`enableAutoSpaTracking`). */\n uetTagId?: `${number}`;\n /** Microsoft Advertising customer id (`cid` in the ads UI's URLs): enables the Conversions API's ID Sync pixel. */\n uetCustomerId?: `${number}`;\n /**\n * UET consent mode default, pushed inside the tag snippet so bat.js reads it before the first\n * page load. Defaults to `ad_storage: granted`, which is how the tag behaves without a signal,\n * so Microsoft stops flagging EEA/UK/CH events as missing consent. Sites with a consent banner\n * pass `{ ad_storage: 'denied' }` and send `update` with `setUETConsent` when the visitor\n * decides; `false` pushes no default.\n * https://help.ads.microsoft.com/#apex/ads/en/60119/1\n */\n uetConsent?: UETConsent | false;\n hotjarId?: `${number}`;\n facebookAppId?: string;\n nonce?: string;\n debugMode?: boolean;\n reportWebVitals?: boolean;\n}\n\nexport function Analytics({\n gaId,\n gaSrc,\n nonce,\n debugMode,\n metaPixelId,\n openaiPixelId,\n redditPixelId,\n linkedInPartnerId,\n uetTagId,\n uetCustomerId,\n uetConsent = { ad_storage: 'granted' },\n hotjarId,\n facebookAppId,\n reportWebVitals = true,\n}: Props) {\n const { pathname, searchStr } = useLocation();\n useWebAnalytics(pathname, searchStr);\n useOutboundClickAnalytics();\n useUETIdSync(uetCustomerId);\n\n useReportWebVitals((metric) => {\n if (!reportWebVitals) return;\n const properties = {\n value: metric.delta,\n metric_id: metric.id,\n metric_value: metric.value,\n metric_delta: metric.delta,\n metric_rating: metric.rating,\n metric_navigation_type: metric.navigationType,\n non_interaction: true, // avoids affecting bounce rate.\n };\n track(metric.name, properties);\n });\n\n return (\n <>\n {facebookAppId && <meta property=\"fb:app_id\" content={facebookAppId} />}\n {gaId && (\n <>\n <script\n async\n id=\"gtag\"\n nonce={nonce}\n src={gaSrc ?? `https://www.googletagmanager.com/gtag/js?id=${gaId}`}\n />\n <script\n async\n nonce={nonce}\n id=\"gtag-init\"\n dangerouslySetInnerHTML={{\n __html: `\n window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('config', '${gaId}'${debugMode ? \" ,{ 'debug_mode': true }\" : ''});\n `,\n }}\n />\n </>\n )}\n {metaPixelId && (\n <script\n async\n id=\"meta-pixel\"\n dangerouslySetInnerHTML={{\n __html: `\n !(function (f, b, e, v, n, t, s) {\n if (f.fbq) return;\n n = f.fbq = function () {\n n.callMethod ? n.callMethod.apply(n, arguments) : n.queue.push(arguments);\n };\n if (!f._fbq) f._fbq = n;\n n.push = n;\n n.loaded = !0;\n n.version = '2.0';\n n.queue = [];\n t = b.createElement(e);\n t.async = !0;\n t.src = v;\n s = b.getElementsByTagName(e)[0];\n s.parentNode.insertBefore(t, s);\n })(window, document, 'script', 'https://connect.facebook.net/en_US/fbevents.js');\n fbq('init', '${metaPixelId}');\n fbq('track', 'PageView');`,\n }}\n />\n )}\n {openaiPixelId && (\n <script\n async\n id=\"openai-pixel\"\n dangerouslySetInnerHTML={{\n __html: `\n (function (w, d, s, u) {\n if (w.oaiq) return;\n var q = function () {\n q.q.push(arguments);\n };\n q.q = [];\n w.oaiq = q;\n var js = d.createElement(s);\n js.async = true;\n js.src = u;\n var f = d.getElementsByTagName(s)[0];\n f.parentNode.insertBefore(js, f);\n })(window, document, \"script\", \"https://bzrcdn.openai.com/sdk/oaiq.min.js\");\n\n oaiq(\"init\", { pixelId: \"${openaiPixelId}\" });\n oaiq(\"measure\", \"page_viewed\", { type: \"contents\" });\n `,\n }}\n />\n )}\n {redditPixelId && (\n <script\n async\n id=\"reddit-pixel\"\n dangerouslySetInnerHTML={{\n __html: `\n !function(w,d) {\n if(!w.rdt) {\n var p = w.rdt = function() {\n p.sendEvent ? p.sendEvent.apply(p,arguments) : p.callQueue.push(arguments)\n };\n p.callQueue = [];\n var t = d.createElement(\"script\");\n t.src = \"https://www.redditstatic.com/ads/pixel.js\";\n t.async = !0;\n var s = d.getElementsByTagName(\"script\")[0];\n s.parentNode.insertBefore(t,s)\n }\n }(window, document);\n rdt('init', '${redditPixelId}');\n rdt('track', 'PageVisit');`,\n }}\n />\n )}\n {linkedInPartnerId && (\n <script\n async\n id=\"linkedin-insight-tag\"\n dangerouslySetInnerHTML={{\n __html: `\n _linkedin_partner_id = \"${linkedInPartnerId}\";\n window._linkedin_data_partner_ids = window._linkedin_data_partner_ids || [];\n window._linkedin_data_partner_ids.push(_linkedin_partner_id);\n\n (function(l) {\n if (!l){\n window.lintrk = function(a,b){\n window.lintrk.q.push([a,b])\n };\n window.lintrk.q=[]\n }\n var s = document.getElementsByTagName(\"script\")[0];\n var b = document.createElement(\"script\");\n b.type = \"text/javascript\";b.async = true;\n b.src = \"https://snap.licdn.com/li.lms-analytics/insight.min.js\";\n s.parentNode.insertBefore(b, s);\n })(window.lintrk);\n `,\n }}\n />\n )}\n {uetTagId && (\n <script\n async\n id=\"uet-tag\"\n dangerouslySetInnerHTML={{\n __html: `\n (function (w, d, t, u, o) {\n w[u] = w[u] || [], o.ts = (new Date).getTime();\n ${uetConsent ? `w[u].push(\"consent\", \"default\", ${JSON.stringify(uetConsent)});` : ''}\n var n = d.createElement(t);\n n.src = \"https://bat.bing.net/bat.js?ti=\" + o.ti + (\"uetq\" != u ? \"&q=\" + u : \"\"),\n n.async = 1, n.onload = n.onreadystatechange = function() {\n var s = this.readyState;\n s && \"loaded\" !== s && \"complete\" !== s ||\n (o.q = w[u], w[u] = new UET(o), w[u].push(\"pageLoad\"),\n n.onload = n.onreadystatechange = null)\n };\n var i = d.getElementsByTagName(t)[0];\n i.parentNode.insertBefore(n, i);\n })(window, document, \"script\", \"uetq\", {\n ti: \"${uetTagId}\",\n enableAutoSpaTracking: true\n });\n `,\n }}\n />\n )}\n {hotjarId && (\n <script\n async\n id=\"hotjar\"\n dangerouslySetInnerHTML={{\n __html: `\n (function(h,o,t,j,a,r){\n h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};\n h._hjSettings={hjid:${hotjarId},hjsv:6};\n a=o.getElementsByTagName('head')[0];\n r=o.createElement('script');r.async=1;\n r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;\n a.appendChild(r);\n })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');\n `,\n }}\n />\n )}\n </>\n );\n}\n"],"mappings":";;;;;;;;;AAuCA,SAAgB,UAAU,EACxB,MACA,OACA,OACA,WACA,aACA,eACA,eACA,mBACA,UACA,eACA,aAAa,EAAE,YAAY,UAAU,GACrC,UACA,eACA,kBAAkB,QACV;CACR,MAAM,EAAE,UAAU,eAAA,GAAcA,uBAAAA,YAAAA,CAAY;CAC5C,gCAAA,gBAAgB,UAAU,SAAS;CACnC,2CAAA,0BAA0B;CAC1B,8BAAA,aAAa,aAAa;CAE1B,oCAAA,oBAAoB,WAAW;EAC7B,IAAI,CAAC,iBAAiB;EACtB,MAAM,aAAa;GACjB,OAAO,OAAO;GACd,WAAW,OAAO;GAClB,cAAc,OAAO;GACrB,cAAc,OAAO;GACrB,eAAe,OAAO;GACtB,wBAAwB,OAAO;GAC/B,iBAAiB;EACnB;EACA,oBAAA,MAAM,OAAO,MAAM,UAAU;CAC/B,CAAC;CAED,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA;EACG,iBAAiB,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;GAAM,UAAS;GAAY,SAAS;EAAgB,CAAA;EACrE,QACC,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;GACE,OAAA;GACA,IAAG;GACI;GACP,KAAK,SAAS,+CAA+C;EAC9D,CAAA,GACD,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;GACE,OAAA;GACO;GACP,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;;gCAIU,KAAK,GAAG,YAAY,6BAA6B,GAAG;cAExE;EACD,CAAA,CACD,EAAA,CAAA;EAEH,eACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;GACE,OAAA;GACA,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;;;;;;;;;;;;;;;2BAiBO,YAAY;uCAE7B;EACD,CAAA;EAEF,iBACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;GACE,OAAA;GACA,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;;;;;;;;;;;;;2CAeuB,cAAc;;cAG/C;EACD,CAAA;EAEF,iBACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;GACE,OAAA;GACA,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;;;;;;;;;;;;2BAcO,cAAc;wCAE/B;EACD,CAAA;EAEF,qBACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;GACE,OAAA;GACA,IAAG;GACH,yBAAyB,EACvB,QAAQ;sCACkB,kBAAkB;;;;;;;;;;;;;;;;;cAkB9C;EACD,CAAA;EAEF,YACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;GACE,OAAA;GACA,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;kBAGF,aAAa,mCAAmC,KAAK,UAAU,UAAU,EAAE,MAAM,GAAG;;;;;;;;;;;;uBAY/E,SAAS;;;cAItB;EACD,CAAA;EAEF,YACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;GACE,OAAA;GACA,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;oCAGgB,SAAS;;;;;;cAOnC;EACD,CAAA;CAEH,EAAA,CAAA;AAEN"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { GaId, GtmId } from "../track/gtag.cjs";
|
|
2
2
|
import { PixelId } from "../track/fbq.cjs";
|
|
3
3
|
import { PixelId as PixelId$1 } from "../track/rdt.cjs";
|
|
4
|
+
import { UETConsent } from "../track/uetq.cjs";
|
|
4
5
|
//#region src/tanstack/analytics.d.ts
|
|
5
6
|
interface Props {
|
|
6
7
|
gaId?: GaId;
|
|
@@ -14,12 +15,21 @@ interface Props {
|
|
|
14
15
|
uetTagId?: `${number}`;
|
|
15
16
|
/** Microsoft Advertising customer id (`cid` in the ads UI's URLs): enables the Conversions API's ID Sync pixel. */
|
|
16
17
|
uetCustomerId?: `${number}`;
|
|
18
|
+
/**
|
|
19
|
+
* UET consent mode default, pushed inside the tag snippet so bat.js reads it before the first
|
|
20
|
+
* page load. Defaults to `ad_storage: granted`, which is how the tag behaves without a signal,
|
|
21
|
+
* so Microsoft stops flagging EEA/UK/CH events as missing consent. Sites with a consent banner
|
|
22
|
+
* pass `{ ad_storage: 'denied' }` and send `update` with `setUETConsent` when the visitor
|
|
23
|
+
* decides; `false` pushes no default.
|
|
24
|
+
* https://help.ads.microsoft.com/#apex/ads/en/60119/1
|
|
25
|
+
*/
|
|
26
|
+
uetConsent?: UETConsent | false;
|
|
17
27
|
hotjarId?: `${number}`;
|
|
18
28
|
facebookAppId?: string;
|
|
19
29
|
nonce?: string;
|
|
20
30
|
debugMode?: boolean;
|
|
21
31
|
reportWebVitals?: boolean;
|
|
22
32
|
}
|
|
23
|
-
export declare function Analytics({ gaId, gaSrc, nonce, debugMode, metaPixelId, openaiPixelId, redditPixelId, linkedInPartnerId, uetTagId, uetCustomerId, hotjarId, facebookAppId, reportWebVitals }: Props): import("react").JSX.Element;
|
|
33
|
+
export declare function Analytics({ gaId, gaSrc, nonce, debugMode, metaPixelId, openaiPixelId, redditPixelId, linkedInPartnerId, uetTagId, uetCustomerId, uetConsent, hotjarId, facebookAppId, reportWebVitals }: Props): import("react").JSX.Element;
|
|
24
34
|
//#endregion
|
|
25
35
|
//# sourceMappingURL=analytics.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analytics.d.cts","names":["MetaPixelId","RedditPixelId"],"sources":["../../src/tanstack/analytics.tsx"],"mappings":"
|
|
1
|
+
{"version":3,"file":"analytics.d.cts","names":["MetaPixelId","RedditPixelId"],"sources":["../../src/tanstack/analytics.tsx"],"mappings":";;;;;UAWU;EACR,OAAO;EACP;EACA,QAAQ;EACR,cAAcA;EACd;EACA,gBAAgBC;EAChB;;EAEA;;EAEA;;;;;;;;;EASA,aAAa;EACb;EACA;EACA;EACA;EACA;;wBAGc,YACd,MACA,OACA,OACA,WACA,aACA,eACA,eACA,mBACA,UACA,eACA,YACA,UACA,eACA,mBACC,wBAAK,IAAA"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { GaId, GtmId } from "../track/gtag.mjs";
|
|
2
2
|
import { PixelId } from "../track/fbq.mjs";
|
|
3
3
|
import { PixelId as PixelId$1 } from "../track/rdt.mjs";
|
|
4
|
+
import { UETConsent } from "../track/uetq.mjs";
|
|
4
5
|
//#region src/tanstack/analytics.d.ts
|
|
5
6
|
interface Props {
|
|
6
7
|
gaId?: GaId;
|
|
@@ -14,12 +15,21 @@ interface Props {
|
|
|
14
15
|
uetTagId?: `${number}`;
|
|
15
16
|
/** Microsoft Advertising customer id (`cid` in the ads UI's URLs): enables the Conversions API's ID Sync pixel. */
|
|
16
17
|
uetCustomerId?: `${number}`;
|
|
18
|
+
/**
|
|
19
|
+
* UET consent mode default, pushed inside the tag snippet so bat.js reads it before the first
|
|
20
|
+
* page load. Defaults to `ad_storage: granted`, which is how the tag behaves without a signal,
|
|
21
|
+
* so Microsoft stops flagging EEA/UK/CH events as missing consent. Sites with a consent banner
|
|
22
|
+
* pass `{ ad_storage: 'denied' }` and send `update` with `setUETConsent` when the visitor
|
|
23
|
+
* decides; `false` pushes no default.
|
|
24
|
+
* https://help.ads.microsoft.com/#apex/ads/en/60119/1
|
|
25
|
+
*/
|
|
26
|
+
uetConsent?: UETConsent | false;
|
|
17
27
|
hotjarId?: `${number}`;
|
|
18
28
|
facebookAppId?: string;
|
|
19
29
|
nonce?: string;
|
|
20
30
|
debugMode?: boolean;
|
|
21
31
|
reportWebVitals?: boolean;
|
|
22
32
|
}
|
|
23
|
-
export declare function Analytics({ gaId, gaSrc, nonce, debugMode, metaPixelId, openaiPixelId, redditPixelId, linkedInPartnerId, uetTagId, uetCustomerId, hotjarId, facebookAppId, reportWebVitals }: Props): import("react").JSX.Element;
|
|
33
|
+
export declare function Analytics({ gaId, gaSrc, nonce, debugMode, metaPixelId, openaiPixelId, redditPixelId, linkedInPartnerId, uetTagId, uetCustomerId, uetConsent, hotjarId, facebookAppId, reportWebVitals }: Props): import("react").JSX.Element;
|
|
24
34
|
//#endregion
|
|
25
35
|
//# sourceMappingURL=analytics.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analytics.d.mts","names":["MetaPixelId","RedditPixelId"],"sources":["../../src/tanstack/analytics.tsx"],"mappings":"
|
|
1
|
+
{"version":3,"file":"analytics.d.mts","names":["MetaPixelId","RedditPixelId"],"sources":["../../src/tanstack/analytics.tsx"],"mappings":";;;;;UAWU;EACR,OAAO;EACP;EACA,QAAQ;EACR,cAAcA;EACd;EACA,gBAAgBC;EAChB;;EAEA;;EAEA;;;;;;;;;EASA,aAAa;EACb;EACA;EACA;EACA;EACA;;wBAGc,YACd,MACA,OACA,OACA,WACA,aACA,eACA,eACA,mBACA,UACA,eACA,YACA,UACA,eACA,mBACC,wBAAK,IAAA"}
|
|
@@ -6,7 +6,7 @@ import { useWebAnalytics } from "../hooks/use-web-analytics.mjs";
|
|
|
6
6
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
import { useLocation } from "@tanstack/react-router";
|
|
8
8
|
//#region src/tanstack/analytics.tsx
|
|
9
|
-
function Analytics({ gaId, gaSrc, nonce, debugMode, metaPixelId, openaiPixelId, redditPixelId, linkedInPartnerId, uetTagId, uetCustomerId, hotjarId, facebookAppId, reportWebVitals = true }) {
|
|
9
|
+
function Analytics({ gaId, gaSrc, nonce, debugMode, metaPixelId, openaiPixelId, redditPixelId, linkedInPartnerId, uetTagId, uetCustomerId, uetConsent = { ad_storage: "granted" }, hotjarId, facebookAppId, reportWebVitals = true }) {
|
|
10
10
|
const { pathname, searchStr } = useLocation();
|
|
11
11
|
useWebAnalytics(pathname, searchStr);
|
|
12
12
|
useOutboundClickAnalytics();
|
|
@@ -139,6 +139,7 @@ function Analytics({ gaId, gaSrc, nonce, debugMode, metaPixelId, openaiPixelId,
|
|
|
139
139
|
dangerouslySetInnerHTML: { __html: `
|
|
140
140
|
(function (w, d, t, u, o) {
|
|
141
141
|
w[u] = w[u] || [], o.ts = (new Date).getTime();
|
|
142
|
+
${uetConsent ? `w[u].push("consent", "default", ${JSON.stringify(uetConsent)});` : ""}
|
|
142
143
|
var n = d.createElement(t);
|
|
143
144
|
n.src = "https://bat.bing.net/bat.js?ti=" + o.ti + ("uetq" != u ? "&q=" + u : ""),
|
|
144
145
|
n.async = 1, n.onload = n.onreadystatechange = function() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analytics.mjs","names":[],"sources":["../../src/tanstack/analytics.tsx"],"sourcesContent":["import { useLocation } from '@tanstack/react-router';\nimport { useOutboundClickAnalytics } from '../hooks/use-outbound-click-analytics';\nimport { useReportWebVitals } from '../hooks/use-report-web-vitals';\nimport { useUETIdSync } from '../hooks/use-uet-id-sync';\nimport { useWebAnalytics } from '../hooks/use-web-analytics';\nimport type { PixelId as MetaPixelId } from '../track/fbq';\nimport type { GaId, GtmId } from '../track/gtag';\nimport { track } from '../track/index';\nimport type { PixelId as RedditPixelId } from '../track/rdt';\n\ninterface Props {\n gaId?: GaId;\n gaSrc?: string;\n gtmId?: GtmId;\n metaPixelId?: MetaPixelId;\n openaiPixelId?: string;\n redditPixelId?: RedditPixelId;\n linkedInPartnerId?: `${number}`;\n /** Microsoft Advertising UET tag id. The tag reports page loads itself (`enableAutoSpaTracking`). */\n uetTagId?: `${number}`;\n /** Microsoft Advertising customer id (`cid` in the ads UI's URLs): enables the Conversions API's ID Sync pixel. */\n uetCustomerId?: `${number}`;\n hotjarId?: `${number}`;\n facebookAppId?: string;\n nonce?: string;\n debugMode?: boolean;\n reportWebVitals?: boolean;\n}\n\nexport function Analytics({\n gaId,\n gaSrc,\n nonce,\n debugMode,\n metaPixelId,\n openaiPixelId,\n redditPixelId,\n linkedInPartnerId,\n uetTagId,\n uetCustomerId,\n hotjarId,\n facebookAppId,\n reportWebVitals = true,\n}: Props) {\n const { pathname, searchStr } = useLocation();\n useWebAnalytics(pathname, searchStr);\n useOutboundClickAnalytics();\n useUETIdSync(uetCustomerId);\n\n useReportWebVitals((metric) => {\n if (!reportWebVitals) return;\n const properties = {\n value: metric.delta,\n metric_id: metric.id,\n metric_value: metric.value,\n metric_delta: metric.delta,\n metric_rating: metric.rating,\n metric_navigation_type: metric.navigationType,\n non_interaction: true, // avoids affecting bounce rate.\n };\n track(metric.name, properties);\n });\n\n return (\n <>\n {facebookAppId && <meta property=\"fb:app_id\" content={facebookAppId} />}\n {gaId && (\n <>\n <script\n async\n id=\"gtag\"\n nonce={nonce}\n src={gaSrc ?? `https://www.googletagmanager.com/gtag/js?id=${gaId}`}\n />\n <script\n async\n nonce={nonce}\n id=\"gtag-init\"\n dangerouslySetInnerHTML={{\n __html: `\n window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('config', '${gaId}'${debugMode ? \" ,{ 'debug_mode': true }\" : ''});\n `,\n }}\n />\n </>\n )}\n {metaPixelId && (\n <script\n async\n id=\"meta-pixel\"\n dangerouslySetInnerHTML={{\n __html: `\n !(function (f, b, e, v, n, t, s) {\n if (f.fbq) return;\n n = f.fbq = function () {\n n.callMethod ? n.callMethod.apply(n, arguments) : n.queue.push(arguments);\n };\n if (!f._fbq) f._fbq = n;\n n.push = n;\n n.loaded = !0;\n n.version = '2.0';\n n.queue = [];\n t = b.createElement(e);\n t.async = !0;\n t.src = v;\n s = b.getElementsByTagName(e)[0];\n s.parentNode.insertBefore(t, s);\n })(window, document, 'script', 'https://connect.facebook.net/en_US/fbevents.js');\n fbq('init', '${metaPixelId}');\n fbq('track', 'PageView');`,\n }}\n />\n )}\n {openaiPixelId && (\n <script\n async\n id=\"openai-pixel\"\n dangerouslySetInnerHTML={{\n __html: `\n (function (w, d, s, u) {\n if (w.oaiq) return;\n var q = function () {\n q.q.push(arguments);\n };\n q.q = [];\n w.oaiq = q;\n var js = d.createElement(s);\n js.async = true;\n js.src = u;\n var f = d.getElementsByTagName(s)[0];\n f.parentNode.insertBefore(js, f);\n })(window, document, \"script\", \"https://bzrcdn.openai.com/sdk/oaiq.min.js\");\n\n oaiq(\"init\", { pixelId: \"${openaiPixelId}\" });\n oaiq(\"measure\", \"page_viewed\", { type: \"contents\" });\n `,\n }}\n />\n )}\n {redditPixelId && (\n <script\n async\n id=\"reddit-pixel\"\n dangerouslySetInnerHTML={{\n __html: `\n !function(w,d) {\n if(!w.rdt) {\n var p = w.rdt = function() {\n p.sendEvent ? p.sendEvent.apply(p,arguments) : p.callQueue.push(arguments)\n };\n p.callQueue = [];\n var t = d.createElement(\"script\");\n t.src = \"https://www.redditstatic.com/ads/pixel.js\";\n t.async = !0;\n var s = d.getElementsByTagName(\"script\")[0];\n s.parentNode.insertBefore(t,s)\n }\n }(window, document);\n rdt('init', '${redditPixelId}');\n rdt('track', 'PageVisit');`,\n }}\n />\n )}\n {linkedInPartnerId && (\n <script\n async\n id=\"linkedin-insight-tag\"\n dangerouslySetInnerHTML={{\n __html: `\n _linkedin_partner_id = \"${linkedInPartnerId}\";\n window._linkedin_data_partner_ids = window._linkedin_data_partner_ids || [];\n window._linkedin_data_partner_ids.push(_linkedin_partner_id);\n\n (function(l) {\n if (!l){\n window.lintrk = function(a,b){\n window.lintrk.q.push([a,b])\n };\n window.lintrk.q=[]\n }\n var s = document.getElementsByTagName(\"script\")[0];\n var b = document.createElement(\"script\");\n b.type = \"text/javascript\";b.async = true;\n b.src = \"https://snap.licdn.com/li.lms-analytics/insight.min.js\";\n s.parentNode.insertBefore(b, s);\n })(window.lintrk);\n `,\n }}\n />\n )}\n {uetTagId && (\n <script\n async\n id=\"uet-tag\"\n dangerouslySetInnerHTML={{\n __html: `\n (function (w, d, t, u, o) {\n w[u] = w[u] || [], o.ts = (new Date).getTime();\n var n = d.createElement(t);\n n.src = \"https://bat.bing.net/bat.js?ti=\" + o.ti + (\"uetq\" != u ? \"&q=\" + u : \"\"),\n n.async = 1, n.onload = n.onreadystatechange = function() {\n var s = this.readyState;\n s && \"loaded\" !== s && \"complete\" !== s ||\n (o.q = w[u], w[u] = new UET(o), w[u].push(\"pageLoad\"),\n n.onload = n.onreadystatechange = null)\n };\n var i = d.getElementsByTagName(t)[0];\n i.parentNode.insertBefore(n, i);\n })(window, document, \"script\", \"uetq\", {\n ti: \"${uetTagId}\",\n enableAutoSpaTracking: true\n });\n `,\n }}\n />\n )}\n {hotjarId && (\n <script\n async\n id=\"hotjar\"\n dangerouslySetInnerHTML={{\n __html: `\n (function(h,o,t,j,a,r){\n h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};\n h._hjSettings={hjid:${hotjarId},hjsv:6};\n a=o.getElementsByTagName('head')[0];\n r=o.createElement('script');r.async=1;\n r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;\n a.appendChild(r);\n })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');\n `,\n }}\n />\n )}\n </>\n );\n}\n"],"mappings":";;;;;;;;AA6BA,SAAgB,UAAU,EACxB,MACA,OACA,OACA,WACA,aACA,eACA,eACA,mBACA,UACA,eACA,UACA,eACA,kBAAkB,QACV;CACR,MAAM,EAAE,UAAU,cAAc,YAAY;CAC5C,gBAAgB,UAAU,SAAS;CACnC,0BAA0B;CAC1B,aAAa,aAAa;CAE1B,oBAAoB,WAAW;EAC7B,IAAI,CAAC,iBAAiB;EACtB,MAAM,aAAa;GACjB,OAAO,OAAO;GACd,WAAW,OAAO;GAClB,cAAc,OAAO;GACrB,cAAc,OAAO;GACrB,eAAe,OAAO;GACtB,wBAAwB,OAAO;GAC/B,iBAAiB;EACnB;EACA,MAAM,OAAO,MAAM,UAAU;CAC/B,CAAC;CAED,OACE,qBAAA,UAAA,EAAA,UAAA;EACG,iBAAiB,oBAAC,QAAD;GAAM,UAAS;GAAY,SAAS;EAAgB,CAAA;EACrE,QACC,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,UAAD;GACE,OAAA;GACA,IAAG;GACI;GACP,KAAK,SAAS,+CAA+C;EAC9D,CAAA,GACD,oBAAC,UAAD;GACE,OAAA;GACO;GACP,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;;gCAIU,KAAK,GAAG,YAAY,6BAA6B,GAAG;cAExE;EACD,CAAA,CACD,EAAA,CAAA;EAEH,eACC,oBAAC,UAAD;GACE,OAAA;GACA,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;;;;;;;;;;;;;;;2BAiBO,YAAY;uCAE7B;EACD,CAAA;EAEF,iBACC,oBAAC,UAAD;GACE,OAAA;GACA,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;;;;;;;;;;;;;2CAeuB,cAAc;;cAG/C;EACD,CAAA;EAEF,iBACC,oBAAC,UAAD;GACE,OAAA;GACA,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;;;;;;;;;;;;2BAcO,cAAc;wCAE/B;EACD,CAAA;EAEF,qBACC,oBAAC,UAAD;GACE,OAAA;GACA,IAAG;GACH,yBAAyB,EACvB,QAAQ;sCACkB,kBAAkB;;;;;;;;;;;;;;;;;cAkB9C;EACD,CAAA;EAEF,YACC,oBAAC,UAAD;GACE,OAAA;GACA,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;;;;;;;;;;;;uBAcG,SAAS;;;cAItB;EACD,CAAA;EAEF,YACC,oBAAC,UAAD;GACE,OAAA;GACA,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;oCAGgB,SAAS;;;;;;cAOnC;EACD,CAAA;CAEH,EAAA,CAAA;AAEN"}
|
|
1
|
+
{"version":3,"file":"analytics.mjs","names":[],"sources":["../../src/tanstack/analytics.tsx"],"sourcesContent":["import { useLocation } from '@tanstack/react-router';\nimport { useOutboundClickAnalytics } from '../hooks/use-outbound-click-analytics';\nimport { useReportWebVitals } from '../hooks/use-report-web-vitals';\nimport { useUETIdSync } from '../hooks/use-uet-id-sync';\nimport { useWebAnalytics } from '../hooks/use-web-analytics';\nimport type { PixelId as MetaPixelId } from '../track/fbq';\nimport type { GaId, GtmId } from '../track/gtag';\nimport { track } from '../track/index';\nimport type { PixelId as RedditPixelId } from '../track/rdt';\nimport type { UETConsent } from '../track/uetq';\n\ninterface Props {\n gaId?: GaId;\n gaSrc?: string;\n gtmId?: GtmId;\n metaPixelId?: MetaPixelId;\n openaiPixelId?: string;\n redditPixelId?: RedditPixelId;\n linkedInPartnerId?: `${number}`;\n /** Microsoft Advertising UET tag id. The tag reports page loads itself (`enableAutoSpaTracking`). */\n uetTagId?: `${number}`;\n /** Microsoft Advertising customer id (`cid` in the ads UI's URLs): enables the Conversions API's ID Sync pixel. */\n uetCustomerId?: `${number}`;\n /**\n * UET consent mode default, pushed inside the tag snippet so bat.js reads it before the first\n * page load. Defaults to `ad_storage: granted`, which is how the tag behaves without a signal,\n * so Microsoft stops flagging EEA/UK/CH events as missing consent. Sites with a consent banner\n * pass `{ ad_storage: 'denied' }` and send `update` with `setUETConsent` when the visitor\n * decides; `false` pushes no default.\n * https://help.ads.microsoft.com/#apex/ads/en/60119/1\n */\n uetConsent?: UETConsent | false;\n hotjarId?: `${number}`;\n facebookAppId?: string;\n nonce?: string;\n debugMode?: boolean;\n reportWebVitals?: boolean;\n}\n\nexport function Analytics({\n gaId,\n gaSrc,\n nonce,\n debugMode,\n metaPixelId,\n openaiPixelId,\n redditPixelId,\n linkedInPartnerId,\n uetTagId,\n uetCustomerId,\n uetConsent = { ad_storage: 'granted' },\n hotjarId,\n facebookAppId,\n reportWebVitals = true,\n}: Props) {\n const { pathname, searchStr } = useLocation();\n useWebAnalytics(pathname, searchStr);\n useOutboundClickAnalytics();\n useUETIdSync(uetCustomerId);\n\n useReportWebVitals((metric) => {\n if (!reportWebVitals) return;\n const properties = {\n value: metric.delta,\n metric_id: metric.id,\n metric_value: metric.value,\n metric_delta: metric.delta,\n metric_rating: metric.rating,\n metric_navigation_type: metric.navigationType,\n non_interaction: true, // avoids affecting bounce rate.\n };\n track(metric.name, properties);\n });\n\n return (\n <>\n {facebookAppId && <meta property=\"fb:app_id\" content={facebookAppId} />}\n {gaId && (\n <>\n <script\n async\n id=\"gtag\"\n nonce={nonce}\n src={gaSrc ?? `https://www.googletagmanager.com/gtag/js?id=${gaId}`}\n />\n <script\n async\n nonce={nonce}\n id=\"gtag-init\"\n dangerouslySetInnerHTML={{\n __html: `\n window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('config', '${gaId}'${debugMode ? \" ,{ 'debug_mode': true }\" : ''});\n `,\n }}\n />\n </>\n )}\n {metaPixelId && (\n <script\n async\n id=\"meta-pixel\"\n dangerouslySetInnerHTML={{\n __html: `\n !(function (f, b, e, v, n, t, s) {\n if (f.fbq) return;\n n = f.fbq = function () {\n n.callMethod ? n.callMethod.apply(n, arguments) : n.queue.push(arguments);\n };\n if (!f._fbq) f._fbq = n;\n n.push = n;\n n.loaded = !0;\n n.version = '2.0';\n n.queue = [];\n t = b.createElement(e);\n t.async = !0;\n t.src = v;\n s = b.getElementsByTagName(e)[0];\n s.parentNode.insertBefore(t, s);\n })(window, document, 'script', 'https://connect.facebook.net/en_US/fbevents.js');\n fbq('init', '${metaPixelId}');\n fbq('track', 'PageView');`,\n }}\n />\n )}\n {openaiPixelId && (\n <script\n async\n id=\"openai-pixel\"\n dangerouslySetInnerHTML={{\n __html: `\n (function (w, d, s, u) {\n if (w.oaiq) return;\n var q = function () {\n q.q.push(arguments);\n };\n q.q = [];\n w.oaiq = q;\n var js = d.createElement(s);\n js.async = true;\n js.src = u;\n var f = d.getElementsByTagName(s)[0];\n f.parentNode.insertBefore(js, f);\n })(window, document, \"script\", \"https://bzrcdn.openai.com/sdk/oaiq.min.js\");\n\n oaiq(\"init\", { pixelId: \"${openaiPixelId}\" });\n oaiq(\"measure\", \"page_viewed\", { type: \"contents\" });\n `,\n }}\n />\n )}\n {redditPixelId && (\n <script\n async\n id=\"reddit-pixel\"\n dangerouslySetInnerHTML={{\n __html: `\n !function(w,d) {\n if(!w.rdt) {\n var p = w.rdt = function() {\n p.sendEvent ? p.sendEvent.apply(p,arguments) : p.callQueue.push(arguments)\n };\n p.callQueue = [];\n var t = d.createElement(\"script\");\n t.src = \"https://www.redditstatic.com/ads/pixel.js\";\n t.async = !0;\n var s = d.getElementsByTagName(\"script\")[0];\n s.parentNode.insertBefore(t,s)\n }\n }(window, document);\n rdt('init', '${redditPixelId}');\n rdt('track', 'PageVisit');`,\n }}\n />\n )}\n {linkedInPartnerId && (\n <script\n async\n id=\"linkedin-insight-tag\"\n dangerouslySetInnerHTML={{\n __html: `\n _linkedin_partner_id = \"${linkedInPartnerId}\";\n window._linkedin_data_partner_ids = window._linkedin_data_partner_ids || [];\n window._linkedin_data_partner_ids.push(_linkedin_partner_id);\n\n (function(l) {\n if (!l){\n window.lintrk = function(a,b){\n window.lintrk.q.push([a,b])\n };\n window.lintrk.q=[]\n }\n var s = document.getElementsByTagName(\"script\")[0];\n var b = document.createElement(\"script\");\n b.type = \"text/javascript\";b.async = true;\n b.src = \"https://snap.licdn.com/li.lms-analytics/insight.min.js\";\n s.parentNode.insertBefore(b, s);\n })(window.lintrk);\n `,\n }}\n />\n )}\n {uetTagId && (\n <script\n async\n id=\"uet-tag\"\n dangerouslySetInnerHTML={{\n __html: `\n (function (w, d, t, u, o) {\n w[u] = w[u] || [], o.ts = (new Date).getTime();\n ${uetConsent ? `w[u].push(\"consent\", \"default\", ${JSON.stringify(uetConsent)});` : ''}\n var n = d.createElement(t);\n n.src = \"https://bat.bing.net/bat.js?ti=\" + o.ti + (\"uetq\" != u ? \"&q=\" + u : \"\"),\n n.async = 1, n.onload = n.onreadystatechange = function() {\n var s = this.readyState;\n s && \"loaded\" !== s && \"complete\" !== s ||\n (o.q = w[u], w[u] = new UET(o), w[u].push(\"pageLoad\"),\n n.onload = n.onreadystatechange = null)\n };\n var i = d.getElementsByTagName(t)[0];\n i.parentNode.insertBefore(n, i);\n })(window, document, \"script\", \"uetq\", {\n ti: \"${uetTagId}\",\n enableAutoSpaTracking: true\n });\n `,\n }}\n />\n )}\n {hotjarId && (\n <script\n async\n id=\"hotjar\"\n dangerouslySetInnerHTML={{\n __html: `\n (function(h,o,t,j,a,r){\n h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};\n h._hjSettings={hjid:${hotjarId},hjsv:6};\n a=o.getElementsByTagName('head')[0];\n r=o.createElement('script');r.async=1;\n r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;\n a.appendChild(r);\n })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');\n `,\n }}\n />\n )}\n </>\n );\n}\n"],"mappings":";;;;;;;;AAuCA,SAAgB,UAAU,EACxB,MACA,OACA,OACA,WACA,aACA,eACA,eACA,mBACA,UACA,eACA,aAAa,EAAE,YAAY,UAAU,GACrC,UACA,eACA,kBAAkB,QACV;CACR,MAAM,EAAE,UAAU,cAAc,YAAY;CAC5C,gBAAgB,UAAU,SAAS;CACnC,0BAA0B;CAC1B,aAAa,aAAa;CAE1B,oBAAoB,WAAW;EAC7B,IAAI,CAAC,iBAAiB;EACtB,MAAM,aAAa;GACjB,OAAO,OAAO;GACd,WAAW,OAAO;GAClB,cAAc,OAAO;GACrB,cAAc,OAAO;GACrB,eAAe,OAAO;GACtB,wBAAwB,OAAO;GAC/B,iBAAiB;EACnB;EACA,MAAM,OAAO,MAAM,UAAU;CAC/B,CAAC;CAED,OACE,qBAAA,UAAA,EAAA,UAAA;EACG,iBAAiB,oBAAC,QAAD;GAAM,UAAS;GAAY,SAAS;EAAgB,CAAA;EACrE,QACC,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,UAAD;GACE,OAAA;GACA,IAAG;GACI;GACP,KAAK,SAAS,+CAA+C;EAC9D,CAAA,GACD,oBAAC,UAAD;GACE,OAAA;GACO;GACP,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;;gCAIU,KAAK,GAAG,YAAY,6BAA6B,GAAG;cAExE;EACD,CAAA,CACD,EAAA,CAAA;EAEH,eACC,oBAAC,UAAD;GACE,OAAA;GACA,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;;;;;;;;;;;;;;;2BAiBO,YAAY;uCAE7B;EACD,CAAA;EAEF,iBACC,oBAAC,UAAD;GACE,OAAA;GACA,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;;;;;;;;;;;;;2CAeuB,cAAc;;cAG/C;EACD,CAAA;EAEF,iBACC,oBAAC,UAAD;GACE,OAAA;GACA,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;;;;;;;;;;;;2BAcO,cAAc;wCAE/B;EACD,CAAA;EAEF,qBACC,oBAAC,UAAD;GACE,OAAA;GACA,IAAG;GACH,yBAAyB,EACvB,QAAQ;sCACkB,kBAAkB;;;;;;;;;;;;;;;;;cAkB9C;EACD,CAAA;EAEF,YACC,oBAAC,UAAD;GACE,OAAA;GACA,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;kBAGF,aAAa,mCAAmC,KAAK,UAAU,UAAU,EAAE,MAAM,GAAG;;;;;;;;;;;;uBAY/E,SAAS;;;cAItB;EACD,CAAA;EAEF,YACC,oBAAC,UAAD;GACE,OAAA;GACA,IAAG;GACH,yBAAyB,EACvB,QAAQ;;;oCAGgB,SAAS;;;;;;cAOnC;EACD,CAAA;CAEH,EAAA,CAAA;AAEN"}
|
|
@@ -3,6 +3,18 @@ const require_click_id_index = require("../click-id/index.cjs");
|
|
|
3
3
|
let _tanstack_react_start = require("@tanstack/react-start");
|
|
4
4
|
//#region src/tanstack/middleware.ts
|
|
5
5
|
/**
|
|
6
|
+
* Whether a response could be stored by a shared cache (a CDN) under its `Cache-Control`. One
|
|
7
|
+
* that is `private` or `no-store` already cannot, so a per-user `Set-Cookie` on it is safe as it
|
|
8
|
+
* is, and its own caching is kept — the gtag.js loader served through a first-party Google Tag
|
|
9
|
+
* Gateway (`private, max-age=…`) stays in the browser cache, where a browser never replays a
|
|
10
|
+
* `Set-Cookie`. Anything else — `public`, `s-maxage`, no header at all — might be shared, and is
|
|
11
|
+
* made uncacheable.
|
|
12
|
+
*/
|
|
13
|
+
function sharedCacheable(value) {
|
|
14
|
+
if (!value) return true;
|
|
15
|
+
return !value.toLowerCase().split(",").map((directive) => directive.trim()).some((directive) => directive === "private" || directive.startsWith("private=") || directive === "no-store");
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
6
18
|
* TanStack Start request middleware that persists the ad platforms' first-party cookies on the
|
|
7
19
|
* document response: `_fbc`, `_fbp`, `_gcl_aw` / `_gcl_gb`, `_rdt_cid`, `_rdt_uuid`,
|
|
8
20
|
* `_uetmsclkid`, `__oppref` and `__obref`.
|
|
@@ -43,7 +55,7 @@ function createClickIdMiddleware(options) {
|
|
|
43
55
|
});
|
|
44
56
|
if (cookies.length > 0) {
|
|
45
57
|
for (const header of require_click_id_index.toSetCookieHeaders(cookies)) result.response.headers.append("set-cookie", header);
|
|
46
|
-
if (cacheControl !== false) result.response.headers.set("cache-control", cacheControl);
|
|
58
|
+
if (cacheControl !== false && sharedCacheable(result.response.headers.get("cache-control"))) result.response.headers.set("cache-control", cacheControl);
|
|
47
59
|
}
|
|
48
60
|
return result;
|
|
49
61
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.cjs","names":["createMiddleware","resolveClickIdCookies","toSetCookieHeaders"],"sources":["../../src/tanstack/middleware.ts"],"sourcesContent":["import { createMiddleware } from '@tanstack/react-start';\nimport { resolveClickIdCookies, toSetCookieHeaders } from '../click-id/index';\n\nexport interface ClickIdMiddlewareOptions {\n /**\n * `Domain` attribute for the cookies: the site's registrable domain, e.g. `.shware.io`, where the\n * pixels write theirs. Required — set it in production; `null` (host-only) is for `localhost`.\n * See `ResolveClickIdCookiesInput.domain`.\n */\n domain: string | null;\n /** `Secure` attribute, default true. Set false only for local http testing. */\n secure?: boolean;\n /** subdomainIndex for a freshly built `_fbc` (com=0, example.com=1, www.example.com=2). Default 1. */\n subdomainIndex?: number;\n /**\n * Re-issue the stored click and browser ids on every request as an ITP self-heal: the pixels\n * rewrite them through `document.cookie`, which Safari caps at 7 days (24 hours on an\n * ad-decorated landing), and the re-issue restores the long-lived HTTP cookie. On by default.\n * Note it attaches a per-user `Set-Cookie` — and thus `no-store` — to every page response of a\n * visitor carrying one; set false to keep those pages CDN-cacheable. See\n * {@link resolveClickIdCookies}.\n */\n refresh?: boolean;\n /**\n *
|
|
1
|
+
{"version":3,"file":"middleware.cjs","names":["createMiddleware","resolveClickIdCookies","toSetCookieHeaders"],"sources":["../../src/tanstack/middleware.ts"],"sourcesContent":["import { createMiddleware } from '@tanstack/react-start';\nimport { resolveClickIdCookies, toSetCookieHeaders } from '../click-id/index';\n\nexport interface ClickIdMiddlewareOptions {\n /**\n * `Domain` attribute for the cookies: the site's registrable domain, e.g. `.shware.io`, where the\n * pixels write theirs. Required — set it in production; `null` (host-only) is for `localhost`.\n * See `ResolveClickIdCookiesInput.domain`.\n */\n domain: string | null;\n /** `Secure` attribute, default true. Set false only for local http testing. */\n secure?: boolean;\n /** subdomainIndex for a freshly built `_fbc` (com=0, example.com=1, www.example.com=2). Default 1. */\n subdomainIndex?: number;\n /**\n * Re-issue the stored click and browser ids on every request as an ITP self-heal: the pixels\n * rewrite them through `document.cookie`, which Safari caps at 7 days (24 hours on an\n * ad-decorated landing), and the re-issue restores the long-lived HTTP cookie. On by default.\n * Note it attaches a per-user `Set-Cookie` — and thus `no-store` — to every page response of a\n * visitor carrying one; set false to keep those pages CDN-cacheable. See\n * {@link resolveClickIdCookies}.\n */\n refresh?: boolean;\n /**\n * The `Cache-Control` for a response we attach cookies to when it could otherwise be stored by a\n * shared cache (default `private, no-store`): a per-user `Set-Cookie` must never end up on a\n * shared-cache entry, or one visitor's `_fbc` would be served to everyone. A response already\n * `private` or `no-store` keeps its own. Only set this false if you guarantee these responses\n * are never cached.\n */\n cacheControl?: string | false;\n /**\n * Consent gate. Return false to skip setting cookies for this request (e.g. before the visitor has\n * granted consent where required). Runs per request with the incoming `Request`.\n */\n shouldPersist?: (request: Request) => boolean;\n}\n\n/**\n * Whether a response could be stored by a shared cache (a CDN) under its `Cache-Control`. One\n * that is `private` or `no-store` already cannot, so a per-user `Set-Cookie` on it is safe as it\n * is, and its own caching is kept — the gtag.js loader served through a first-party Google Tag\n * Gateway (`private, max-age=…`) stays in the browser cache, where a browser never replays a\n * `Set-Cookie`. Anything else — `public`, `s-maxage`, no header at all — might be shared, and is\n * made uncacheable.\n */\nfunction sharedCacheable(value: string | null): boolean {\n if (!value) return true;\n const directives = value\n .toLowerCase()\n .split(',')\n .map((directive) => directive.trim());\n return !directives.some(\n (directive) =>\n directive === 'private' || directive.startsWith('private=') || directive === 'no-store'\n );\n}\n\n/**\n * TanStack Start request middleware that persists the ad platforms' first-party cookies on the\n * document response: `_fbc`, `_fbp`, `_gcl_aw` / `_gcl_gb`, `_rdt_cid`, `_rdt_uuid`,\n * `_uetmsclkid`, `__oppref` and `__obref`.\n *\n * Setting `_fbc` here — on the top document via an HTTP `Set-Cookie` header, before any client JS\n * runs — is what Meta officially recommends and the only reliable way to keep the cookie alive for\n * 90 days in Safari: ITP caps JavaScript-set cookies on a fbclid-decorated landing page to 24\n * hours, and a document response is never classified as CNAME/IP cloaking (it is the reference the\n * browser measures cloaking against).\n *\n * Register it as a global request middleware:\n * ```ts\n * // start.ts\n * import { createStart } from '@tanstack/react-start'\n * import { createClickIdMiddleware } from '@shware/analytics/tanstack'\n * const clickIdMiddleware = createClickIdMiddleware({\n * domain: import.meta.env.DEV ? null : '.example.com',\n * secure: !import.meta.env.DEV,\n * })\n * export const startInstance = createStart(() => ({ requestMiddleware: [clickIdMiddleware] }))\n * ```\n *\n * reference: https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/fbp-and-fbc\n */\nexport function createClickIdMiddleware(options: ClickIdMiddlewareOptions) {\n const { cacheControl = 'private, no-store' } = options;\n\n return createMiddleware({ type: 'request' }).server(async ({ request, next, handlerType }) => {\n const result = await next();\n\n // Skip serverFn RPC responses. 'router' covers SSR document requests *and* custom server\n // routes (API endpoints) — those also get cookies when the URL carries a click id.\n if (handlerType !== 'router') return result;\n if (options.shouldPersist && !options.shouldPersist(request)) return result;\n\n const { cookies } = resolveClickIdCookies({\n url: request.url,\n cookieHeader: request.headers.get('cookie'),\n domain: options.domain,\n secure: options.secure,\n subdomainIndex: options.subdomainIndex,\n refresh: options.refresh ?? true,\n });\n\n if (cookies.length > 0) {\n for (const header of toSetCookieHeaders(cookies)) {\n result.response.headers.append('set-cookie', header);\n }\n if (cacheControl !== false && sharedCacheable(result.response.headers.get('cache-control'))) {\n result.response.headers.set('cache-control', cacheControl);\n }\n }\n\n return result;\n });\n}\n"],"mappings":";;;;;;;;;;;;AA8CA,SAAS,gBAAgB,OAA+B;CACtD,IAAI,CAAC,OAAO,OAAO;CAKnB,OAAO,CAJY,MAChB,YAAY,CAAC,CACb,MAAM,GAAG,CAAC,CACV,KAAK,cAAc,UAAU,KAAK,CACpB,CAAC,CAAC,MAChB,cACC,cAAc,aAAa,UAAU,WAAW,UAAU,KAAK,cAAc,UACjF;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA,SAAgB,wBAAwB,SAAmC;CACzE,MAAM,EAAE,eAAe,wBAAwB;CAE/C,QAAA,GAAOA,sBAAAA,iBAAAA,CAAiB,EAAE,MAAM,UAAU,CAAC,CAAC,CAAC,OAAO,OAAO,EAAE,SAAS,MAAM,kBAAkB;EAC5F,MAAM,SAAS,MAAM,KAAK;EAI1B,IAAI,gBAAgB,UAAU,OAAO;EACrC,IAAI,QAAQ,iBAAiB,CAAC,QAAQ,cAAc,OAAO,GAAG,OAAO;EAErE,MAAM,EAAE,YAAYC,uBAAAA,sBAAsB;GACxC,KAAK,QAAQ;GACb,cAAc,QAAQ,QAAQ,IAAI,QAAQ;GAC1C,QAAQ,QAAQ;GAChB,QAAQ,QAAQ;GAChB,gBAAgB,QAAQ;GACxB,SAAS,QAAQ,WAAW;EAC9B,CAAC;EAED,IAAI,QAAQ,SAAS,GAAG;GACtB,KAAK,MAAM,UAAUC,uBAAAA,mBAAmB,OAAO,GAC7C,OAAO,SAAS,QAAQ,OAAO,cAAc,MAAM;GAErD,IAAI,iBAAiB,SAAS,gBAAgB,OAAO,SAAS,QAAQ,IAAI,eAAe,CAAC,GACxF,OAAO,SAAS,QAAQ,IAAI,iBAAiB,YAAY;EAE7D;EAEA,OAAO;CACT,CAAC;AACH"}
|
|
@@ -20,9 +20,11 @@ export interface ClickIdMiddlewareOptions {
|
|
|
20
20
|
*/
|
|
21
21
|
refresh?: boolean;
|
|
22
22
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
23
|
+
* The `Cache-Control` for a response we attach cookies to when it could otherwise be stored by a
|
|
24
|
+
* shared cache (default `private, no-store`): a per-user `Set-Cookie` must never end up on a
|
|
25
|
+
* shared-cache entry, or one visitor's `_fbc` would be served to everyone. A response already
|
|
26
|
+
* `private` or `no-store` keeps its own. Only set this false if you guarantee these responses
|
|
27
|
+
* are never cached.
|
|
26
28
|
*/
|
|
27
29
|
cacheControl?: string | false;
|
|
28
30
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.d.cts","names":[],"sources":["../../src/tanstack/middleware.ts"],"mappings":";iBAGiB;;;;;;EAMf;;EAEA;;EAEA;;;;;;;;;EASA
|
|
1
|
+
{"version":3,"file":"middleware.d.cts","names":[],"sources":["../../src/tanstack/middleware.ts"],"mappings":";iBAGiB;;;;;;EAMf;;EAEA;;EAEA;;;;;;;;;EASA;;;;;;;;EAQA;;;;;EAKA,iBAAiB,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;wBAgDZ,wBAAwB,SAAS,2DAAwB"}
|
|
@@ -20,9 +20,11 @@ export interface ClickIdMiddlewareOptions {
|
|
|
20
20
|
*/
|
|
21
21
|
refresh?: boolean;
|
|
22
22
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
23
|
+
* The `Cache-Control` for a response we attach cookies to when it could otherwise be stored by a
|
|
24
|
+
* shared cache (default `private, no-store`): a per-user `Set-Cookie` must never end up on a
|
|
25
|
+
* shared-cache entry, or one visitor's `_fbc` would be served to everyone. A response already
|
|
26
|
+
* `private` or `no-store` keeps its own. Only set this false if you guarantee these responses
|
|
27
|
+
* are never cached.
|
|
26
28
|
*/
|
|
27
29
|
cacheControl?: string | false;
|
|
28
30
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.d.mts","names":[],"sources":["../../src/tanstack/middleware.ts"],"mappings":";iBAGiB;;;;;;EAMf;;EAEA;;EAEA;;;;;;;;;EASA
|
|
1
|
+
{"version":3,"file":"middleware.d.mts","names":[],"sources":["../../src/tanstack/middleware.ts"],"mappings":";iBAGiB;;;;;;EAMf;;EAEA;;EAEA;;;;;;;;;EASA;;;;;;;;EAQA;;;;;EAKA,iBAAiB,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;wBAgDZ,wBAAwB,SAAS,2DAAwB"}
|
|
@@ -2,6 +2,18 @@ import { resolveClickIdCookies, toSetCookieHeaders } from "../click-id/index.mjs
|
|
|
2
2
|
import { createMiddleware } from "@tanstack/react-start";
|
|
3
3
|
//#region src/tanstack/middleware.ts
|
|
4
4
|
/**
|
|
5
|
+
* Whether a response could be stored by a shared cache (a CDN) under its `Cache-Control`. One
|
|
6
|
+
* that is `private` or `no-store` already cannot, so a per-user `Set-Cookie` on it is safe as it
|
|
7
|
+
* is, and its own caching is kept — the gtag.js loader served through a first-party Google Tag
|
|
8
|
+
* Gateway (`private, max-age=…`) stays in the browser cache, where a browser never replays a
|
|
9
|
+
* `Set-Cookie`. Anything else — `public`, `s-maxage`, no header at all — might be shared, and is
|
|
10
|
+
* made uncacheable.
|
|
11
|
+
*/
|
|
12
|
+
function sharedCacheable(value) {
|
|
13
|
+
if (!value) return true;
|
|
14
|
+
return !value.toLowerCase().split(",").map((directive) => directive.trim()).some((directive) => directive === "private" || directive.startsWith("private=") || directive === "no-store");
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
5
17
|
* TanStack Start request middleware that persists the ad platforms' first-party cookies on the
|
|
6
18
|
* document response: `_fbc`, `_fbp`, `_gcl_aw` / `_gcl_gb`, `_rdt_cid`, `_rdt_uuid`,
|
|
7
19
|
* `_uetmsclkid`, `__oppref` and `__obref`.
|
|
@@ -42,7 +54,7 @@ function createClickIdMiddleware(options) {
|
|
|
42
54
|
});
|
|
43
55
|
if (cookies.length > 0) {
|
|
44
56
|
for (const header of toSetCookieHeaders(cookies)) result.response.headers.append("set-cookie", header);
|
|
45
|
-
if (cacheControl !== false) result.response.headers.set("cache-control", cacheControl);
|
|
57
|
+
if (cacheControl !== false && sharedCacheable(result.response.headers.get("cache-control"))) result.response.headers.set("cache-control", cacheControl);
|
|
46
58
|
}
|
|
47
59
|
return result;
|
|
48
60
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.mjs","names":[],"sources":["../../src/tanstack/middleware.ts"],"sourcesContent":["import { createMiddleware } from '@tanstack/react-start';\nimport { resolveClickIdCookies, toSetCookieHeaders } from '../click-id/index';\n\nexport interface ClickIdMiddlewareOptions {\n /**\n * `Domain` attribute for the cookies: the site's registrable domain, e.g. `.shware.io`, where the\n * pixels write theirs. Required — set it in production; `null` (host-only) is for `localhost`.\n * See `ResolveClickIdCookiesInput.domain`.\n */\n domain: string | null;\n /** `Secure` attribute, default true. Set false only for local http testing. */\n secure?: boolean;\n /** subdomainIndex for a freshly built `_fbc` (com=0, example.com=1, www.example.com=2). Default 1. */\n subdomainIndex?: number;\n /**\n * Re-issue the stored click and browser ids on every request as an ITP self-heal: the pixels\n * rewrite them through `document.cookie`, which Safari caps at 7 days (24 hours on an\n * ad-decorated landing), and the re-issue restores the long-lived HTTP cookie. On by default.\n * Note it attaches a per-user `Set-Cookie` — and thus `no-store` — to every page response of a\n * visitor carrying one; set false to keep those pages CDN-cacheable. See\n * {@link resolveClickIdCookies}.\n */\n refresh?: boolean;\n /**\n *
|
|
1
|
+
{"version":3,"file":"middleware.mjs","names":[],"sources":["../../src/tanstack/middleware.ts"],"sourcesContent":["import { createMiddleware } from '@tanstack/react-start';\nimport { resolveClickIdCookies, toSetCookieHeaders } from '../click-id/index';\n\nexport interface ClickIdMiddlewareOptions {\n /**\n * `Domain` attribute for the cookies: the site's registrable domain, e.g. `.shware.io`, where the\n * pixels write theirs. Required — set it in production; `null` (host-only) is for `localhost`.\n * See `ResolveClickIdCookiesInput.domain`.\n */\n domain: string | null;\n /** `Secure` attribute, default true. Set false only for local http testing. */\n secure?: boolean;\n /** subdomainIndex for a freshly built `_fbc` (com=0, example.com=1, www.example.com=2). Default 1. */\n subdomainIndex?: number;\n /**\n * Re-issue the stored click and browser ids on every request as an ITP self-heal: the pixels\n * rewrite them through `document.cookie`, which Safari caps at 7 days (24 hours on an\n * ad-decorated landing), and the re-issue restores the long-lived HTTP cookie. On by default.\n * Note it attaches a per-user `Set-Cookie` — and thus `no-store` — to every page response of a\n * visitor carrying one; set false to keep those pages CDN-cacheable. See\n * {@link resolveClickIdCookies}.\n */\n refresh?: boolean;\n /**\n * The `Cache-Control` for a response we attach cookies to when it could otherwise be stored by a\n * shared cache (default `private, no-store`): a per-user `Set-Cookie` must never end up on a\n * shared-cache entry, or one visitor's `_fbc` would be served to everyone. A response already\n * `private` or `no-store` keeps its own. Only set this false if you guarantee these responses\n * are never cached.\n */\n cacheControl?: string | false;\n /**\n * Consent gate. Return false to skip setting cookies for this request (e.g. before the visitor has\n * granted consent where required). Runs per request with the incoming `Request`.\n */\n shouldPersist?: (request: Request) => boolean;\n}\n\n/**\n * Whether a response could be stored by a shared cache (a CDN) under its `Cache-Control`. One\n * that is `private` or `no-store` already cannot, so a per-user `Set-Cookie` on it is safe as it\n * is, and its own caching is kept — the gtag.js loader served through a first-party Google Tag\n * Gateway (`private, max-age=…`) stays in the browser cache, where a browser never replays a\n * `Set-Cookie`. Anything else — `public`, `s-maxage`, no header at all — might be shared, and is\n * made uncacheable.\n */\nfunction sharedCacheable(value: string | null): boolean {\n if (!value) return true;\n const directives = value\n .toLowerCase()\n .split(',')\n .map((directive) => directive.trim());\n return !directives.some(\n (directive) =>\n directive === 'private' || directive.startsWith('private=') || directive === 'no-store'\n );\n}\n\n/**\n * TanStack Start request middleware that persists the ad platforms' first-party cookies on the\n * document response: `_fbc`, `_fbp`, `_gcl_aw` / `_gcl_gb`, `_rdt_cid`, `_rdt_uuid`,\n * `_uetmsclkid`, `__oppref` and `__obref`.\n *\n * Setting `_fbc` here — on the top document via an HTTP `Set-Cookie` header, before any client JS\n * runs — is what Meta officially recommends and the only reliable way to keep the cookie alive for\n * 90 days in Safari: ITP caps JavaScript-set cookies on a fbclid-decorated landing page to 24\n * hours, and a document response is never classified as CNAME/IP cloaking (it is the reference the\n * browser measures cloaking against).\n *\n * Register it as a global request middleware:\n * ```ts\n * // start.ts\n * import { createStart } from '@tanstack/react-start'\n * import { createClickIdMiddleware } from '@shware/analytics/tanstack'\n * const clickIdMiddleware = createClickIdMiddleware({\n * domain: import.meta.env.DEV ? null : '.example.com',\n * secure: !import.meta.env.DEV,\n * })\n * export const startInstance = createStart(() => ({ requestMiddleware: [clickIdMiddleware] }))\n * ```\n *\n * reference: https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/fbp-and-fbc\n */\nexport function createClickIdMiddleware(options: ClickIdMiddlewareOptions) {\n const { cacheControl = 'private, no-store' } = options;\n\n return createMiddleware({ type: 'request' }).server(async ({ request, next, handlerType }) => {\n const result = await next();\n\n // Skip serverFn RPC responses. 'router' covers SSR document requests *and* custom server\n // routes (API endpoints) — those also get cookies when the URL carries a click id.\n if (handlerType !== 'router') return result;\n if (options.shouldPersist && !options.shouldPersist(request)) return result;\n\n const { cookies } = resolveClickIdCookies({\n url: request.url,\n cookieHeader: request.headers.get('cookie'),\n domain: options.domain,\n secure: options.secure,\n subdomainIndex: options.subdomainIndex,\n refresh: options.refresh ?? true,\n });\n\n if (cookies.length > 0) {\n for (const header of toSetCookieHeaders(cookies)) {\n result.response.headers.append('set-cookie', header);\n }\n if (cacheControl !== false && sharedCacheable(result.response.headers.get('cache-control'))) {\n result.response.headers.set('cache-control', cacheControl);\n }\n }\n\n return result;\n });\n}\n"],"mappings":";;;;;;;;;;;AA8CA,SAAS,gBAAgB,OAA+B;CACtD,IAAI,CAAC,OAAO,OAAO;CAKnB,OAAO,CAJY,MAChB,YAAY,CAAC,CACb,MAAM,GAAG,CAAC,CACV,KAAK,cAAc,UAAU,KAAK,CACpB,CAAC,CAAC,MAChB,cACC,cAAc,aAAa,UAAU,WAAW,UAAU,KAAK,cAAc,UACjF;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA,SAAgB,wBAAwB,SAAmC;CACzE,MAAM,EAAE,eAAe,wBAAwB;CAE/C,OAAO,iBAAiB,EAAE,MAAM,UAAU,CAAC,CAAC,CAAC,OAAO,OAAO,EAAE,SAAS,MAAM,kBAAkB;EAC5F,MAAM,SAAS,MAAM,KAAK;EAI1B,IAAI,gBAAgB,UAAU,OAAO;EACrC,IAAI,QAAQ,iBAAiB,CAAC,QAAQ,cAAc,OAAO,GAAG,OAAO;EAErE,MAAM,EAAE,YAAY,sBAAsB;GACxC,KAAK,QAAQ;GACb,cAAc,QAAQ,QAAQ,IAAI,QAAQ;GAC1C,QAAQ,QAAQ;GAChB,QAAQ,QAAQ;GAChB,gBAAgB,QAAQ;GACxB,SAAS,QAAQ,WAAW;EAC9B,CAAC;EAED,IAAI,QAAQ,SAAS,GAAG;GACtB,KAAK,MAAM,UAAU,mBAAmB,OAAO,GAC7C,OAAO,SAAS,QAAQ,OAAO,cAAc,MAAM;GAErD,IAAI,iBAAiB,SAAS,gBAAgB,OAAO,SAAS,QAAQ,IAAI,eAAe,CAAC,GACxF,OAAO,SAAS,QAAQ,IAAI,iBAAiB,YAAY;EAE7D;EAEA,OAAO;CACT,CAAC;AACH"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { UETConsent, UETEventParams, UETItem, UETPageType, UETPid } from "../track/uetq.cjs";
|
|
1
2
|
import { sendGAEvent, setGAUser } from "./google-analytics.cjs";
|
|
2
3
|
import { sendFBEvent, setFBUser } from "./meta-pixel.cjs";
|
|
3
4
|
import { LinkedinConversionConfig, sendLinkedinEvent, setLinkedinUser } from "./linkedin-insight-tag.cjs";
|
|
4
5
|
import { sendOpenAIEvent, setOpenAIUser } from "./openai-pixel.cjs";
|
|
5
6
|
import { sendRedditEvent, setRedditUser } from "./reddit-pixel.cjs";
|
|
6
|
-
import { UETConsent, UETEventParams, UETItem, UETPageType, UETPid } from "../track/uetq.cjs";
|
|
7
7
|
import { configureUET, sendUETEvent, sendUETIdSync, setUETConsent, setUETUser, syncUETVisitor } from "./microsoft-uet.cjs";
|
|
8
8
|
export { type LinkedinConversionConfig, type UETConsent, type UETEventParams, type UETItem, type UETPageType, type UETPid, configureUET, sendFBEvent, sendGAEvent, sendLinkedinEvent, sendOpenAIEvent, sendRedditEvent, sendUETEvent, sendUETIdSync, setFBUser, setGAUser, setLinkedinUser, setOpenAIUser, setRedditUser, setUETConsent, setUETUser, syncUETVisitor };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { UETConsent, UETEventParams, UETItem, UETPageType, UETPid } from "../track/uetq.mjs";
|
|
1
2
|
import { sendGAEvent, setGAUser } from "./google-analytics.mjs";
|
|
2
3
|
import { sendFBEvent, setFBUser } from "./meta-pixel.mjs";
|
|
3
4
|
import { LinkedinConversionConfig, sendLinkedinEvent, setLinkedinUser } from "./linkedin-insight-tag.mjs";
|
|
4
5
|
import { sendOpenAIEvent, setOpenAIUser } from "./openai-pixel.mjs";
|
|
5
6
|
import { sendRedditEvent, setRedditUser } from "./reddit-pixel.mjs";
|
|
6
|
-
import { UETConsent, UETEventParams, UETItem, UETPageType, UETPid } from "../track/uetq.mjs";
|
|
7
7
|
import { configureUET, sendUETEvent, sendUETIdSync, setUETConsent, setUETUser, syncUETVisitor } from "./microsoft-uet.mjs";
|
|
8
8
|
export { type LinkedinConversionConfig, type UETConsent, type UETEventParams, type UETItem, type UETPageType, type UETPid, configureUET, sendFBEvent, sendGAEvent, sendLinkedinEvent, sendOpenAIEvent, sendRedditEvent, sendUETEvent, sendUETIdSync, setFBUser, setGAUser, setLinkedinUser, setOpenAIUser, setRedditUser, setUETConsent, setUETUser, syncUETVisitor };
|