@shware/analytics 8.3.0 → 8.6.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/README.md +28 -16
- package/dist/hooks/use-uet-id-sync.cjs +19 -0
- package/dist/hooks/use-uet-id-sync.cjs.map +1 -0
- package/dist/hooks/use-uet-id-sync.d.cts +10 -0
- package/dist/hooks/use-uet-id-sync.d.cts.map +1 -0
- package/dist/hooks/use-uet-id-sync.d.mts +10 -0
- package/dist/hooks/use-uet-id-sync.d.mts.map +1 -0
- package/dist/hooks/use-uet-id-sync.mjs +18 -0
- package/dist/hooks/use-uet-id-sync.mjs.map +1 -0
- package/dist/hooks/use-web-analytics.cjs +11 -5
- package/dist/hooks/use-web-analytics.cjs.map +1 -1
- package/dist/hooks/use-web-analytics.d.cts +4 -1
- package/dist/hooks/use-web-analytics.d.cts.map +1 -1
- package/dist/hooks/use-web-analytics.d.mts +4 -1
- package/dist/hooks/use-web-analytics.d.mts.map +1 -1
- package/dist/hooks/use-web-analytics.mjs +11 -5
- package/dist/hooks/use-web-analytics.mjs.map +1 -1
- package/dist/next/index.cjs +40 -2
- package/dist/next/index.cjs.map +1 -1
- package/dist/next/index.d.cts +5 -1
- package/dist/next/index.d.cts.map +1 -1
- package/dist/next/index.d.mts +5 -1
- package/dist/next/index.d.mts.map +1 -1
- package/dist/next/index.mjs +41 -3
- package/dist/next/index.mjs.map +1 -1
- package/dist/react-router/index.cjs +27 -3
- package/dist/react-router/index.cjs.map +1 -1
- package/dist/react-router/index.d.cts +5 -1
- package/dist/react-router/index.d.cts.map +1 -1
- package/dist/react-router/index.d.mts +5 -1
- package/dist/react-router/index.d.mts.map +1 -1
- package/dist/react-router/index.mjs +27 -3
- package/dist/react-router/index.mjs.map +1 -1
- package/dist/schema/index.cjs +1 -0
- package/dist/schema/index.cjs.map +1 -1
- package/dist/schema/index.d.cts +4 -0
- package/dist/schema/index.d.cts.map +1 -1
- package/dist/schema/index.d.mts +4 -0
- package/dist/schema/index.d.mts.map +1 -1
- package/dist/schema/index.mjs +1 -0
- package/dist/schema/index.mjs.map +1 -1
- package/dist/server/index.d.cts +2 -2
- package/dist/server/index.d.mts +2 -2
- package/dist/server/microsoft-conversions-api.cjs +8 -8
- package/dist/server/microsoft-conversions-api.cjs.map +1 -1
- package/dist/server/microsoft-conversions-api.d.cts +15 -8
- package/dist/server/microsoft-conversions-api.d.cts.map +1 -1
- package/dist/server/microsoft-conversions-api.d.mts +15 -8
- package/dist/server/microsoft-conversions-api.d.mts.map +1 -1
- package/dist/server/microsoft-conversions-api.mjs +8 -8
- package/dist/server/microsoft-conversions-api.mjs.map +1 -1
- package/dist/server/openai-conversions-api.cjs +1 -1
- package/dist/server/openai-conversions-api.mjs +1 -1
- package/dist/server/reddit-conversions-api.cjs +1 -1
- package/dist/server/reddit-conversions-api.mjs +1 -1
- package/dist/tanstack/analytics.cjs +27 -3
- package/dist/tanstack/analytics.cjs.map +1 -1
- package/dist/tanstack/analytics.d.cts +5 -1
- package/dist/tanstack/analytics.d.cts.map +1 -1
- package/dist/tanstack/analytics.d.mts +5 -1
- package/dist/tanstack/analytics.d.mts.map +1 -1
- package/dist/tanstack/analytics.mjs +27 -3
- package/dist/tanstack/analytics.mjs.map +1 -1
- package/dist/third-parties/index.cjs +3 -1
- package/dist/third-parties/index.d.cts +2 -2
- package/dist/third-parties/index.d.mts +2 -2
- package/dist/third-parties/index.mjs +2 -2
- package/dist/third-parties/meta-pixel.cjs +1 -1
- package/dist/third-parties/meta-pixel.mjs +1 -1
- package/dist/third-parties/microsoft-uet.cjs +45 -17
- package/dist/third-parties/microsoft-uet.cjs.map +1 -1
- package/dist/third-parties/microsoft-uet.d.cts +13 -19
- package/dist/third-parties/microsoft-uet.d.cts.map +1 -1
- package/dist/third-parties/microsoft-uet.d.mts +13 -19
- package/dist/third-parties/microsoft-uet.d.mts.map +1 -1
- package/dist/third-parties/microsoft-uet.mjs +44 -18
- package/dist/third-parties/microsoft-uet.mjs.map +1 -1
- package/dist/third-parties/openai-pixel.cjs +1 -1
- package/dist/third-parties/openai-pixel.mjs +1 -1
- package/dist/third-parties/reddit-pixel.cjs +1 -1
- package/dist/third-parties/reddit-pixel.mjs +1 -1
- package/dist/track/types.d.cts +7 -0
- package/dist/track/types.d.cts.map +1 -1
- package/dist/track/types.d.mts +7 -0
- package/dist/track/types.d.mts.map +1 -1
- package/dist/web/index.cjs +25 -1
- package/dist/web/index.cjs.map +1 -1
- package/dist/web/index.d.cts.map +1 -1
- package/dist/web/index.d.mts.map +1 -1
- package/dist/web/index.mjs +25 -1
- package/dist/web/index.mjs.map +1 -1
- package/dist/web/page-key.cjs +53 -0
- package/dist/web/page-key.cjs.map +1 -0
- package/dist/web/page-key.d.cts +24 -0
- package/dist/web/page-key.d.cts.map +1 -0
- package/dist/web/page-key.d.mts +24 -0
- package/dist/web/page-key.d.mts.map +1 -0
- package/dist/web/page-key.mjs +52 -0
- package/dist/web/page-key.mjs.map +1 -0
- package/package.json +1 -1
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import { track } from "../track/index.mjs";
|
|
2
2
|
import { useOutboundClickAnalytics } from "../hooks/use-outbound-click-analytics.mjs";
|
|
3
3
|
import { useReportWebVitals } from "../hooks/use-report-web-vitals.mjs";
|
|
4
|
+
import { useUETIdSync } from "../hooks/use-uet-id-sync.mjs";
|
|
4
5
|
import { useWebAnalytics } from "../hooks/use-web-analytics.mjs";
|
|
5
6
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
7
|
import { useLocation } from "@tanstack/react-router";
|
|
7
8
|
//#region src/tanstack/analytics.tsx
|
|
8
|
-
function Analytics({ gaId, gaSrc, nonce, debugMode, metaPixelId, openaiPixelId, redditPixelId, linkedInPartnerId, hotjarId, facebookAppId, reportWebVitals = true }) {
|
|
9
|
-
const { pathname } = useLocation();
|
|
10
|
-
useWebAnalytics(pathname);
|
|
9
|
+
function Analytics({ gaId, gaSrc, nonce, debugMode, metaPixelId, openaiPixelId, redditPixelId, linkedInPartnerId, uetTagId, uetCustomerId, hotjarId, facebookAppId, reportWebVitals = true }) {
|
|
10
|
+
const { pathname, searchStr } = useLocation();
|
|
11
|
+
useWebAnalytics(pathname, searchStr);
|
|
11
12
|
useOutboundClickAnalytics();
|
|
13
|
+
useUETIdSync(uetCustomerId);
|
|
12
14
|
useReportWebVitals((metric) => {
|
|
13
15
|
if (!reportWebVitals) return;
|
|
14
16
|
const properties = {
|
|
@@ -129,6 +131,28 @@ function Analytics({ gaId, gaSrc, nonce, debugMode, metaPixelId, openaiPixelId,
|
|
|
129
131
|
b.src = "https://snap.licdn.com/li.lms-analytics/insight.min.js";
|
|
130
132
|
s.parentNode.insertBefore(b, s);
|
|
131
133
|
})(window.lintrk);
|
|
134
|
+
` }
|
|
135
|
+
}),
|
|
136
|
+
uetTagId && /* @__PURE__ */ jsx("script", {
|
|
137
|
+
async: true,
|
|
138
|
+
id: "uet-tag",
|
|
139
|
+
dangerouslySetInnerHTML: { __html: `
|
|
140
|
+
(function (w, d, t, u, o) {
|
|
141
|
+
w[u] = w[u] || [], o.ts = (new Date).getTime();
|
|
142
|
+
var n = d.createElement(t);
|
|
143
|
+
n.src = "https://bat.bing.net/bat.js?ti=" + o.ti + ("uetq" != u ? "&q=" + u : ""),
|
|
144
|
+
n.async = 1, n.onload = n.onreadystatechange = function() {
|
|
145
|
+
var s = this.readyState;
|
|
146
|
+
s && "loaded" !== s && "complete" !== s ||
|
|
147
|
+
(o.q = w[u], w[u] = new UET(o), w[u].push("pageLoad"),
|
|
148
|
+
n.onload = n.onreadystatechange = null)
|
|
149
|
+
};
|
|
150
|
+
var i = d.getElementsByTagName(t)[0];
|
|
151
|
+
i.parentNode.insertBefore(n, i);
|
|
152
|
+
})(window, document, "script", "uetq", {
|
|
153
|
+
ti: "${uetTagId}",
|
|
154
|
+
enableAutoSpaTracking: true
|
|
155
|
+
});
|
|
132
156
|
` }
|
|
133
157
|
}),
|
|
134
158
|
hotjarId && /* @__PURE__ */ jsx("script", {
|
|
@@ -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 { 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 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 hotjarId,\n facebookAppId,\n reportWebVitals = true,\n}: Props) {\n const { pathname } = useLocation();\n useWebAnalytics(pathname);\n useOutboundClickAnalytics();\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 {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":"
|
|
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,10 +1,11 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_third_parties_microsoft_uet = require("./microsoft-uet.cjs");
|
|
2
3
|
const require_third_parties_google_analytics = require("./google-analytics.cjs");
|
|
3
4
|
const require_third_parties_meta_pixel = require("./meta-pixel.cjs");
|
|
4
5
|
const require_third_parties_linkedin_insight_tag = require("./linkedin-insight-tag.cjs");
|
|
5
6
|
const require_third_parties_openai_pixel = require("./openai-pixel.cjs");
|
|
6
7
|
const require_third_parties_reddit_pixel = require("./reddit-pixel.cjs");
|
|
7
|
-
|
|
8
|
+
exports.configureUET = require_third_parties_microsoft_uet.configureUET;
|
|
8
9
|
exports.sendFBEvent = require_third_parties_meta_pixel.sendFBEvent;
|
|
9
10
|
exports.sendGAEvent = require_third_parties_google_analytics.sendGAEvent;
|
|
10
11
|
exports.sendLinkedinEvent = require_third_parties_linkedin_insight_tag.sendLinkedinEvent;
|
|
@@ -19,3 +20,4 @@ exports.setOpenAIUser = require_third_parties_openai_pixel.setOpenAIUser;
|
|
|
19
20
|
exports.setRedditUser = require_third_parties_reddit_pixel.setRedditUser;
|
|
20
21
|
exports.setUETConsent = require_third_parties_microsoft_uet.setUETConsent;
|
|
21
22
|
exports.setUETUser = require_third_parties_microsoft_uet.setUETUser;
|
|
23
|
+
exports.syncUETVisitor = require_third_parties_microsoft_uet.syncUETVisitor;
|
|
@@ -4,5 +4,5 @@ import { LinkedinConversionConfig, sendLinkedinEvent, setLinkedinUser } from "./
|
|
|
4
4
|
import { sendOpenAIEvent, setOpenAIUser } from "./openai-pixel.cjs";
|
|
5
5
|
import { sendRedditEvent, setRedditUser } from "./reddit-pixel.cjs";
|
|
6
6
|
import { UETConsent, UETEventParams, UETItem, UETPageType, UETPid } from "../track/uetq.cjs";
|
|
7
|
-
import { sendUETEvent, sendUETIdSync, setUETConsent, setUETUser } from "./microsoft-uet.cjs";
|
|
8
|
-
export { type LinkedinConversionConfig, type UETConsent, type UETEventParams, type UETItem, type UETPageType, type UETPid, sendFBEvent, sendGAEvent, sendLinkedinEvent, sendOpenAIEvent, sendRedditEvent, sendUETEvent, sendUETIdSync, setFBUser, setGAUser, setLinkedinUser, setOpenAIUser, setRedditUser, setUETConsent, setUETUser };
|
|
7
|
+
import { configureUET, sendUETEvent, sendUETIdSync, setUETConsent, setUETUser, syncUETVisitor } from "./microsoft-uet.cjs";
|
|
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 };
|
|
@@ -4,5 +4,5 @@ import { LinkedinConversionConfig, sendLinkedinEvent, setLinkedinUser } from "./
|
|
|
4
4
|
import { sendOpenAIEvent, setOpenAIUser } from "./openai-pixel.mjs";
|
|
5
5
|
import { sendRedditEvent, setRedditUser } from "./reddit-pixel.mjs";
|
|
6
6
|
import { UETConsent, UETEventParams, UETItem, UETPageType, UETPid } from "../track/uetq.mjs";
|
|
7
|
-
import { sendUETEvent, sendUETIdSync, setUETConsent, setUETUser } from "./microsoft-uet.mjs";
|
|
8
|
-
export { type LinkedinConversionConfig, type UETConsent, type UETEventParams, type UETItem, type UETPageType, type UETPid, sendFBEvent, sendGAEvent, sendLinkedinEvent, sendOpenAIEvent, sendRedditEvent, sendUETEvent, sendUETIdSync, setFBUser, setGAUser, setLinkedinUser, setOpenAIUser, setRedditUser, setUETConsent, setUETUser };
|
|
7
|
+
import { configureUET, sendUETEvent, sendUETIdSync, setUETConsent, setUETUser, syncUETVisitor } from "./microsoft-uet.mjs";
|
|
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,7 +1,7 @@
|
|
|
1
|
+
import { configureUET, sendUETEvent, sendUETIdSync, setUETConsent, setUETUser, syncUETVisitor } from "./microsoft-uet.mjs";
|
|
1
2
|
import { sendGAEvent, setGAUser } from "./google-analytics.mjs";
|
|
2
3
|
import { sendFBEvent, setFBUser } from "./meta-pixel.mjs";
|
|
3
4
|
import { 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
|
-
|
|
7
|
-
export { sendFBEvent, sendGAEvent, sendLinkedinEvent, sendOpenAIEvent, sendRedditEvent, sendUETEvent, sendUETIdSync, setFBUser, setGAUser, setLinkedinUser, setOpenAIUser, setRedditUser, setUETConsent, setUETUser };
|
|
7
|
+
export { configureUET, sendFBEvent, sendGAEvent, sendLinkedinEvent, sendOpenAIEvent, sendRedditEvent, sendUETEvent, sendUETIdSync, setFBUser, setGAUser, setLinkedinUser, setOpenAIUser, setRedditUser, setUETConsent, setUETUser, syncUETVisitor };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_track_fbq = require("../track/fbq.cjs");
|
|
3
2
|
const require_utils_field = require("../utils/field.cjs");
|
|
3
|
+
const require_track_fbq = require("../track/fbq.cjs");
|
|
4
4
|
//#region src/third-parties/meta-pixel.ts
|
|
5
5
|
const metrics = [
|
|
6
6
|
"CLS",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const
|
|
2
|
+
const require_visitor_index = require("../visitor/index.cjs");
|
|
3
3
|
const require_track_uetq = require("../track/uetq.cjs");
|
|
4
|
+
const require_utils_field = require("../utils/field.cjs");
|
|
4
5
|
const require_utils_sha256 = require("../utils/sha256.cjs");
|
|
5
6
|
//#region src/third-parties/microsoft-uet.ts
|
|
6
7
|
const metrics = [
|
|
@@ -47,23 +48,23 @@ function sendUETEvent(name, properties, eventId) {
|
|
|
47
48
|
* when the page load already went out. Values are sent raw — the tag normalizes and SHA-256
|
|
48
49
|
* hashes them in the browser (bat.js `validatePid`) before anything leaves the page.
|
|
49
50
|
*
|
|
50
|
-
*
|
|
51
|
-
* and `set` addresses whichever tag drains `uetq
|
|
51
|
+
* A setter itself, like `setGAUser`, rather than a factory like `setFBUser(pixelId)`: UET is
|
|
52
|
+
* bound to its tag by the snippet and `set` addresses whichever tag drains `uetq`, so there is
|
|
53
|
+
* nothing to bind first.
|
|
52
54
|
*/
|
|
53
|
-
function setUETUser() {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
};
|
|
55
|
+
function setUETUser({ user_id, user_data }) {
|
|
56
|
+
if (typeof window === "undefined" || !window.uetq) {
|
|
57
|
+
console.warn("uetq has not been initialized");
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (user_id) syncUETVisitor(user_id);
|
|
61
|
+
const em = require_utils_field.getFirst(user_data?.email);
|
|
62
|
+
const ph = require_utils_field.getFirst(user_data?.phone_number);
|
|
63
|
+
if (!em && !ph) return;
|
|
64
|
+
window.uetq.push("set", { pid: clean({
|
|
65
|
+
em,
|
|
66
|
+
ph
|
|
67
|
+
}) });
|
|
67
68
|
}
|
|
68
69
|
/**
|
|
69
70
|
* UET consent mode. Push `default` before the tag loads (the tag processes `consent` early, ahead
|
|
@@ -93,6 +94,31 @@ function setUETConsent(mode, consent) {
|
|
|
93
94
|
* the pixel goes out without `UID` rather than with a raw id.
|
|
94
95
|
* https://learn.microsoft.com/en-us/advertising/guides/uet-conversion-api-integration#id-sync-and-why-it-matters
|
|
95
96
|
*/
|
|
97
|
+
/**
|
|
98
|
+
* The Microsoft Advertising customer id the ID Sync pixel reports to, set once by the framework
|
|
99
|
+
* `Analytics` component's `uetCustomerId` prop (or `configureUET`). Unset, nothing syncs.
|
|
100
|
+
*/
|
|
101
|
+
let uetCustomerId;
|
|
102
|
+
function configureUET(options) {
|
|
103
|
+
uetCustomerId = options.customerId === void 0 ? void 0 : String(options.customerId);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Sync the SDK visitor — the `anonymousId` of the events the server sends to the Conversions
|
|
107
|
+
* API — with Microsoft, plus the user's `UID` when one is known. The `Analytics` components run
|
|
108
|
+
* it on mount so every visit syncs at least once, anonymous visitors included (they are who
|
|
109
|
+
* remarketing audiences are built from), and `setUETUser` runs it again on sign-in.
|
|
110
|
+
*/
|
|
111
|
+
async function syncUETVisitor(userId) {
|
|
112
|
+
if (!uetCustomerId) return;
|
|
113
|
+
try {
|
|
114
|
+
const { id } = await require_visitor_index.getVisitor();
|
|
115
|
+
sendUETIdSync({
|
|
116
|
+
customerId: uetCustomerId,
|
|
117
|
+
visitorId: id,
|
|
118
|
+
userId
|
|
119
|
+
});
|
|
120
|
+
} catch {}
|
|
121
|
+
}
|
|
96
122
|
function sendUETIdSync(options) {
|
|
97
123
|
if (typeof window === "undefined" || typeof Image === "undefined") return;
|
|
98
124
|
if (isLocal()) return;
|
|
@@ -111,9 +137,11 @@ function sendUETIdSync(options) {
|
|
|
111
137
|
require_utils_sha256.sha256(options.userId).then(fire, () => fire());
|
|
112
138
|
}
|
|
113
139
|
//#endregion
|
|
140
|
+
exports.configureUET = configureUET;
|
|
114
141
|
exports.sendUETEvent = sendUETEvent;
|
|
115
142
|
exports.sendUETIdSync = sendUETIdSync;
|
|
116
143
|
exports.setUETConsent = setUETConsent;
|
|
117
144
|
exports.setUETUser = setUETUser;
|
|
145
|
+
exports.syncUETVisitor = syncUETVisitor;
|
|
118
146
|
|
|
119
147
|
//# sourceMappingURL=microsoft-uet.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"microsoft-uet.cjs","names":["mapUETEvent","getFirst"],"sources":["../../src/third-parties/microsoft-uet.ts"],"sourcesContent":["import type { UpdateVisitorDTO } from '../schema/index';\nimport type { EventName, TrackName, TrackProperties } from '../track/types';\nimport { type UETConsent, type UETQ, mapUETEvent } from '../track/uetq';\nimport { getFirst } from '../utils/field';\nimport { sha256 } from '../utils/sha256';\n\ndeclare global {\n interface Window {\n /**\n * Defined by the UET snippet before `bat.js` loads (as a plain array), so pushes made early\n * are queued rather than lost. Undefined only where the snippet was never installed.\n */\n uetq?: UETQ;\n }\n}\n\nconst metrics = ['CLS', 'FCP', 'FID', 'INP', 'LCP', 'TTFB'];\n\n/** Drop `undefined` fields: bat.js validates every key it receives, and `undefined` is a value. */\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\nfunction clean(value: unknown): any {\n return JSON.parse(JSON.stringify(value));\n}\n\nfunction isLocal(): boolean {\n return window.location.host.includes('127.0.0.1') || window.location.host.includes('localhost');\n}\n\n/**\n * Forward an internal track event to the Microsoft Advertising UET tag.\n *\n * `eventId` is reused as UET's `event_id` so the browser event deduplicates against the same\n * conversion sent through the Conversions API (`sendMicrosoftEvents`). The action name is the\n * internal name on both channels — see `mapUETEvent`.\n *\n * `page_view` is not forwarded: bat.js turns that action into its page-load beacon, which the\n * snippet already fires on load and, with `enableAutoSpaTracking: true` (the setting in\n * Microsoft's generated snippet), on every history change — forwarding the SDK's own page views\n * would report each page twice. The tag owns page loads; this tracker owns everything else.\n */\nexport function sendUETEvent<T extends EventName>(\n name: TrackName<T>,\n properties?: TrackProperties<T>,\n eventId?: string\n) {\n if (typeof window === 'undefined' || !window.uetq) {\n console.warn('uetq has not been initialized');\n return;\n }\n if (metrics.includes(name) || name === 'page_view') return;\n if (isLocal()) return;\n\n const [action, params] = mapUETEvent(name, properties, eventId);\n window.uetq.push('event', action, clean(params));\n}\n\n/**\n * Enhanced conversions: hand the tag the visitor's email and phone so Microsoft can match a\n * conversion to an ad click without a third-party cookie. A `set` applies to every event fired\n * from the page afterwards, `pageLoad` included, and the tag fires a `pid` beacon on its own\n * when the page load already went out. Values are sent raw — the tag normalizes and SHA-256\n * hashes them in the browser (bat.js `validatePid`) before anything leaves the page.\n *\n *
|
|
1
|
+
{"version":3,"file":"microsoft-uet.cjs","names":["mapUETEvent","getFirst","getVisitor"],"sources":["../../src/third-parties/microsoft-uet.ts"],"sourcesContent":["import type { UpdateVisitorDTO } from '../schema/index';\nimport type { EventName, TrackName, TrackProperties } from '../track/types';\nimport { type UETConsent, type UETQ, mapUETEvent } from '../track/uetq';\nimport { getFirst } from '../utils/field';\nimport { sha256 } from '../utils/sha256';\nimport { getVisitor } from '../visitor/index';\n\ndeclare global {\n interface Window {\n /**\n * Defined by the UET snippet before `bat.js` loads (as a plain array), so pushes made early\n * are queued rather than lost. Undefined only where the snippet was never installed.\n */\n uetq?: UETQ;\n }\n}\n\nconst metrics = ['CLS', 'FCP', 'FID', 'INP', 'LCP', 'TTFB'];\n\n/** Drop `undefined` fields: bat.js validates every key it receives, and `undefined` is a value. */\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\nfunction clean(value: unknown): any {\n return JSON.parse(JSON.stringify(value));\n}\n\nfunction isLocal(): boolean {\n return window.location.host.includes('127.0.0.1') || window.location.host.includes('localhost');\n}\n\n/**\n * Forward an internal track event to the Microsoft Advertising UET tag.\n *\n * `eventId` is reused as UET's `event_id` so the browser event deduplicates against the same\n * conversion sent through the Conversions API (`sendMicrosoftEvents`). The action name is the\n * internal name on both channels — see `mapUETEvent`.\n *\n * `page_view` is not forwarded: bat.js turns that action into its page-load beacon, which the\n * snippet already fires on load and, with `enableAutoSpaTracking: true` (the setting in\n * Microsoft's generated snippet), on every history change — forwarding the SDK's own page views\n * would report each page twice. The tag owns page loads; this tracker owns everything else.\n */\nexport function sendUETEvent<T extends EventName>(\n name: TrackName<T>,\n properties?: TrackProperties<T>,\n eventId?: string\n) {\n if (typeof window === 'undefined' || !window.uetq) {\n console.warn('uetq has not been initialized');\n return;\n }\n if (metrics.includes(name) || name === 'page_view') return;\n if (isLocal()) return;\n\n const [action, params] = mapUETEvent(name, properties, eventId);\n window.uetq.push('event', action, clean(params));\n}\n\n/**\n * Enhanced conversions: hand the tag the visitor's email and phone so Microsoft can match a\n * conversion to an ad click without a third-party cookie. A `set` applies to every event fired\n * from the page afterwards, `pageLoad` included, and the tag fires a `pid` beacon on its own\n * when the page load already went out. Values are sent raw — the tag normalizes and SHA-256\n * hashes them in the browser (bat.js `validatePid`) before anything leaves the page.\n *\n * A setter itself, like `setGAUser`, rather than a factory like `setFBUser(pixelId)`: UET is\n * bound to its tag by the snippet and `set` addresses whichever tag drains `uetq`, so there is\n * nothing to bind first.\n */\nexport function setUETUser({ user_id, user_data }: UpdateVisitorDTO) {\n if (typeof window === 'undefined' || !window.uetq) {\n console.warn('uetq has not been initialized');\n return;\n }\n\n // A signed-in user is also the moment the ID Sync pixel can carry a `UID` — see `syncUETVisitor`.\n if (user_id) void syncUETVisitor(user_id);\n\n const em = getFirst(user_data?.email);\n const ph = getFirst(user_data?.phone_number);\n if (!em && !ph) return;\n\n window.uetq.push('set', { pid: clean({ em, ph }) });\n}\n\n/**\n * UET consent mode. Push `default` before the tag loads (the tag processes `consent` early, ahead\n * of the queued events) and `update` when the visitor decides. With `ad_storage: 'denied'` the\n * tag neither writes its cookies nor reads the `msclkid` from the URL.\n * https://help.ads.microsoft.com/#apex/ads/en/60119/1\n */\nexport function setUETConsent(mode: 'default' | 'update', consent: UETConsent) {\n if (typeof window === 'undefined') return;\n window.uetq ??= [] as unknown as UETQ;\n window.uetq.push('consent', mode, consent);\n}\n\n/**\n * The Conversions API's client-side ID Sync pixel: ties the visitor id sent server-side as\n * `anonymousId` to Microsoft's own identifier, so server events can be attributed across\n * contexts (view-through, audiences). Microsoft requires it for remarketing built from CAPI\n * events and recommends it for measurement quality; fire it at least once per session, ideally\n * on the first page view. A pixel rather than a fetch on purpose: Microsoft must observe the\n * browser context of the sync, which a server-side call cannot carry.\n *\n * `customerId` is the Microsoft Advertising customer id (`cid` in the UI's URLs) — not the UET\n * tag id. `visitorId` is the SDK visitor id (`getVisitor().id`), which is what\n * `sendMicrosoftEvents` sends as `anonymousId`; Microsoft requires the two to be equal.\n * `userId` is the raw signed-in user id: it is SHA-256 hashed here, exactly as the server sender\n * hashes it into `externalId`, so the pair matches as well. Hashing is asynchronous, so the\n * pixel fires once the digest resolves; where SubtleCrypto is unavailable (an insecure context)\n * the pixel goes out without `UID` rather than with a raw id.\n * https://learn.microsoft.com/en-us/advertising/guides/uet-conversion-api-integration#id-sync-and-why-it-matters\n */\n/**\n * The Microsoft Advertising customer id the ID Sync pixel reports to, set once by the framework\n * `Analytics` component's `uetCustomerId` prop (or `configureUET`). Unset, nothing syncs.\n */\nlet uetCustomerId: string | undefined;\n\nexport function configureUET(options: { customerId?: string | number }) {\n uetCustomerId = options.customerId === undefined ? undefined : String(options.customerId);\n}\n\n/**\n * Sync the SDK visitor — the `anonymousId` of the events the server sends to the Conversions\n * API — with Microsoft, plus the user's `UID` when one is known. The `Analytics` components run\n * it on mount so every visit syncs at least once, anonymous visitors included (they are who\n * remarketing audiences are built from), and `setUETUser` runs it again on sign-in.\n */\nexport async function syncUETVisitor(userId?: string): Promise<void> {\n if (!uetCustomerId) return;\n try {\n const { id } = await getVisitor();\n sendUETIdSync({ customerId: uetCustomerId, visitorId: id, userId });\n } catch {\n // The visitor request failed; the next page load tries again.\n }\n}\n\nexport function sendUETIdSync(options: {\n customerId: string | number;\n visitorId: string;\n /** The signed-in user's id, raw; hashed before it leaves the page. */\n userId?: string;\n}) {\n if (typeof window === 'undefined' || typeof Image === 'undefined') return;\n if (isLocal()) return;\n\n const fire = (uid?: string) => {\n const params = new URLSearchParams({\n Red3: `BACID_${options.customerId}`,\n VID: options.visitorId,\n });\n if (uid) params.set('UID', uid);\n new Image().src = `https://c.bing.com/c.gif?${params.toString()}`;\n };\n\n if (!options.userId) {\n fire();\n return;\n }\n sha256(options.userId).then(fire, () => fire());\n}\n"],"mappings":";;;;;;AAiBA,MAAM,UAAU;CAAC;CAAO;CAAO;CAAO;CAAO;CAAO;AAAM;;AAI1D,SAAS,MAAM,OAAqB;CAClC,OAAO,KAAK,MAAM,KAAK,UAAU,KAAK,CAAC;AACzC;AAEA,SAAS,UAAmB;CAC1B,OAAO,OAAO,SAAS,KAAK,SAAS,WAAW,KAAK,OAAO,SAAS,KAAK,SAAS,WAAW;AAChG;;;;;;;;;;;;;AAcA,SAAgB,aACd,MACA,YACA,SACA;CACA,IAAI,OAAO,WAAW,eAAe,CAAC,OAAO,MAAM;EACjD,QAAQ,KAAK,+BAA+B;EAC5C;CACF;CACA,IAAI,QAAQ,SAAS,IAAI,KAAK,SAAS,aAAa;CACpD,IAAI,QAAQ,GAAG;CAEf,MAAM,CAAC,QAAQ,UAAUA,mBAAAA,YAAY,MAAM,YAAY,OAAO;CAC9D,OAAO,KAAK,KAAK,SAAS,QAAQ,MAAM,MAAM,CAAC;AACjD;;;;;;;;;;;;AAaA,SAAgB,WAAW,EAAE,SAAS,aAA+B;CACnE,IAAI,OAAO,WAAW,eAAe,CAAC,OAAO,MAAM;EACjD,QAAQ,KAAK,+BAA+B;EAC5C;CACF;CAGA,IAAI,SAAS,eAAoB,OAAO;CAExC,MAAM,KAAKC,oBAAAA,SAAS,WAAW,KAAK;CACpC,MAAM,KAAKA,oBAAAA,SAAS,WAAW,YAAY;CAC3C,IAAI,CAAC,MAAM,CAAC,IAAI;CAEhB,OAAO,KAAK,KAAK,OAAO,EAAE,KAAK,MAAM;EAAE;EAAI;CAAG,CAAC,EAAE,CAAC;AACpD;;;;;;;AAQA,SAAgB,cAAc,MAA4B,SAAqB;CAC7E,IAAI,OAAO,WAAW,aAAa;CACnC,OAAO,SAAS,CAAC;CACjB,OAAO,KAAK,KAAK,WAAW,MAAM,OAAO;AAC3C;;;;;;;;;;;;;;;;;;;;;;AAuBA,IAAI;AAEJ,SAAgB,aAAa,SAA2C;CACtE,gBAAgB,QAAQ,eAAe,KAAA,IAAY,KAAA,IAAY,OAAO,QAAQ,UAAU;AAC1F;;;;;;;AAQA,eAAsB,eAAe,QAAgC;CACnE,IAAI,CAAC,eAAe;CACpB,IAAI;EACF,MAAM,EAAE,OAAO,MAAMC,sBAAAA,WAAW;EAChC,cAAc;GAAE,YAAY;GAAe,WAAW;GAAI;EAAO,CAAC;CACpE,QAAQ,CAER;AACF;AAEA,SAAgB,cAAc,SAK3B;CACD,IAAI,OAAO,WAAW,eAAe,OAAO,UAAU,aAAa;CACnE,IAAI,QAAQ,GAAG;CAEf,MAAM,QAAQ,QAAiB;EAC7B,MAAM,SAAS,IAAI,gBAAgB;GACjC,MAAM,SAAS,QAAQ;GACvB,KAAK,QAAQ;EACf,CAAC;EACD,IAAI,KAAK,OAAO,IAAI,OAAO,GAAG;EAC9B,IAAI,MAAM,CAAC,CAAC,MAAM,4BAA4B,OAAO,SAAS;CAChE;CAEA,IAAI,CAAC,QAAQ,QAAQ;EACnB,KAAK;EACL;CACF;CACA,qBAAA,OAAO,QAAQ,MAAM,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC;AAChD"}
|
|
@@ -31,10 +31,11 @@ declare function sendUETEvent<T extends EventName>(name: TrackName<T>, propertie
|
|
|
31
31
|
* when the page load already went out. Values are sent raw — the tag normalizes and SHA-256
|
|
32
32
|
* hashes them in the browser (bat.js `validatePid`) before anything leaves the page.
|
|
33
33
|
*
|
|
34
|
-
*
|
|
35
|
-
* and `set` addresses whichever tag drains `uetq
|
|
34
|
+
* A setter itself, like `setGAUser`, rather than a factory like `setFBUser(pixelId)`: UET is
|
|
35
|
+
* bound to its tag by the snippet and `set` addresses whichever tag drains `uetq`, so there is
|
|
36
|
+
* nothing to bind first.
|
|
36
37
|
*/
|
|
37
|
-
declare function setUETUser(
|
|
38
|
+
declare function setUETUser({ user_id, user_data }: UpdateVisitorDTO): void;
|
|
38
39
|
/**
|
|
39
40
|
* UET consent mode. Push `default` before the tag loads (the tag processes `consent` early, ahead
|
|
40
41
|
* of the queued events) and `update` when the visitor decides. With `ad_storage: 'denied'` the
|
|
@@ -42,23 +43,16 @@ declare function setUETUser(): ({ user_data }: UpdateVisitorDTO) => void;
|
|
|
42
43
|
* https://help.ads.microsoft.com/#apex/ads/en/60119/1
|
|
43
44
|
*/
|
|
44
45
|
declare function setUETConsent(mode: 'default' | 'update', consent: UETConsent): void;
|
|
46
|
+
declare function configureUET(options: {
|
|
47
|
+
customerId?: string | number;
|
|
48
|
+
}): void;
|
|
45
49
|
/**
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* on the first page view. A pixel rather than a fetch on purpose: Microsoft must observe the
|
|
51
|
-
* browser context of the sync, which a server-side call cannot carry.
|
|
52
|
-
*
|
|
53
|
-
* `customerId` is the Microsoft Advertising customer id (`cid` in the UI's URLs) — not the UET
|
|
54
|
-
* tag id. `visitorId` is the SDK visitor id (`getVisitor().id`), which is what
|
|
55
|
-
* `sendMicrosoftEvents` sends as `anonymousId`; Microsoft requires the two to be equal.
|
|
56
|
-
* `userId` is the raw signed-in user id: it is SHA-256 hashed here, exactly as the server sender
|
|
57
|
-
* hashes it into `externalId`, so the pair matches as well. Hashing is asynchronous, so the
|
|
58
|
-
* pixel fires once the digest resolves; where SubtleCrypto is unavailable (an insecure context)
|
|
59
|
-
* the pixel goes out without `UID` rather than with a raw id.
|
|
60
|
-
* https://learn.microsoft.com/en-us/advertising/guides/uet-conversion-api-integration#id-sync-and-why-it-matters
|
|
50
|
+
* Sync the SDK visitor — the `anonymousId` of the events the server sends to the Conversions
|
|
51
|
+
* API — with Microsoft, plus the user's `UID` when one is known. The `Analytics` components run
|
|
52
|
+
* it on mount so every visit syncs at least once, anonymous visitors included (they are who
|
|
53
|
+
* remarketing audiences are built from), and `setUETUser` runs it again on sign-in.
|
|
61
54
|
*/
|
|
55
|
+
declare function syncUETVisitor(userId?: string): Promise<void>;
|
|
62
56
|
declare function sendUETIdSync(options: {
|
|
63
57
|
customerId: string | number;
|
|
64
58
|
visitorId: string;
|
|
@@ -66,5 +60,5 @@ declare function sendUETIdSync(options: {
|
|
|
66
60
|
userId?: string;
|
|
67
61
|
}): void;
|
|
68
62
|
//#endregion
|
|
69
|
-
export { sendUETEvent, sendUETIdSync, setUETConsent, setUETUser };
|
|
63
|
+
export { configureUET, sendUETEvent, sendUETIdSync, setUETConsent, setUETUser, syncUETVisitor };
|
|
70
64
|
//# sourceMappingURL=microsoft-uet.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"microsoft-uet.d.cts","names":[],"sources":["../../src/third-parties/microsoft-uet.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"microsoft-uet.d.cts","names":[],"sources":["../../src/third-parties/microsoft-uet.ts"],"mappings":";;;;QAOQ;YACI;;;;;IAKR,OAAO;;;;;;;;;;;;;;;iBA4BK,aAAa,UAAU,WACrC,MAAM,UAAU,IAChB,aAAa,gBAAgB,IAC7B;;;;;;;;;;;;iBAwBc,aAAa,SAAS,aAAa;;;;;;;iBAsBnC,cAAc,4BAA4B,SAAS;iBA6BnD,aAAa;EAAW;;;;;;;;iBAUlB,eAAe,kBAAkB;iBAUvC,cAAc;EAC5B;EACA;;EAEA"}
|
|
@@ -31,10 +31,11 @@ declare function sendUETEvent<T extends EventName>(name: TrackName<T>, propertie
|
|
|
31
31
|
* when the page load already went out. Values are sent raw — the tag normalizes and SHA-256
|
|
32
32
|
* hashes them in the browser (bat.js `validatePid`) before anything leaves the page.
|
|
33
33
|
*
|
|
34
|
-
*
|
|
35
|
-
* and `set` addresses whichever tag drains `uetq
|
|
34
|
+
* A setter itself, like `setGAUser`, rather than a factory like `setFBUser(pixelId)`: UET is
|
|
35
|
+
* bound to its tag by the snippet and `set` addresses whichever tag drains `uetq`, so there is
|
|
36
|
+
* nothing to bind first.
|
|
36
37
|
*/
|
|
37
|
-
declare function setUETUser(
|
|
38
|
+
declare function setUETUser({ user_id, user_data }: UpdateVisitorDTO): void;
|
|
38
39
|
/**
|
|
39
40
|
* UET consent mode. Push `default` before the tag loads (the tag processes `consent` early, ahead
|
|
40
41
|
* of the queued events) and `update` when the visitor decides. With `ad_storage: 'denied'` the
|
|
@@ -42,23 +43,16 @@ declare function setUETUser(): ({ user_data }: UpdateVisitorDTO) => void;
|
|
|
42
43
|
* https://help.ads.microsoft.com/#apex/ads/en/60119/1
|
|
43
44
|
*/
|
|
44
45
|
declare function setUETConsent(mode: 'default' | 'update', consent: UETConsent): void;
|
|
46
|
+
declare function configureUET(options: {
|
|
47
|
+
customerId?: string | number;
|
|
48
|
+
}): void;
|
|
45
49
|
/**
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* on the first page view. A pixel rather than a fetch on purpose: Microsoft must observe the
|
|
51
|
-
* browser context of the sync, which a server-side call cannot carry.
|
|
52
|
-
*
|
|
53
|
-
* `customerId` is the Microsoft Advertising customer id (`cid` in the UI's URLs) — not the UET
|
|
54
|
-
* tag id. `visitorId` is the SDK visitor id (`getVisitor().id`), which is what
|
|
55
|
-
* `sendMicrosoftEvents` sends as `anonymousId`; Microsoft requires the two to be equal.
|
|
56
|
-
* `userId` is the raw signed-in user id: it is SHA-256 hashed here, exactly as the server sender
|
|
57
|
-
* hashes it into `externalId`, so the pair matches as well. Hashing is asynchronous, so the
|
|
58
|
-
* pixel fires once the digest resolves; where SubtleCrypto is unavailable (an insecure context)
|
|
59
|
-
* the pixel goes out without `UID` rather than with a raw id.
|
|
60
|
-
* https://learn.microsoft.com/en-us/advertising/guides/uet-conversion-api-integration#id-sync-and-why-it-matters
|
|
50
|
+
* Sync the SDK visitor — the `anonymousId` of the events the server sends to the Conversions
|
|
51
|
+
* API — with Microsoft, plus the user's `UID` when one is known. The `Analytics` components run
|
|
52
|
+
* it on mount so every visit syncs at least once, anonymous visitors included (they are who
|
|
53
|
+
* remarketing audiences are built from), and `setUETUser` runs it again on sign-in.
|
|
61
54
|
*/
|
|
55
|
+
declare function syncUETVisitor(userId?: string): Promise<void>;
|
|
62
56
|
declare function sendUETIdSync(options: {
|
|
63
57
|
customerId: string | number;
|
|
64
58
|
visitorId: string;
|
|
@@ -66,5 +60,5 @@ declare function sendUETIdSync(options: {
|
|
|
66
60
|
userId?: string;
|
|
67
61
|
}): void;
|
|
68
62
|
//#endregion
|
|
69
|
-
export { sendUETEvent, sendUETIdSync, setUETConsent, setUETUser };
|
|
63
|
+
export { configureUET, sendUETEvent, sendUETIdSync, setUETConsent, setUETUser, syncUETVisitor };
|
|
70
64
|
//# sourceMappingURL=microsoft-uet.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"microsoft-uet.d.mts","names":[],"sources":["../../src/third-parties/microsoft-uet.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"microsoft-uet.d.mts","names":[],"sources":["../../src/third-parties/microsoft-uet.ts"],"mappings":";;;;QAOQ;YACI;;;;;IAKR,OAAO;;;;;;;;;;;;;;;iBA4BK,aAAa,UAAU,WACrC,MAAM,UAAU,IAChB,aAAa,gBAAgB,IAC7B;;;;;;;;;;;;iBAwBc,aAAa,SAAS,aAAa;;;;;;;iBAsBnC,cAAc,4BAA4B,SAAS;iBA6BnD,aAAa;EAAW;;;;;;;;iBAUlB,eAAe,kBAAkB;iBAUvC,cAAc;EAC5B;EACA;;EAEA"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getVisitor } from "../visitor/index.mjs";
|
|
2
2
|
import { mapUETEvent } from "../track/uetq.mjs";
|
|
3
|
+
import { getFirst } from "../utils/field.mjs";
|
|
3
4
|
import { sha256 } from "../utils/sha256.mjs";
|
|
4
5
|
//#region src/third-parties/microsoft-uet.ts
|
|
5
6
|
const metrics = [
|
|
@@ -46,23 +47,23 @@ function sendUETEvent(name, properties, eventId) {
|
|
|
46
47
|
* when the page load already went out. Values are sent raw — the tag normalizes and SHA-256
|
|
47
48
|
* hashes them in the browser (bat.js `validatePid`) before anything leaves the page.
|
|
48
49
|
*
|
|
49
|
-
*
|
|
50
|
-
* and `set` addresses whichever tag drains `uetq
|
|
50
|
+
* A setter itself, like `setGAUser`, rather than a factory like `setFBUser(pixelId)`: UET is
|
|
51
|
+
* bound to its tag by the snippet and `set` addresses whichever tag drains `uetq`, so there is
|
|
52
|
+
* nothing to bind first.
|
|
51
53
|
*/
|
|
52
|
-
function setUETUser() {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
};
|
|
54
|
+
function setUETUser({ user_id, user_data }) {
|
|
55
|
+
if (typeof window === "undefined" || !window.uetq) {
|
|
56
|
+
console.warn("uetq has not been initialized");
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (user_id) syncUETVisitor(user_id);
|
|
60
|
+
const em = getFirst(user_data?.email);
|
|
61
|
+
const ph = getFirst(user_data?.phone_number);
|
|
62
|
+
if (!em && !ph) return;
|
|
63
|
+
window.uetq.push("set", { pid: clean({
|
|
64
|
+
em,
|
|
65
|
+
ph
|
|
66
|
+
}) });
|
|
66
67
|
}
|
|
67
68
|
/**
|
|
68
69
|
* UET consent mode. Push `default` before the tag loads (the tag processes `consent` early, ahead
|
|
@@ -92,6 +93,31 @@ function setUETConsent(mode, consent) {
|
|
|
92
93
|
* the pixel goes out without `UID` rather than with a raw id.
|
|
93
94
|
* https://learn.microsoft.com/en-us/advertising/guides/uet-conversion-api-integration#id-sync-and-why-it-matters
|
|
94
95
|
*/
|
|
96
|
+
/**
|
|
97
|
+
* The Microsoft Advertising customer id the ID Sync pixel reports to, set once by the framework
|
|
98
|
+
* `Analytics` component's `uetCustomerId` prop (or `configureUET`). Unset, nothing syncs.
|
|
99
|
+
*/
|
|
100
|
+
let uetCustomerId;
|
|
101
|
+
function configureUET(options) {
|
|
102
|
+
uetCustomerId = options.customerId === void 0 ? void 0 : String(options.customerId);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Sync the SDK visitor — the `anonymousId` of the events the server sends to the Conversions
|
|
106
|
+
* API — with Microsoft, plus the user's `UID` when one is known. The `Analytics` components run
|
|
107
|
+
* it on mount so every visit syncs at least once, anonymous visitors included (they are who
|
|
108
|
+
* remarketing audiences are built from), and `setUETUser` runs it again on sign-in.
|
|
109
|
+
*/
|
|
110
|
+
async function syncUETVisitor(userId) {
|
|
111
|
+
if (!uetCustomerId) return;
|
|
112
|
+
try {
|
|
113
|
+
const { id } = await getVisitor();
|
|
114
|
+
sendUETIdSync({
|
|
115
|
+
customerId: uetCustomerId,
|
|
116
|
+
visitorId: id,
|
|
117
|
+
userId
|
|
118
|
+
});
|
|
119
|
+
} catch {}
|
|
120
|
+
}
|
|
95
121
|
function sendUETIdSync(options) {
|
|
96
122
|
if (typeof window === "undefined" || typeof Image === "undefined") return;
|
|
97
123
|
if (isLocal()) return;
|
|
@@ -110,6 +136,6 @@ function sendUETIdSync(options) {
|
|
|
110
136
|
sha256(options.userId).then(fire, () => fire());
|
|
111
137
|
}
|
|
112
138
|
//#endregion
|
|
113
|
-
export { sendUETEvent, sendUETIdSync, setUETConsent, setUETUser };
|
|
139
|
+
export { configureUET, sendUETEvent, sendUETIdSync, setUETConsent, setUETUser, syncUETVisitor };
|
|
114
140
|
|
|
115
141
|
//# sourceMappingURL=microsoft-uet.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"microsoft-uet.mjs","names":[],"sources":["../../src/third-parties/microsoft-uet.ts"],"sourcesContent":["import type { UpdateVisitorDTO } from '../schema/index';\nimport type { EventName, TrackName, TrackProperties } from '../track/types';\nimport { type UETConsent, type UETQ, mapUETEvent } from '../track/uetq';\nimport { getFirst } from '../utils/field';\nimport { sha256 } from '../utils/sha256';\n\ndeclare global {\n interface Window {\n /**\n * Defined by the UET snippet before `bat.js` loads (as a plain array), so pushes made early\n * are queued rather than lost. Undefined only where the snippet was never installed.\n */\n uetq?: UETQ;\n }\n}\n\nconst metrics = ['CLS', 'FCP', 'FID', 'INP', 'LCP', 'TTFB'];\n\n/** Drop `undefined` fields: bat.js validates every key it receives, and `undefined` is a value. */\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\nfunction clean(value: unknown): any {\n return JSON.parse(JSON.stringify(value));\n}\n\nfunction isLocal(): boolean {\n return window.location.host.includes('127.0.0.1') || window.location.host.includes('localhost');\n}\n\n/**\n * Forward an internal track event to the Microsoft Advertising UET tag.\n *\n * `eventId` is reused as UET's `event_id` so the browser event deduplicates against the same\n * conversion sent through the Conversions API (`sendMicrosoftEvents`). The action name is the\n * internal name on both channels — see `mapUETEvent`.\n *\n * `page_view` is not forwarded: bat.js turns that action into its page-load beacon, which the\n * snippet already fires on load and, with `enableAutoSpaTracking: true` (the setting in\n * Microsoft's generated snippet), on every history change — forwarding the SDK's own page views\n * would report each page twice. The tag owns page loads; this tracker owns everything else.\n */\nexport function sendUETEvent<T extends EventName>(\n name: TrackName<T>,\n properties?: TrackProperties<T>,\n eventId?: string\n) {\n if (typeof window === 'undefined' || !window.uetq) {\n console.warn('uetq has not been initialized');\n return;\n }\n if (metrics.includes(name) || name === 'page_view') return;\n if (isLocal()) return;\n\n const [action, params] = mapUETEvent(name, properties, eventId);\n window.uetq.push('event', action, clean(params));\n}\n\n/**\n * Enhanced conversions: hand the tag the visitor's email and phone so Microsoft can match a\n * conversion to an ad click without a third-party cookie. A `set` applies to every event fired\n * from the page afterwards, `pageLoad` included, and the tag fires a `pid` beacon on its own\n * when the page load already went out. Values are sent raw — the tag normalizes and SHA-256\n * hashes them in the browser (bat.js `validatePid`) before anything leaves the page.\n *\n *
|
|
1
|
+
{"version":3,"file":"microsoft-uet.mjs","names":[],"sources":["../../src/third-parties/microsoft-uet.ts"],"sourcesContent":["import type { UpdateVisitorDTO } from '../schema/index';\nimport type { EventName, TrackName, TrackProperties } from '../track/types';\nimport { type UETConsent, type UETQ, mapUETEvent } from '../track/uetq';\nimport { getFirst } from '../utils/field';\nimport { sha256 } from '../utils/sha256';\nimport { getVisitor } from '../visitor/index';\n\ndeclare global {\n interface Window {\n /**\n * Defined by the UET snippet before `bat.js` loads (as a plain array), so pushes made early\n * are queued rather than lost. Undefined only where the snippet was never installed.\n */\n uetq?: UETQ;\n }\n}\n\nconst metrics = ['CLS', 'FCP', 'FID', 'INP', 'LCP', 'TTFB'];\n\n/** Drop `undefined` fields: bat.js validates every key it receives, and `undefined` is a value. */\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\nfunction clean(value: unknown): any {\n return JSON.parse(JSON.stringify(value));\n}\n\nfunction isLocal(): boolean {\n return window.location.host.includes('127.0.0.1') || window.location.host.includes('localhost');\n}\n\n/**\n * Forward an internal track event to the Microsoft Advertising UET tag.\n *\n * `eventId` is reused as UET's `event_id` so the browser event deduplicates against the same\n * conversion sent through the Conversions API (`sendMicrosoftEvents`). The action name is the\n * internal name on both channels — see `mapUETEvent`.\n *\n * `page_view` is not forwarded: bat.js turns that action into its page-load beacon, which the\n * snippet already fires on load and, with `enableAutoSpaTracking: true` (the setting in\n * Microsoft's generated snippet), on every history change — forwarding the SDK's own page views\n * would report each page twice. The tag owns page loads; this tracker owns everything else.\n */\nexport function sendUETEvent<T extends EventName>(\n name: TrackName<T>,\n properties?: TrackProperties<T>,\n eventId?: string\n) {\n if (typeof window === 'undefined' || !window.uetq) {\n console.warn('uetq has not been initialized');\n return;\n }\n if (metrics.includes(name) || name === 'page_view') return;\n if (isLocal()) return;\n\n const [action, params] = mapUETEvent(name, properties, eventId);\n window.uetq.push('event', action, clean(params));\n}\n\n/**\n * Enhanced conversions: hand the tag the visitor's email and phone so Microsoft can match a\n * conversion to an ad click without a third-party cookie. A `set` applies to every event fired\n * from the page afterwards, `pageLoad` included, and the tag fires a `pid` beacon on its own\n * when the page load already went out. Values are sent raw — the tag normalizes and SHA-256\n * hashes them in the browser (bat.js `validatePid`) before anything leaves the page.\n *\n * A setter itself, like `setGAUser`, rather than a factory like `setFBUser(pixelId)`: UET is\n * bound to its tag by the snippet and `set` addresses whichever tag drains `uetq`, so there is\n * nothing to bind first.\n */\nexport function setUETUser({ user_id, user_data }: UpdateVisitorDTO) {\n if (typeof window === 'undefined' || !window.uetq) {\n console.warn('uetq has not been initialized');\n return;\n }\n\n // A signed-in user is also the moment the ID Sync pixel can carry a `UID` — see `syncUETVisitor`.\n if (user_id) void syncUETVisitor(user_id);\n\n const em = getFirst(user_data?.email);\n const ph = getFirst(user_data?.phone_number);\n if (!em && !ph) return;\n\n window.uetq.push('set', { pid: clean({ em, ph }) });\n}\n\n/**\n * UET consent mode. Push `default` before the tag loads (the tag processes `consent` early, ahead\n * of the queued events) and `update` when the visitor decides. With `ad_storage: 'denied'` the\n * tag neither writes its cookies nor reads the `msclkid` from the URL.\n * https://help.ads.microsoft.com/#apex/ads/en/60119/1\n */\nexport function setUETConsent(mode: 'default' | 'update', consent: UETConsent) {\n if (typeof window === 'undefined') return;\n window.uetq ??= [] as unknown as UETQ;\n window.uetq.push('consent', mode, consent);\n}\n\n/**\n * The Conversions API's client-side ID Sync pixel: ties the visitor id sent server-side as\n * `anonymousId` to Microsoft's own identifier, so server events can be attributed across\n * contexts (view-through, audiences). Microsoft requires it for remarketing built from CAPI\n * events and recommends it for measurement quality; fire it at least once per session, ideally\n * on the first page view. A pixel rather than a fetch on purpose: Microsoft must observe the\n * browser context of the sync, which a server-side call cannot carry.\n *\n * `customerId` is the Microsoft Advertising customer id (`cid` in the UI's URLs) — not the UET\n * tag id. `visitorId` is the SDK visitor id (`getVisitor().id`), which is what\n * `sendMicrosoftEvents` sends as `anonymousId`; Microsoft requires the two to be equal.\n * `userId` is the raw signed-in user id: it is SHA-256 hashed here, exactly as the server sender\n * hashes it into `externalId`, so the pair matches as well. Hashing is asynchronous, so the\n * pixel fires once the digest resolves; where SubtleCrypto is unavailable (an insecure context)\n * the pixel goes out without `UID` rather than with a raw id.\n * https://learn.microsoft.com/en-us/advertising/guides/uet-conversion-api-integration#id-sync-and-why-it-matters\n */\n/**\n * The Microsoft Advertising customer id the ID Sync pixel reports to, set once by the framework\n * `Analytics` component's `uetCustomerId` prop (or `configureUET`). Unset, nothing syncs.\n */\nlet uetCustomerId: string | undefined;\n\nexport function configureUET(options: { customerId?: string | number }) {\n uetCustomerId = options.customerId === undefined ? undefined : String(options.customerId);\n}\n\n/**\n * Sync the SDK visitor — the `anonymousId` of the events the server sends to the Conversions\n * API — with Microsoft, plus the user's `UID` when one is known. The `Analytics` components run\n * it on mount so every visit syncs at least once, anonymous visitors included (they are who\n * remarketing audiences are built from), and `setUETUser` runs it again on sign-in.\n */\nexport async function syncUETVisitor(userId?: string): Promise<void> {\n if (!uetCustomerId) return;\n try {\n const { id } = await getVisitor();\n sendUETIdSync({ customerId: uetCustomerId, visitorId: id, userId });\n } catch {\n // The visitor request failed; the next page load tries again.\n }\n}\n\nexport function sendUETIdSync(options: {\n customerId: string | number;\n visitorId: string;\n /** The signed-in user's id, raw; hashed before it leaves the page. */\n userId?: string;\n}) {\n if (typeof window === 'undefined' || typeof Image === 'undefined') return;\n if (isLocal()) return;\n\n const fire = (uid?: string) => {\n const params = new URLSearchParams({\n Red3: `BACID_${options.customerId}`,\n VID: options.visitorId,\n });\n if (uid) params.set('UID', uid);\n new Image().src = `https://c.bing.com/c.gif?${params.toString()}`;\n };\n\n if (!options.userId) {\n fire();\n return;\n }\n sha256(options.userId).then(fire, () => fire());\n}\n"],"mappings":";;;;;AAiBA,MAAM,UAAU;CAAC;CAAO;CAAO;CAAO;CAAO;CAAO;AAAM;;AAI1D,SAAS,MAAM,OAAqB;CAClC,OAAO,KAAK,MAAM,KAAK,UAAU,KAAK,CAAC;AACzC;AAEA,SAAS,UAAmB;CAC1B,OAAO,OAAO,SAAS,KAAK,SAAS,WAAW,KAAK,OAAO,SAAS,KAAK,SAAS,WAAW;AAChG;;;;;;;;;;;;;AAcA,SAAgB,aACd,MACA,YACA,SACA;CACA,IAAI,OAAO,WAAW,eAAe,CAAC,OAAO,MAAM;EACjD,QAAQ,KAAK,+BAA+B;EAC5C;CACF;CACA,IAAI,QAAQ,SAAS,IAAI,KAAK,SAAS,aAAa;CACpD,IAAI,QAAQ,GAAG;CAEf,MAAM,CAAC,QAAQ,UAAU,YAAY,MAAM,YAAY,OAAO;CAC9D,OAAO,KAAK,KAAK,SAAS,QAAQ,MAAM,MAAM,CAAC;AACjD;;;;;;;;;;;;AAaA,SAAgB,WAAW,EAAE,SAAS,aAA+B;CACnE,IAAI,OAAO,WAAW,eAAe,CAAC,OAAO,MAAM;EACjD,QAAQ,KAAK,+BAA+B;EAC5C;CACF;CAGA,IAAI,SAAS,eAAoB,OAAO;CAExC,MAAM,KAAK,SAAS,WAAW,KAAK;CACpC,MAAM,KAAK,SAAS,WAAW,YAAY;CAC3C,IAAI,CAAC,MAAM,CAAC,IAAI;CAEhB,OAAO,KAAK,KAAK,OAAO,EAAE,KAAK,MAAM;EAAE;EAAI;CAAG,CAAC,EAAE,CAAC;AACpD;;;;;;;AAQA,SAAgB,cAAc,MAA4B,SAAqB;CAC7E,IAAI,OAAO,WAAW,aAAa;CACnC,OAAO,SAAS,CAAC;CACjB,OAAO,KAAK,KAAK,WAAW,MAAM,OAAO;AAC3C;;;;;;;;;;;;;;;;;;;;;;AAuBA,IAAI;AAEJ,SAAgB,aAAa,SAA2C;CACtE,gBAAgB,QAAQ,eAAe,KAAA,IAAY,KAAA,IAAY,OAAO,QAAQ,UAAU;AAC1F;;;;;;;AAQA,eAAsB,eAAe,QAAgC;CACnE,IAAI,CAAC,eAAe;CACpB,IAAI;EACF,MAAM,EAAE,OAAO,MAAM,WAAW;EAChC,cAAc;GAAE,YAAY;GAAe,WAAW;GAAI;EAAO,CAAC;CACpE,QAAQ,CAER;AACF;AAEA,SAAgB,cAAc,SAK3B;CACD,IAAI,OAAO,WAAW,eAAe,OAAO,UAAU,aAAa;CACnE,IAAI,QAAQ,GAAG;CAEf,MAAM,QAAQ,QAAiB;EAC7B,MAAM,SAAS,IAAI,gBAAgB;GACjC,MAAM,SAAS,QAAQ;GACvB,KAAK,QAAQ;EACf,CAAC;EACD,IAAI,KAAK,OAAO,IAAI,OAAO,GAAG;EAC9B,IAAI,MAAM,CAAC,CAAC,MAAM,4BAA4B,OAAO,SAAS;CAChE;CAEA,IAAI,CAAC,QAAQ,QAAQ;EACnB,KAAK;EACL;CACF;CACA,OAAO,QAAQ,MAAM,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC;AAChD"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_utils_field = require("../utils/field.cjs");
|
|
3
|
-
const require_track_oaiq = require("../track/oaiq.cjs");
|
|
4
3
|
const require_utils_sha256 = require("../utils/sha256.cjs");
|
|
4
|
+
const require_track_oaiq = require("../track/oaiq.cjs");
|
|
5
5
|
//#region src/third-parties/openai-pixel.ts
|
|
6
6
|
/** Drop `undefined` fields so the SDK only receives populated values. */
|
|
7
7
|
function clean(value) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getFirst } from "../utils/field.mjs";
|
|
2
|
-
import { NON_AD_EVENTS, mapOAIEvent } from "../track/oaiq.mjs";
|
|
3
2
|
import { sha256 } from "../utils/sha256.mjs";
|
|
3
|
+
import { NON_AD_EVENTS, mapOAIEvent } from "../track/oaiq.mjs";
|
|
4
4
|
//#region src/third-parties/openai-pixel.ts
|
|
5
5
|
/** Drop `undefined` fields so the SDK only receives populated values. */
|
|
6
6
|
function clean(value) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_track_rdt = require("../track/rdt.cjs");
|
|
3
2
|
const require_utils_field = require("../utils/field.cjs");
|
|
3
|
+
const require_track_rdt = require("../track/rdt.cjs");
|
|
4
4
|
//#region src/third-parties/reddit-pixel.ts
|
|
5
5
|
const metrics = [
|
|
6
6
|
"CLS",
|
package/dist/track/types.d.cts
CHANGED
|
@@ -108,6 +108,13 @@ interface PageInfo {
|
|
|
108
108
|
page_location?: string;
|
|
109
109
|
page_referrer?: string;
|
|
110
110
|
page_title?: string;
|
|
111
|
+
/**
|
|
112
|
+
* Identifies one page load: every event of a page carries the same id, and a navigation — a
|
|
113
|
+
* reload, or a single-page-app route change, the same moments a `page_view` is sent — starts
|
|
114
|
+
* a new one. Lets a server-side sender tie a conversion to the page load it happened on
|
|
115
|
+
* (Microsoft's `pageLoadId`). Web only.
|
|
116
|
+
*/
|
|
117
|
+
page_load_id?: string;
|
|
111
118
|
/**
|
|
112
119
|
* @deprecated Renamed to `page_location` in 7.0.0, and never set by this SDK any more.
|
|
113
120
|
* Declared so events from clients still on an older version keep their page URL through
|