@bacano/sdk 1.1.20 → 1.2.2
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 +4 -0
- package/STOREFRONT_FORMS.md +7 -0
- package/STOREFRONT_MARKETING.md +161 -6
- package/index.cjs +322 -86
- package/index.js +322 -86
- package/marketing/browser-adapters.d.ts +30 -0
- package/marketing/clarity.d.ts +1 -1
- package/marketing/form-interactions.d.ts +12 -0
- package/marketing/gtm.d.ts +6 -0
- package/marketing/index.d.ts +2 -0
- package/marketing/interactions.d.ts +19 -0
- package/marketing/types.d.ts +5 -2
- package/package.json +1 -1
- package/react/cta-tracking.d.ts +5 -0
- package/react/form-sections.d.ts +16 -0
- package/react/form-tracking.d.ts +11 -0
- package/react/forms.cjs +230 -93
- package/react/forms.d.ts +6 -2
- package/react/forms.js +222 -85
- package/react/marketing-provider.d.ts +2 -1
- package/react.cjs +411 -136
- package/react.d.ts +1 -0
- package/react.js +394 -119
- package/skills/bacano-web/SKILL.md +5 -0
- package/skills/bacano-web/references/forms.md +5 -0
- package/skills/bacano-web/references/interactions.md +147 -0
- package/skills/bacano-web/references/report.md +5 -0
- package/types.d.ts +4 -0
package/index.cjs
CHANGED
|
@@ -394,7 +394,8 @@ async function getWebsitePublicConfig(options) {
|
|
|
394
394
|
pixelId: marketing.destinations.meta.pixel_id,
|
|
395
395
|
diagnosticMode: marketing.destinations.meta.diagnostic_mode ?? false
|
|
396
396
|
} : null,
|
|
397
|
-
clarity: marketing.destinations.clarity ? { projectId: marketing.destinations.clarity.project_id } : null
|
|
397
|
+
clarity: marketing.destinations.clarity ? { projectId: marketing.destinations.clarity.project_id } : null,
|
|
398
|
+
...marketing.destinations.gtm ? { gtm: { containerId: marketing.destinations.gtm.container_id } } : {}
|
|
398
399
|
}
|
|
399
400
|
},
|
|
400
401
|
legal: {
|
|
@@ -2957,6 +2958,9 @@ var ALLOWED_MARKETING_PARAMETERS = /* @__PURE__ */ new Set([
|
|
|
2957
2958
|
function sanitizeMarketingUrl(input, baseUrl) {
|
|
2958
2959
|
try {
|
|
2959
2960
|
const url = new URL(input, baseUrl);
|
|
2961
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") return "";
|
|
2962
|
+
url.username = "";
|
|
2963
|
+
url.password = "";
|
|
2960
2964
|
const safeParameters = new URLSearchParams();
|
|
2961
2965
|
for (const [key, value] of url.searchParams.entries()) {
|
|
2962
2966
|
if (ALLOWED_MARKETING_PARAMETERS.has(key.toLowerCase()) && !SENSITIVE_PARAMETER_PATTERNS.some((pattern) => pattern.test(key))) {
|
|
@@ -5732,50 +5736,65 @@ function createContentModule(graphqlUrl, getHeaders, getContext, storageUrl) {
|
|
|
5732
5736
|
};
|
|
5733
5737
|
}
|
|
5734
5738
|
|
|
5735
|
-
// libs/sdk/src/marketing/
|
|
5736
|
-
var
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5739
|
+
// libs/sdk/src/marketing/interactions.ts
|
|
5740
|
+
var WEBSITE_INTERACTION_EVENTS = [
|
|
5741
|
+
"cta_click",
|
|
5742
|
+
"form_open",
|
|
5743
|
+
"form_start",
|
|
5744
|
+
"form_step_complete",
|
|
5745
|
+
"form_submit_attempt",
|
|
5746
|
+
"form_submit_error",
|
|
5747
|
+
"form_submit_success"
|
|
5748
|
+
];
|
|
5749
|
+
function isInteractionEvent(name) {
|
|
5750
|
+
return WEBSITE_INTERACTION_EVENTS.some((candidate) => candidate === name);
|
|
5751
|
+
}
|
|
5752
|
+
function isInteractionIdentifier(value) {
|
|
5753
|
+
return typeof value === "string" && /^[a-z][a-z0-9_-]{0,63}$/.test(value);
|
|
5754
|
+
}
|
|
5755
|
+
function isBrowserMarketingEvent(name) {
|
|
5756
|
+
return isInteractionEvent(name) || [
|
|
5757
|
+
"page_view",
|
|
5758
|
+
"search",
|
|
5759
|
+
"view_item_list",
|
|
5760
|
+
"select_item",
|
|
5761
|
+
"view_item",
|
|
5762
|
+
"add_to_cart",
|
|
5763
|
+
"remove_from_cart",
|
|
5764
|
+
"view_cart",
|
|
5765
|
+
"begin_checkout",
|
|
5766
|
+
"add_shipping_info",
|
|
5767
|
+
"add_payment_info",
|
|
5768
|
+
"contact"
|
|
5769
|
+
].includes(name);
|
|
5770
|
+
}
|
|
5771
|
+
function interactionParameters(event) {
|
|
5772
|
+
if (!isInteractionEvent(event.eventName)) return {};
|
|
5773
|
+
if (event.eventName === "cta_click" ? !isInteractionIdentifier(event.ctaId) : !isInteractionIdentifier(event.formKey))
|
|
5774
|
+
return null;
|
|
5775
|
+
if (event.eventName === "form_step_complete" && !isInteractionIdentifier(event.stepKey))
|
|
5776
|
+
return null;
|
|
5777
|
+
if (event.eventName === "form_submit_error" && !["validation", "network", "rejected", "unavailable"].includes(
|
|
5778
|
+
event.errorCategory ?? ""
|
|
5779
|
+
))
|
|
5780
|
+
return null;
|
|
5781
|
+
const params = {};
|
|
5782
|
+
for (const [key, value] of Object.entries({
|
|
5783
|
+
form_key: event.formKey,
|
|
5784
|
+
cta_id: event.ctaId,
|
|
5785
|
+
placement: event.placement,
|
|
5786
|
+
step_key: event.stepKey
|
|
5787
|
+
})) {
|
|
5788
|
+
if (value === void 0) continue;
|
|
5789
|
+
if (!isInteractionIdentifier(value)) return null;
|
|
5790
|
+
params[key] = value;
|
|
5749
5791
|
}
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
if (typeof document === "undefined") return;
|
|
5754
|
-
const id = `bacano-clarity-${projectId}`;
|
|
5755
|
-
if (document.getElementById(id)) return;
|
|
5756
|
-
const script = document.createElement("script");
|
|
5757
|
-
script.id = id;
|
|
5758
|
-
script.async = true;
|
|
5759
|
-
script.src = `https://www.clarity.ms/tag/${encodeURIComponent(projectId)}`;
|
|
5760
|
-
script.referrerPolicy = "strict-origin-when-cross-origin";
|
|
5761
|
-
document.head.appendChild(script);
|
|
5762
|
-
}
|
|
5763
|
-
function sendClarityEvent(eventName) {
|
|
5764
|
-
clarityWindow()?.clarity?.("event", eventName);
|
|
5792
|
+
if (event.eventName === "form_submit_error" && event.errorCategory)
|
|
5793
|
+
params.error_category = event.errorCategory;
|
|
5794
|
+
return params;
|
|
5765
5795
|
}
|
|
5766
|
-
|
|
5767
|
-
|
|
5768
|
-
function matchesCanonicalMarketingHost(canonicalDomain, currentHostname) {
|
|
5769
|
-
if (canonicalDomain === void 0) return true;
|
|
5770
|
-
if (!canonicalDomain?.trim()) return false;
|
|
5771
|
-
try {
|
|
5772
|
-
const configuredHost = new URL(
|
|
5773
|
-
canonicalDomain.includes("://") ? canonicalDomain : `https://${canonicalDomain}`
|
|
5774
|
-
).hostname.toLowerCase();
|
|
5775
|
-
return currentHostname.toLowerCase() === configuredHost;
|
|
5776
|
-
} catch {
|
|
5777
|
-
return false;
|
|
5778
|
-
}
|
|
5796
|
+
function newMarketingEventId() {
|
|
5797
|
+
return typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `evt_${Date.now()}_${Math.random().toString(16).slice(2)}`;
|
|
5779
5798
|
}
|
|
5780
5799
|
|
|
5781
5800
|
// libs/sdk/src/marketing/ga4.ts
|
|
@@ -5803,19 +5822,20 @@ var WEBSITE_MARKETING_CONTACT_PLACEMENTS = [
|
|
|
5803
5822
|
"contact_page"
|
|
5804
5823
|
];
|
|
5805
5824
|
|
|
5806
|
-
// libs/sdk/src/marketing/
|
|
5825
|
+
// libs/sdk/src/marketing/browser-adapters.ts
|
|
5807
5826
|
var initializedGa4Destinations = /* @__PURE__ */ new Set();
|
|
5808
5827
|
var initializedMetaDestinations = /* @__PURE__ */ new Set();
|
|
5809
5828
|
function marketingWindow() {
|
|
5810
5829
|
return typeof window === "undefined" ? null : window;
|
|
5811
5830
|
}
|
|
5812
|
-
function loadScriptOnce(id, source) {
|
|
5831
|
+
function loadScriptOnce(id, source, onError) {
|
|
5813
5832
|
if (typeof document === "undefined" || document.getElementById(id)) return;
|
|
5814
5833
|
const script = document.createElement("script");
|
|
5815
5834
|
script.id = id;
|
|
5816
5835
|
script.async = true;
|
|
5817
5836
|
script.src = source;
|
|
5818
5837
|
script.referrerPolicy = "strict-origin-when-cross-origin";
|
|
5838
|
+
script.onerror = () => onError?.();
|
|
5819
5839
|
document.head.appendChild(script);
|
|
5820
5840
|
}
|
|
5821
5841
|
function prepareGa4(measurementId) {
|
|
@@ -5830,10 +5850,11 @@ function prepareGa4(measurementId) {
|
|
|
5830
5850
|
target.gtag("config", measurementId, { send_page_view: false });
|
|
5831
5851
|
initializedGa4Destinations.add(measurementId);
|
|
5832
5852
|
}
|
|
5833
|
-
function loadGa4Script(measurementId) {
|
|
5853
|
+
function loadGa4Script(measurementId, onError) {
|
|
5834
5854
|
loadScriptOnce(
|
|
5835
5855
|
`bacano-ga4-${measurementId}`,
|
|
5836
|
-
`https://www.googletagmanager.com/gtag/js?id=${encodeURIComponent(measurementId)}
|
|
5856
|
+
`https://www.googletagmanager.com/gtag/js?id=${encodeURIComponent(measurementId)}`,
|
|
5857
|
+
onError
|
|
5837
5858
|
);
|
|
5838
5859
|
}
|
|
5839
5860
|
function captureGa4ClientId(measurementId, websiteId, diagnostic) {
|
|
@@ -5881,10 +5902,11 @@ function prepareMeta(pixelId) {
|
|
|
5881
5902
|
target.fbq("init", pixelId);
|
|
5882
5903
|
initializedMetaDestinations.add(pixelId);
|
|
5883
5904
|
}
|
|
5884
|
-
function loadMetaScript() {
|
|
5905
|
+
function loadMetaScript(onError) {
|
|
5885
5906
|
loadScriptOnce(
|
|
5886
5907
|
"bacano-meta-pixel",
|
|
5887
|
-
"https://connect.facebook.net/en_US/fbevents.js"
|
|
5908
|
+
"https://connect.facebook.net/en_US/fbevents.js",
|
|
5909
|
+
onError
|
|
5888
5910
|
);
|
|
5889
5911
|
}
|
|
5890
5912
|
function scheduleScriptLoad(load, strategy) {
|
|
@@ -5948,10 +5970,12 @@ function contactPlacementFor(event) {
|
|
|
5948
5970
|
}
|
|
5949
5971
|
return placement;
|
|
5950
5972
|
}
|
|
5951
|
-
function sendGa4(event, diagnosticMode) {
|
|
5973
|
+
function sendGa4(event, diagnosticMode, measurementId) {
|
|
5952
5974
|
const target = marketingWindow();
|
|
5953
5975
|
const contactPlacement = contactPlacementFor(event);
|
|
5954
5976
|
target?.gtag?.("event", event.eventName, {
|
|
5977
|
+
send_to: measurementId,
|
|
5978
|
+
...interactionParameters(event),
|
|
5955
5979
|
currency: event.currency,
|
|
5956
5980
|
value: event.value,
|
|
5957
5981
|
search_term: event.searchTerm,
|
|
@@ -5968,15 +5992,17 @@ function sendGa4(event, diagnosticMode) {
|
|
|
5968
5992
|
debug_mode: diagnosticMode ? true : void 0
|
|
5969
5993
|
});
|
|
5970
5994
|
}
|
|
5971
|
-
function sendMeta(event) {
|
|
5995
|
+
function sendMeta(event, pixelId) {
|
|
5972
5996
|
const target = marketingWindow();
|
|
5973
5997
|
const eventName = metaEventName(event.eventName);
|
|
5974
5998
|
const isStandard = eventName !== event.eventName;
|
|
5975
5999
|
const contactPlacement = contactPlacementFor(event);
|
|
5976
6000
|
target?.fbq?.(
|
|
5977
|
-
isStandard ? "
|
|
6001
|
+
isStandard ? "trackSingle" : "trackSingleCustom",
|
|
6002
|
+
pixelId,
|
|
5978
6003
|
eventName,
|
|
5979
6004
|
{
|
|
6005
|
+
...interactionParameters(event),
|
|
5980
6006
|
currency: event.currency,
|
|
5981
6007
|
value: event.value,
|
|
5982
6008
|
search_string: event.searchTerm,
|
|
@@ -5993,40 +6019,192 @@ function sendMeta(event) {
|
|
|
5993
6019
|
{ eventID: event.eventId }
|
|
5994
6020
|
);
|
|
5995
6021
|
}
|
|
5996
|
-
|
|
5997
|
-
|
|
6022
|
+
|
|
6023
|
+
// libs/sdk/src/marketing/clarity.ts
|
|
6024
|
+
var initializedDestinations = /* @__PURE__ */ new Set();
|
|
6025
|
+
function clarityWindow() {
|
|
6026
|
+
return typeof window === "undefined" ? null : window;
|
|
6027
|
+
}
|
|
6028
|
+
function prepareClarity(projectId) {
|
|
6029
|
+
const target = clarityWindow();
|
|
6030
|
+
if (!target || initializedDestinations.has(projectId)) return;
|
|
6031
|
+
if (!target.clarity) {
|
|
6032
|
+
const clarity = function() {
|
|
6033
|
+
clarity.q ??= [];
|
|
6034
|
+
clarity.q.push(arguments);
|
|
6035
|
+
};
|
|
6036
|
+
target.clarity = clarity;
|
|
6037
|
+
}
|
|
6038
|
+
initializedDestinations.add(projectId);
|
|
6039
|
+
}
|
|
6040
|
+
function loadClarityScript(projectId, onError) {
|
|
6041
|
+
if (typeof document === "undefined") return;
|
|
6042
|
+
const id = `bacano-clarity-${projectId}`;
|
|
6043
|
+
if (document.getElementById(id)) return;
|
|
6044
|
+
const script = document.createElement("script");
|
|
6045
|
+
script.id = id;
|
|
6046
|
+
script.async = true;
|
|
6047
|
+
script.src = `https://www.clarity.ms/tag/${encodeURIComponent(projectId)}`;
|
|
6048
|
+
script.referrerPolicy = "strict-origin-when-cross-origin";
|
|
6049
|
+
script.onerror = () => onError?.();
|
|
6050
|
+
document.head.appendChild(script);
|
|
6051
|
+
}
|
|
6052
|
+
function sendClarityEvent(eventName) {
|
|
6053
|
+
clarityWindow()?.clarity?.("event", eventName);
|
|
6054
|
+
}
|
|
6055
|
+
|
|
6056
|
+
// libs/sdk/src/marketing/domain.ts
|
|
6057
|
+
function matchesCanonicalMarketingHost(canonicalDomain, currentHostname) {
|
|
6058
|
+
if (canonicalDomain === void 0) return true;
|
|
6059
|
+
if (!canonicalDomain?.trim()) return false;
|
|
6060
|
+
try {
|
|
6061
|
+
const configuredHost = new URL(
|
|
6062
|
+
canonicalDomain.includes("://") ? canonicalDomain : `https://${canonicalDomain}`
|
|
6063
|
+
).hostname.toLowerCase();
|
|
6064
|
+
return currentHostname.toLowerCase() === configuredHost;
|
|
6065
|
+
} catch {
|
|
6066
|
+
return false;
|
|
6067
|
+
}
|
|
6068
|
+
}
|
|
6069
|
+
|
|
6070
|
+
// libs/sdk/src/marketing/gtm.ts
|
|
6071
|
+
var CONTAINER_ID = /^GTM-[A-Z0-9]{4,32}$/;
|
|
6072
|
+
var preparedQueues = /* @__PURE__ */ new WeakMap();
|
|
6073
|
+
function prepareGtm(containerId) {
|
|
6074
|
+
const target = marketingWindow();
|
|
6075
|
+
if (!target || !CONTAINER_ID.test(containerId)) return;
|
|
6076
|
+
target.dataLayer ??= [];
|
|
6077
|
+
const containers = preparedQueues.get(target.dataLayer) ?? /* @__PURE__ */ new Set();
|
|
6078
|
+
if (containers.has(containerId)) return;
|
|
6079
|
+
target.dataLayer.push({ "gtm.start": Date.now(), event: "gtm.js" });
|
|
6080
|
+
containers.add(containerId);
|
|
6081
|
+
preparedQueues.set(target.dataLayer, containers);
|
|
6082
|
+
}
|
|
6083
|
+
function loadGtmScript(containerId, onError) {
|
|
6084
|
+
const target = marketingWindow();
|
|
6085
|
+
if (!target || typeof document === "undefined" || !CONTAINER_ID.test(containerId))
|
|
6086
|
+
return;
|
|
6087
|
+
const id = `bacano-gtm-${containerId}`;
|
|
6088
|
+
if (document.getElementById(id)) return;
|
|
6089
|
+
prepareGtm(containerId);
|
|
6090
|
+
const script = document.createElement("script");
|
|
6091
|
+
script.id = id;
|
|
6092
|
+
script.async = true;
|
|
6093
|
+
script.src = `https://www.googletagmanager.com/gtm.js?id=${encodeURIComponent(containerId)}`;
|
|
6094
|
+
script.referrerPolicy = "strict-origin-when-cross-origin";
|
|
6095
|
+
script.onerror = () => onError();
|
|
6096
|
+
document.head.appendChild(script);
|
|
6097
|
+
}
|
|
6098
|
+
function sendGtm(event) {
|
|
6099
|
+
const target = marketingWindow();
|
|
6100
|
+
if (!target?.dataLayer) return;
|
|
6101
|
+
target.dataLayer.push({ bacano: null });
|
|
6102
|
+
target.dataLayer.push({
|
|
6103
|
+
event: `bacano_${event.eventName}`,
|
|
6104
|
+
bacano: {
|
|
6105
|
+
schema_version: event.schemaVersion,
|
|
6106
|
+
event_name: event.eventName,
|
|
6107
|
+
event_id: event.eventId,
|
|
6108
|
+
...interactionParameters(event),
|
|
6109
|
+
page_location: event.pageLocation,
|
|
6110
|
+
currency: event.currency,
|
|
6111
|
+
value: event.value,
|
|
6112
|
+
items: mapGa4Items(event.items),
|
|
6113
|
+
item_list_id: event.itemListId,
|
|
6114
|
+
item_list_name: event.itemListName,
|
|
6115
|
+
shipping_tier: event.shippingTier,
|
|
6116
|
+
payment_type: event.paymentType,
|
|
6117
|
+
method: event.contactMethod,
|
|
6118
|
+
contact_placement: event.eventName === "contact" && WEBSITE_MARKETING_CONTACT_PLACEMENTS.some(
|
|
6119
|
+
(value) => value === event.contactPlacement
|
|
6120
|
+
) ? event.contactPlacement : void 0
|
|
6121
|
+
}
|
|
6122
|
+
});
|
|
5998
6123
|
}
|
|
6124
|
+
|
|
6125
|
+
// libs/sdk/src/marketing/runtime.ts
|
|
5999
6126
|
function createWebsiteMarketingRuntime(options) {
|
|
6000
6127
|
let destroyed = false;
|
|
6128
|
+
const dispatched = /* @__PURE__ */ new Set();
|
|
6129
|
+
const observer = options.diagnostic;
|
|
6130
|
+
const diagnostic = (value) => {
|
|
6131
|
+
try {
|
|
6132
|
+
observer?.(value);
|
|
6133
|
+
} catch {
|
|
6134
|
+
}
|
|
6135
|
+
};
|
|
6136
|
+
options = { ...options, diagnostic };
|
|
6001
6137
|
let cancelScheduledLoad = () => void 0;
|
|
6002
6138
|
const target = marketingWindow();
|
|
6003
|
-
const enabled = options.config.enabled && Boolean(
|
|
6139
|
+
const enabled = options.config.enabled && options.measurementAllowed !== false && Boolean(
|
|
6004
6140
|
target && matchesCanonicalMarketingHost(
|
|
6005
6141
|
options.canonicalDomain,
|
|
6006
6142
|
target.location.hostname
|
|
6007
6143
|
)
|
|
6008
6144
|
) && Boolean(
|
|
6009
|
-
options.config.destinations.ga4 || options.config.destinations.meta || options.config.destinations.clarity
|
|
6145
|
+
options.config.destinations.ga4 || options.config.destinations.meta || options.config.destinations.clarity || options.config.destinations.gtm
|
|
6010
6146
|
);
|
|
6147
|
+
if (!enabled)
|
|
6148
|
+
diagnostic({
|
|
6149
|
+
level: "debug",
|
|
6150
|
+
code: !options.config.enabled ? "MARKETING_DISABLED" : options.measurementAllowed === false ? "MEASUREMENT_NOT_ALLOWED" : !target ? "SERVER_RENDER" : !matchesCanonicalMarketingHost(
|
|
6151
|
+
options.canonicalDomain,
|
|
6152
|
+
target.location.hostname
|
|
6153
|
+
) ? "DOMAIN_NOT_ALLOWED" : "PROVIDER_NOT_CONFIGURED",
|
|
6154
|
+
message: "Measurement is inactive; no events are emitted"
|
|
6155
|
+
});
|
|
6011
6156
|
if (enabled) {
|
|
6157
|
+
const guard = (provider, action) => {
|
|
6158
|
+
try {
|
|
6159
|
+
action();
|
|
6160
|
+
} catch {
|
|
6161
|
+
diagnostic({
|
|
6162
|
+
level: "warning",
|
|
6163
|
+
code: "RUNTIME_INITIALIZATION_FAILED",
|
|
6164
|
+
message: `${provider}: initialization failed`
|
|
6165
|
+
});
|
|
6166
|
+
}
|
|
6167
|
+
};
|
|
6168
|
+
const scriptError = (provider) => () => diagnostic({
|
|
6169
|
+
level: "warning",
|
|
6170
|
+
code: "SCRIPT_LOAD_FAILED",
|
|
6171
|
+
message: `${provider}: script could not load (network, CSP or blocker); external reception is unverified`
|
|
6172
|
+
});
|
|
6012
6173
|
try {
|
|
6013
6174
|
if (options.config.destinations.ga4) {
|
|
6014
|
-
|
|
6175
|
+
const { measurementId } = options.config.destinations.ga4;
|
|
6176
|
+
guard("GA4", () => prepareGa4(measurementId));
|
|
6015
6177
|
}
|
|
6016
6178
|
if (options.config.destinations.meta) {
|
|
6017
|
-
|
|
6179
|
+
const { pixelId } = options.config.destinations.meta;
|
|
6180
|
+
guard("Meta", () => prepareMeta(pixelId));
|
|
6018
6181
|
}
|
|
6019
6182
|
if (options.config.destinations.clarity) {
|
|
6020
|
-
|
|
6183
|
+
const { projectId } = options.config.destinations.clarity;
|
|
6184
|
+
guard("Clarity", () => prepareClarity(projectId));
|
|
6185
|
+
}
|
|
6186
|
+
if (options.config.destinations.gtm) {
|
|
6187
|
+
const { containerId } = options.config.destinations.gtm;
|
|
6188
|
+
guard("GTM", () => prepareGtm(containerId));
|
|
6021
6189
|
}
|
|
6022
6190
|
cancelScheduledLoad = scheduleScriptLoad(() => {
|
|
6023
6191
|
if (destroyed) return;
|
|
6024
6192
|
if (options.config.destinations.ga4) {
|
|
6025
|
-
|
|
6193
|
+
const { measurementId } = options.config.destinations.ga4;
|
|
6194
|
+
guard("GA4", () => loadGa4Script(measurementId, scriptError("GA4")));
|
|
6026
6195
|
}
|
|
6027
|
-
if (options.config.destinations.meta)
|
|
6196
|
+
if (options.config.destinations.meta)
|
|
6197
|
+
guard("Meta", () => loadMetaScript(scriptError("Meta")));
|
|
6028
6198
|
if (options.config.destinations.clarity) {
|
|
6029
|
-
|
|
6199
|
+
const { projectId } = options.config.destinations.clarity;
|
|
6200
|
+
guard(
|
|
6201
|
+
"Clarity",
|
|
6202
|
+
() => loadClarityScript(projectId, scriptError("Clarity"))
|
|
6203
|
+
);
|
|
6204
|
+
}
|
|
6205
|
+
if (options.config.destinations.gtm) {
|
|
6206
|
+
const { containerId } = options.config.destinations.gtm;
|
|
6207
|
+
guard("GTM", () => loadGtmScript(containerId, scriptError("GTM")));
|
|
6030
6208
|
}
|
|
6031
6209
|
}, options.scriptLoadStrategy);
|
|
6032
6210
|
captureWebsiteMarketingAttribution(
|
|
@@ -6048,11 +6226,11 @@ function createWebsiteMarketingRuntime(options) {
|
|
|
6048
6226
|
if (options.config.destinations.meta) {
|
|
6049
6227
|
refreshWebsiteMarketingMetaContext(options.websiteId);
|
|
6050
6228
|
}
|
|
6051
|
-
} catch
|
|
6229
|
+
} catch {
|
|
6052
6230
|
options.diagnostic?.({
|
|
6053
6231
|
level: "warning",
|
|
6054
6232
|
code: "RUNTIME_INITIALIZATION_FAILED",
|
|
6055
|
-
message:
|
|
6233
|
+
message: "Marketing initialization failed; external reception is unverified"
|
|
6056
6234
|
});
|
|
6057
6235
|
}
|
|
6058
6236
|
}
|
|
@@ -6060,41 +6238,99 @@ function createWebsiteMarketingRuntime(options) {
|
|
|
6060
6238
|
enabled,
|
|
6061
6239
|
track(input) {
|
|
6062
6240
|
if (!enabled || destroyed) return;
|
|
6241
|
+
if (!isBrowserMarketingEvent(input.eventName)) {
|
|
6242
|
+
diagnostic({
|
|
6243
|
+
level: "warning",
|
|
6244
|
+
code: "INVALID_EVENT",
|
|
6245
|
+
message: "Unknown or server-owned event rejected"
|
|
6246
|
+
});
|
|
6247
|
+
return;
|
|
6248
|
+
}
|
|
6249
|
+
try {
|
|
6250
|
+
captureWebsiteMarketingAttribution(
|
|
6251
|
+
options.websiteId,
|
|
6252
|
+
options.config.attributionWindowDays
|
|
6253
|
+
);
|
|
6254
|
+
} catch {
|
|
6255
|
+
}
|
|
6063
6256
|
const event = {
|
|
6064
6257
|
...input,
|
|
6065
6258
|
schemaVersion: 1,
|
|
6066
|
-
eventId: input.eventId ??
|
|
6259
|
+
eventId: input.eventId ?? newMarketingEventId(),
|
|
6067
6260
|
occurredAt: input.occurredAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
6068
6261
|
currency: input.currency ?? options.config.currencyCode,
|
|
6069
6262
|
pageLocation: sanitizeMarketingUrl(
|
|
6070
6263
|
input.pageLocation ?? (typeof window === "undefined" ? "" : window.location.href)
|
|
6071
6264
|
)
|
|
6072
6265
|
};
|
|
6073
|
-
|
|
6074
|
-
if (
|
|
6075
|
-
|
|
6266
|
+
if (isInteractionEvent(event.eventName)) {
|
|
6267
|
+
if (!interactionParameters(event) || !/^[a-zA-Z0-9_-]{1,100}$/.test(event.eventId)) {
|
|
6268
|
+
diagnostic({
|
|
6269
|
+
level: "warning",
|
|
6270
|
+
code: "INVALID_INTERACTION",
|
|
6271
|
+
message: "Interaction rejected by the public contract",
|
|
6272
|
+
eventName: event.eventName
|
|
6273
|
+
});
|
|
6274
|
+
return;
|
|
6076
6275
|
}
|
|
6077
|
-
|
|
6078
|
-
|
|
6079
|
-
|
|
6276
|
+
for (const key of [
|
|
6277
|
+
"currency",
|
|
6278
|
+
"value",
|
|
6279
|
+
"searchTerm",
|
|
6280
|
+
"itemListId",
|
|
6281
|
+
"itemListName",
|
|
6282
|
+
"shippingTier",
|
|
6283
|
+
"paymentType",
|
|
6284
|
+
"contactMethod",
|
|
6285
|
+
"contactPlacement",
|
|
6286
|
+
"items",
|
|
6287
|
+
"pageTitle"
|
|
6288
|
+
])
|
|
6289
|
+
delete event[key];
|
|
6290
|
+
}
|
|
6291
|
+
const identity = `${event.eventName}:${event.eventId}`;
|
|
6292
|
+
if (dispatched.has(identity)) return;
|
|
6293
|
+
dispatched.add(identity);
|
|
6294
|
+
const oldest = dispatched.values().next().value;
|
|
6295
|
+
if (dispatched.size > 1e3 && oldest) dispatched.delete(oldest);
|
|
6296
|
+
const dispatch = (provider, send) => {
|
|
6297
|
+
try {
|
|
6298
|
+
send();
|
|
6299
|
+
diagnostic({
|
|
6300
|
+
level: "debug",
|
|
6301
|
+
code: "EVENT_DISPATCHED",
|
|
6302
|
+
message: `${provider}: passed to adapter; external reception is unverified`,
|
|
6303
|
+
eventName: event.eventName
|
|
6304
|
+
});
|
|
6305
|
+
} catch {
|
|
6306
|
+
diagnostic({
|
|
6307
|
+
level: "warning",
|
|
6308
|
+
code: "EVENT_DISPATCH_FAILED",
|
|
6309
|
+
message: `${provider}: adapter failed`,
|
|
6310
|
+
eventName: event.eventName
|
|
6311
|
+
});
|
|
6080
6312
|
}
|
|
6081
|
-
|
|
6082
|
-
|
|
6083
|
-
|
|
6084
|
-
|
|
6085
|
-
|
|
6086
|
-
|
|
6087
|
-
|
|
6088
|
-
|
|
6089
|
-
|
|
6090
|
-
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
|
|
6313
|
+
};
|
|
6314
|
+
if (options.config.destinations.ga4) {
|
|
6315
|
+
const ga4 = options.config.destinations.ga4;
|
|
6316
|
+
dispatch(
|
|
6317
|
+
"GA4",
|
|
6318
|
+
() => sendGa4(event, ga4.diagnosticMode, ga4.measurementId)
|
|
6319
|
+
);
|
|
6320
|
+
}
|
|
6321
|
+
if (options.config.destinations.meta) {
|
|
6322
|
+
const meta = options.config.destinations.meta;
|
|
6323
|
+
dispatch("Meta", () => sendMeta(event, meta.pixelId));
|
|
6324
|
+
}
|
|
6325
|
+
if (options.config.destinations.clarity) {
|
|
6326
|
+
dispatch("Clarity", () => sendClarityEvent(event.eventName));
|
|
6327
|
+
}
|
|
6328
|
+
if (options.config.destinations.gtm && /^GTM-[A-Z0-9]{4,32}$/.test(options.config.destinations.gtm.containerId)) {
|
|
6329
|
+
dispatch("GTM", () => sendGtm(event));
|
|
6094
6330
|
}
|
|
6095
6331
|
},
|
|
6096
6332
|
captureAttribution() {
|
|
6097
|
-
if (!enabled) return null;
|
|
6333
|
+
if (!enabled || destroyed) return null;
|
|
6098
6334
|
captureWebsiteMarketingAttribution(
|
|
6099
6335
|
options.websiteId,
|
|
6100
6336
|
options.config.attributionWindowDays
|
|
@@ -6105,7 +6341,7 @@ function createWebsiteMarketingRuntime(options) {
|
|
|
6105
6341
|
return getWebsiteMarketingAttribution(options.websiteId);
|
|
6106
6342
|
},
|
|
6107
6343
|
getAttribution() {
|
|
6108
|
-
if (!enabled) return null;
|
|
6344
|
+
if (!enabled || destroyed) return null;
|
|
6109
6345
|
if (options.config.destinations.meta) {
|
|
6110
6346
|
refreshWebsiteMarketingMetaContext(options.websiteId);
|
|
6111
6347
|
}
|