@accelerated-agency/visual-editor 0.4.9 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +583 -115
- package/dist/vite.cjs +165 -13
- package/dist/vite.js +165 -13
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5012,15 +5012,15 @@ function PlatformVisualEditorV2({
|
|
|
5012
5012
|
) }) });
|
|
5013
5013
|
}
|
|
5014
5014
|
var AI_EDITOR_CHANNEL = "ve-ai-editor";
|
|
5015
|
-
var
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
}
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5015
|
+
var AI_LOCAL_STORAGE_PREFIX = "conversion-vvveb-v2::";
|
|
5016
|
+
var DEVICE_PRESETS = {
|
|
5017
|
+
desktop: { label: "Desktop", width: 1440, height: 1024, device: "desktop" },
|
|
5018
|
+
tablet: { label: "iPad", width: 768, height: 1024, device: "tablet" },
|
|
5019
|
+
mobile: { label: "iPhone 13", width: 390, height: 844, device: "mobile" },
|
|
5020
|
+
"galaxy-s22": { label: "Galaxy S22", width: 360, height: 780, device: "mobile" },
|
|
5021
|
+
"iphone-7": { label: "iPhone 7", width: 375, height: 667, device: "mobile" },
|
|
5022
|
+
"galaxy-j1": { label: "Galaxy J1", width: 360, height: 640, device: "mobile" },
|
|
5023
|
+
responsive: { label: "Responsive", width: 1280, height: 800, device: "desktop" }
|
|
5024
5024
|
};
|
|
5025
5025
|
function fingerprint(value) {
|
|
5026
5026
|
let hash = 5381;
|
|
@@ -5029,9 +5029,17 @@ function fingerprint(value) {
|
|
|
5029
5029
|
}
|
|
5030
5030
|
return (hash >>> 0).toString(36);
|
|
5031
5031
|
}
|
|
5032
|
+
function activeVariationStorageKeyFromExperiment(experiment) {
|
|
5033
|
+
const experimentId = String(experiment?.experimentId || "");
|
|
5034
|
+
const pageUrl = String(experiment?.pageUrl || "");
|
|
5035
|
+
const key = `${AI_LOCAL_STORAGE_PREFIX}activeVar:${experimentId}:${pageUrl}`;
|
|
5036
|
+
if (key === `${AI_LOCAL_STORAGE_PREFIX}activeVar::`) return null;
|
|
5037
|
+
return key;
|
|
5038
|
+
}
|
|
5032
5039
|
function PlatformAiEditor({
|
|
5033
5040
|
embeddedGlobalKey = "__CONVERSION_EMBEDDED__",
|
|
5034
5041
|
proxyBaseUrl = "",
|
|
5042
|
+
trackingMarkers = [],
|
|
5035
5043
|
chatComponent,
|
|
5036
5044
|
className = "fixed inset-0 z-[9999] flex flex-col bg-white",
|
|
5037
5045
|
editorClassName = "flex-1 min-h-0",
|
|
@@ -5061,7 +5069,20 @@ function PlatformAiEditor({
|
|
|
5061
5069
|
const [localActiveVariationId, setLocalActiveVariationId] = useState(null);
|
|
5062
5070
|
const [isSaving, setIsSaving] = useState(false);
|
|
5063
5071
|
const [isIframeLoading, setIsIframeLoading] = useState(false);
|
|
5064
|
-
const [
|
|
5072
|
+
const [currentDevice, setCurrentDevice] = useState("desktop");
|
|
5073
|
+
const [viewportWidth, setViewportWidth] = useState(1440);
|
|
5074
|
+
const [viewportHeight, setViewportHeight] = useState(1024);
|
|
5075
|
+
const [viewportZoom, setViewportZoom] = useState(1);
|
|
5076
|
+
const [viewportPreset, setViewportPreset] = useState("desktop");
|
|
5077
|
+
const [isViewportMenuOpen, setIsViewportMenuOpen] = useState(false);
|
|
5078
|
+
const [menuWidth, setMenuWidth] = useState("1440");
|
|
5079
|
+
const [menuHeight, setMenuHeight] = useState("1024");
|
|
5080
|
+
const [menuZoom, setMenuZoom] = useState("100");
|
|
5081
|
+
const [iframePanelWidth, setIframePanelWidth] = useState(null);
|
|
5082
|
+
const iframePanelRef = useRef(null);
|
|
5083
|
+
const viewportMenuRef = useRef(null);
|
|
5084
|
+
const viewportMenuButtonRef = useRef(null);
|
|
5085
|
+
const viewportLabelRef = useRef(null);
|
|
5065
5086
|
useEffect(() => {
|
|
5066
5087
|
window[embeddedGlobalKey] = true;
|
|
5067
5088
|
return () => {
|
|
@@ -5074,6 +5095,32 @@ function PlatformAiEditor({
|
|
|
5074
5095
|
const variations = experiment?.variations ?? [];
|
|
5075
5096
|
const activeVariationId = controlledActiveVariationId ?? localActiveVariationId;
|
|
5076
5097
|
const setActiveVariationId = controlledSetActiveVariationId ?? setLocalActiveVariationId;
|
|
5098
|
+
const persistedVariationStorageKey = useMemo(
|
|
5099
|
+
() => activeVariationStorageKeyFromExperiment(experiment),
|
|
5100
|
+
[experiment?.experimentId, experiment?.pageUrl]
|
|
5101
|
+
);
|
|
5102
|
+
const readPersistedVariationId = useCallback(() => {
|
|
5103
|
+
if (!persistedVariationStorageKey) return null;
|
|
5104
|
+
try {
|
|
5105
|
+
return sessionStorage.getItem(persistedVariationStorageKey);
|
|
5106
|
+
} catch {
|
|
5107
|
+
return null;
|
|
5108
|
+
}
|
|
5109
|
+
}, [persistedVariationStorageKey]);
|
|
5110
|
+
const persistVariationId = useCallback(
|
|
5111
|
+
(variationId) => {
|
|
5112
|
+
if (!persistedVariationStorageKey) return;
|
|
5113
|
+
try {
|
|
5114
|
+
if (variationId) {
|
|
5115
|
+
sessionStorage.setItem(persistedVariationStorageKey, variationId);
|
|
5116
|
+
} else {
|
|
5117
|
+
sessionStorage.removeItem(persistedVariationStorageKey);
|
|
5118
|
+
}
|
|
5119
|
+
} catch {
|
|
5120
|
+
}
|
|
5121
|
+
},
|
|
5122
|
+
[persistedVariationStorageKey]
|
|
5123
|
+
);
|
|
5077
5124
|
useEffect(() => {
|
|
5078
5125
|
if (!variations.length) {
|
|
5079
5126
|
setActiveVariationId(null);
|
|
@@ -5081,10 +5128,12 @@ function PlatformAiEditor({
|
|
|
5081
5128
|
}
|
|
5082
5129
|
setActiveVariationId((current) => {
|
|
5083
5130
|
if (current && variations.some((variation) => variation._id === current)) return current;
|
|
5084
|
-
const
|
|
5085
|
-
|
|
5131
|
+
const stored = readPersistedVariationId();
|
|
5132
|
+
if (stored && variations.some((variation) => variation._id === stored)) return stored;
|
|
5133
|
+
const firstNonBaseline = variations.find((variation) => !variation.baseline);
|
|
5134
|
+
return firstNonBaseline?._id ?? variations[0]._id;
|
|
5086
5135
|
});
|
|
5087
|
-
}, [variations]);
|
|
5136
|
+
}, [variations, readPersistedVariationId]);
|
|
5088
5137
|
const activeVariation = useMemo(
|
|
5089
5138
|
() => variations.find((variation) => variation._id === activeVariationId) ?? null,
|
|
5090
5139
|
[variations, activeVariationId]
|
|
@@ -5105,18 +5154,52 @@ function PlatformAiEditor({
|
|
|
5105
5154
|
() => `ai-iframe-${activeVariationId ?? "default"}-${cssFingerprint}-${jsFingerprint}`,
|
|
5106
5155
|
[activeVariationId, cssFingerprint, jsFingerprint]
|
|
5107
5156
|
);
|
|
5108
|
-
|
|
5157
|
+
useEffect(() => {
|
|
5158
|
+
const panel = iframePanelRef.current;
|
|
5159
|
+
if (!panel) return;
|
|
5160
|
+
const updateWidth = () => {
|
|
5161
|
+
setIframePanelWidth(panel.clientWidth);
|
|
5162
|
+
};
|
|
5163
|
+
updateWidth();
|
|
5164
|
+
const observer = new ResizeObserver(() => {
|
|
5165
|
+
updateWidth();
|
|
5166
|
+
});
|
|
5167
|
+
observer.observe(panel);
|
|
5168
|
+
return () => {
|
|
5169
|
+
observer.disconnect();
|
|
5170
|
+
};
|
|
5171
|
+
}, []);
|
|
5172
|
+
const viewportFitZoom = useMemo(() => {
|
|
5173
|
+
const available = iframePanelWidth ? Math.max(260, iframePanelWidth - 24) : viewportWidth;
|
|
5174
|
+
if (!viewportWidth || viewportWidth <= 0) return 1;
|
|
5175
|
+
return Math.min(1, available / viewportWidth);
|
|
5176
|
+
}, [viewportWidth, iframePanelWidth]);
|
|
5177
|
+
const appliedViewportZoom = useMemo(() => {
|
|
5178
|
+
let z = Number(viewportZoom);
|
|
5179
|
+
if (!Number.isFinite(z) || z <= 0) z = 1;
|
|
5180
|
+
z = Math.max(0.25, Math.min(2, z));
|
|
5181
|
+
return Math.min(z, viewportFitZoom);
|
|
5182
|
+
}, [viewportZoom, viewportFitZoom]);
|
|
5183
|
+
const viewportLabel = useMemo(
|
|
5184
|
+
() => `${viewportWidth}x${viewportHeight} \xB7 ${Math.round(appliedViewportZoom * 100)}%`,
|
|
5185
|
+
[viewportWidth, viewportHeight, appliedViewportZoom]
|
|
5186
|
+
);
|
|
5109
5187
|
const editorSrc = useMemo(() => {
|
|
5110
5188
|
const pageUrl = experiment?.pageUrl;
|
|
5111
5189
|
if (!pageUrl) return "about:blank";
|
|
5112
5190
|
const safeBaseUrl = normalizeProxyBaseUrl(proxyBaseUrl);
|
|
5113
|
-
const
|
|
5191
|
+
const safeTrackingMarkers = Array.isArray(trackingMarkers) ? trackingMarkers.filter((marker) => typeof marker === "string" && marker.trim().length > 0) : [];
|
|
5192
|
+
const queryParams = new URLSearchParams({
|
|
5114
5193
|
password: experiment?.editorPassword ?? "",
|
|
5115
5194
|
url: pageUrl
|
|
5116
|
-
})
|
|
5195
|
+
});
|
|
5196
|
+
if (safeTrackingMarkers.length) {
|
|
5197
|
+
queryParams.set("trackingMarkers", JSON.stringify(safeTrackingMarkers));
|
|
5198
|
+
}
|
|
5199
|
+
const query = queryParams.toString();
|
|
5117
5200
|
const previewPath = `/api/conversion-proxy?${query}`;
|
|
5118
5201
|
return safeBaseUrl ? `${safeBaseUrl}${previewPath}` : previewPath;
|
|
5119
|
-
}, [proxyBaseUrl, experiment?.pageUrl, experiment?.editorPassword]);
|
|
5202
|
+
}, [proxyBaseUrl, experiment?.pageUrl, experiment?.editorPassword, trackingMarkers]);
|
|
5120
5203
|
const postAiCodeToIframe = useCallback(() => {
|
|
5121
5204
|
const targetWindow = iframeRef.current?.contentWindow;
|
|
5122
5205
|
if (!targetWindow) return;
|
|
@@ -5233,6 +5316,90 @@ function PlatformAiEditor({
|
|
|
5233
5316
|
onSaveSuccess,
|
|
5234
5317
|
onSaveError
|
|
5235
5318
|
]);
|
|
5319
|
+
const clampViewportNumber = useCallback(
|
|
5320
|
+
(value, fallback, min, max) => {
|
|
5321
|
+
const parsed = Number.parseInt(value, 10);
|
|
5322
|
+
if (!Number.isFinite(parsed)) return fallback;
|
|
5323
|
+
return Math.max(min, Math.min(max, parsed));
|
|
5324
|
+
},
|
|
5325
|
+
[]
|
|
5326
|
+
);
|
|
5327
|
+
const setDevicePreset = useCallback((device) => {
|
|
5328
|
+
const preset = DEVICE_PRESETS[device];
|
|
5329
|
+
setViewportPreset(device);
|
|
5330
|
+
setCurrentDevice(device);
|
|
5331
|
+
setViewportWidth(preset.width);
|
|
5332
|
+
setViewportHeight(preset.height);
|
|
5333
|
+
setMenuWidth(String(preset.width));
|
|
5334
|
+
setMenuHeight(String(preset.height));
|
|
5335
|
+
}, []);
|
|
5336
|
+
const setViewportFromPreset = useCallback((presetKey) => {
|
|
5337
|
+
const preset = DEVICE_PRESETS[presetKey];
|
|
5338
|
+
setViewportPreset(presetKey);
|
|
5339
|
+
setViewportWidth(preset.width);
|
|
5340
|
+
setViewportHeight(preset.height);
|
|
5341
|
+
setCurrentDevice(preset.device);
|
|
5342
|
+
setMenuWidth(String(preset.width));
|
|
5343
|
+
setMenuHeight(String(preset.height));
|
|
5344
|
+
}, []);
|
|
5345
|
+
const applyCustomViewport = useCallback(() => {
|
|
5346
|
+
const nextWidth = clampViewportNumber(menuWidth, viewportWidth, 240, 3840);
|
|
5347
|
+
const nextHeight = clampViewportNumber(menuHeight, viewportHeight, 320, 3840);
|
|
5348
|
+
const nextZoomPct = clampViewportNumber(
|
|
5349
|
+
menuZoom,
|
|
5350
|
+
Math.round(appliedViewportZoom * 100),
|
|
5351
|
+
25,
|
|
5352
|
+
200
|
|
5353
|
+
);
|
|
5354
|
+
setViewportWidth(nextWidth);
|
|
5355
|
+
setViewportHeight(nextHeight);
|
|
5356
|
+
setViewportZoom(nextZoomPct / 100);
|
|
5357
|
+
setViewportPreset("custom");
|
|
5358
|
+
setCurrentDevice(nextWidth <= 480 ? "mobile" : nextWidth <= 1024 ? "tablet" : "desktop");
|
|
5359
|
+
setMenuWidth(String(nextWidth));
|
|
5360
|
+
setMenuHeight(String(nextHeight));
|
|
5361
|
+
setMenuZoom(String(nextZoomPct));
|
|
5362
|
+
setIsViewportMenuOpen(false);
|
|
5363
|
+
}, [
|
|
5364
|
+
clampViewportNumber,
|
|
5365
|
+
menuWidth,
|
|
5366
|
+
menuHeight,
|
|
5367
|
+
menuZoom,
|
|
5368
|
+
viewportWidth,
|
|
5369
|
+
viewportHeight,
|
|
5370
|
+
appliedViewportZoom
|
|
5371
|
+
]);
|
|
5372
|
+
useEffect(() => {
|
|
5373
|
+
setMenuWidth(String(viewportWidth));
|
|
5374
|
+
setMenuHeight(String(viewportHeight));
|
|
5375
|
+
setMenuZoom(String(Math.round(appliedViewportZoom * 100)));
|
|
5376
|
+
}, [viewportWidth, viewportHeight, appliedViewportZoom]);
|
|
5377
|
+
useEffect(() => {
|
|
5378
|
+
const onWindowResize = () => {
|
|
5379
|
+
setMenuZoom(String(Math.round(Math.min(viewportZoom, viewportFitZoom) * 100)));
|
|
5380
|
+
};
|
|
5381
|
+
window.addEventListener("resize", onWindowResize);
|
|
5382
|
+
return () => window.removeEventListener("resize", onWindowResize);
|
|
5383
|
+
}, [viewportZoom, viewportFitZoom]);
|
|
5384
|
+
useEffect(() => {
|
|
5385
|
+
if (!isViewportMenuOpen) return;
|
|
5386
|
+
const onDocClick = (event) => {
|
|
5387
|
+
const target = event.target;
|
|
5388
|
+
if (viewportMenuRef.current?.contains(target)) return;
|
|
5389
|
+
if (viewportMenuButtonRef.current?.contains(target)) return;
|
|
5390
|
+
if (viewportLabelRef.current?.contains(target)) return;
|
|
5391
|
+
setIsViewportMenuOpen(false);
|
|
5392
|
+
};
|
|
5393
|
+
const onDocKeyDown = (event) => {
|
|
5394
|
+
if (event.key === "Escape") setIsViewportMenuOpen(false);
|
|
5395
|
+
};
|
|
5396
|
+
document.addEventListener("click", onDocClick);
|
|
5397
|
+
document.addEventListener("keydown", onDocKeyDown);
|
|
5398
|
+
return () => {
|
|
5399
|
+
document.removeEventListener("click", onDocClick);
|
|
5400
|
+
document.removeEventListener("keydown", onDocKeyDown);
|
|
5401
|
+
};
|
|
5402
|
+
}, [isViewportMenuOpen]);
|
|
5236
5403
|
if (error) {
|
|
5237
5404
|
if (renderError) return renderError(error);
|
|
5238
5405
|
return /* @__PURE__ */ jsx("div", { className: "fixed inset-0 z-[9999] flex items-center justify-center bg-slate-50", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2 text-center px-8", children: [
|
|
@@ -5241,112 +5408,413 @@ function PlatformAiEditor({
|
|
|
5241
5408
|
/* @__PURE__ */ jsx("p", { className: "text-xs text-red-400", children: error })
|
|
5242
5409
|
] }) });
|
|
5243
5410
|
}
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
|
|
5260
|
-
|
|
5261
|
-
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
|
|
5411
|
+
const handleVariationSelectChange = useCallback(
|
|
5412
|
+
(nextVariationId) => {
|
|
5413
|
+
persistVariationId(nextVariationId);
|
|
5414
|
+
setActiveVariationId(nextVariationId);
|
|
5415
|
+
},
|
|
5416
|
+
[persistVariationId, setActiveVariationId]
|
|
5417
|
+
);
|
|
5418
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5419
|
+
/* @__PURE__ */ jsx("style", { children: `
|
|
5420
|
+
.ai-dev-toolbar {
|
|
5421
|
+
display: flex;
|
|
5422
|
+
align-items: center;
|
|
5423
|
+
gap: 8px;
|
|
5424
|
+
}
|
|
5425
|
+
.ai-tb-viewport {
|
|
5426
|
+
display: flex;
|
|
5427
|
+
align-items: center;
|
|
5428
|
+
gap: 4px;
|
|
5429
|
+
padding: 6px 10px;
|
|
5430
|
+
border-radius: 6px;
|
|
5431
|
+
border: 1px solid #e5e7eb;
|
|
5432
|
+
background: #fff;
|
|
5433
|
+
height: 30px;
|
|
5434
|
+
flex-shrink: 0;
|
|
5435
|
+
cursor: pointer;
|
|
5436
|
+
color: #404040;
|
|
5437
|
+
font-size: 14px;
|
|
5438
|
+
font-weight: 500;
|
|
5439
|
+
line-height: 1;
|
|
5440
|
+
}
|
|
5441
|
+
.ai-tb-viewport > i {
|
|
5442
|
+
font-size: 9px;
|
|
5443
|
+
}
|
|
5444
|
+
.ai-tb-dev-wrap {
|
|
5445
|
+
position: relative;
|
|
5446
|
+
}
|
|
5447
|
+
.ai-tb-dev-btns {
|
|
5448
|
+
display: flex;
|
|
5449
|
+
align-items: center;
|
|
5450
|
+
gap: 1px;
|
|
5451
|
+
padding: 8px 4px;
|
|
5452
|
+
background: #f0f0f0;
|
|
5453
|
+
border-radius: 7px;
|
|
5454
|
+
height: 30px;
|
|
5455
|
+
width: auto;
|
|
5456
|
+
}
|
|
5457
|
+
.ai-tb-dk-btn {
|
|
5458
|
+
width: 28px;
|
|
5459
|
+
height: 28px;
|
|
5460
|
+
background: transparent;
|
|
5461
|
+
border: none;
|
|
5462
|
+
border-radius: 5px;
|
|
5463
|
+
cursor: pointer;
|
|
5464
|
+
color: #71717a;
|
|
5465
|
+
display: flex;
|
|
5466
|
+
align-items: center;
|
|
5467
|
+
justify-content: center;
|
|
5468
|
+
font-size: 13px;
|
|
5469
|
+
transition: all 0.12s;
|
|
5470
|
+
flex-shrink: 0;
|
|
5471
|
+
}
|
|
5472
|
+
.ai-tb-dk-btn.active {
|
|
5473
|
+
background: #fff;
|
|
5474
|
+
color: #27272a;
|
|
5475
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
|
|
5476
|
+
}
|
|
5477
|
+
.ai-tb-dev-menu {
|
|
5478
|
+
position: absolute;
|
|
5479
|
+
top: calc(100% + 8px);
|
|
5480
|
+
right: 0;
|
|
5481
|
+
z-index: 12040;
|
|
5482
|
+
width: 264px;
|
|
5483
|
+
background: #fff;
|
|
5484
|
+
border: 1px solid #e5e7eb;
|
|
5485
|
+
border-radius: 8px;
|
|
5486
|
+
padding: 4px 4px;
|
|
5487
|
+
box-shadow: 0 12px 28px rgba(2, 6, 23, 0.18);
|
|
5488
|
+
color: #27272a;
|
|
5489
|
+
}
|
|
5490
|
+
.ai-tb-dev-menu > .row {
|
|
5491
|
+
display: flex;
|
|
5492
|
+
align-items: center;
|
|
5493
|
+
gap: 8px;
|
|
5494
|
+
margin: 0 0 8px;
|
|
5495
|
+
justify-content: space-between;
|
|
5496
|
+
padding: 4px 12px;
|
|
5497
|
+
}
|
|
5498
|
+
.ai-tb-dev-menu .row-split {
|
|
5499
|
+
display: flex;
|
|
5500
|
+
gap: 8px;
|
|
5501
|
+
}
|
|
5502
|
+
.ai-tb-dev-menu .row-split > .row{
|
|
5503
|
+
flex-direction: column;
|
|
5504
|
+
align-items: flex-start;
|
|
5505
|
+
}
|
|
5506
|
+
.ai-tb-dev-menu .row-split > * {
|
|
5507
|
+
flex: 1;
|
|
5508
|
+
}
|
|
5509
|
+
.ai-tb-dev-menu .row-split > row {
|
|
5510
|
+
display: flex;
|
|
5511
|
+
flex-direction: column;
|
|
5512
|
+
align-items: flex-start;
|
|
5513
|
+
}
|
|
5514
|
+
.ai-tb-dev-menu label {
|
|
5515
|
+
min-width: fit-content;
|
|
5516
|
+
color: var(--content-subtle, #737373);
|
|
5517
|
+
font-size: 12px;
|
|
5518
|
+
font-style: normal;
|
|
5519
|
+
font-weight: 500;
|
|
5520
|
+
line-height: 14px;
|
|
5521
|
+
}
|
|
5522
|
+
.ai-tb-dev-menu input {
|
|
5523
|
+
box-shadow: 0 0 1px 0 rgba(0, 0, 0, 0.20), 0 1px 2px 0 rgba(0, 0, 0, 0.05), 0 1px 1px 0 rgba(0, 0, 0, 0.01);
|
|
5524
|
+
width: 100%;
|
|
5525
|
+
height: 30px;
|
|
5526
|
+
border-radius: 6px;
|
|
5527
|
+
padding: 0 8px;
|
|
5528
|
+
font-size: 12px;
|
|
5529
|
+
color: #18181b;
|
|
5530
|
+
background: #fff;
|
|
5531
|
+
outline: none;
|
|
5532
|
+
color: #404040;
|
|
5533
|
+
border-color: transparent;
|
|
5534
|
+
}
|
|
5535
|
+
.ai-tb-dev-menu input#ai-dev-zoom-level {
|
|
5536
|
+
max-width: fit-content;
|
|
5537
|
+
width: 72px;
|
|
5538
|
+
}
|
|
5539
|
+
.ai-tb-dev-menu input:focus {
|
|
5540
|
+
border-color: #818cf8;
|
|
5541
|
+
box-shadow: 0 0 0 3px rgba(129, 140, 248, 0.15);
|
|
5542
|
+
}
|
|
5543
|
+
.ai-vp-presets {
|
|
5544
|
+
display: flex;
|
|
5545
|
+
flex-wrap: wrap;
|
|
5546
|
+
gap: 6px;
|
|
5547
|
+
padding: 4px 12px;
|
|
5548
|
+
}
|
|
5549
|
+
.ai-vp-preset-btn {
|
|
5550
|
+
border: 1px solid #e4e4e7;
|
|
5551
|
+
background: #fff;
|
|
5552
|
+
color: #3f3f46;
|
|
5553
|
+
border-radius: 6px;
|
|
5554
|
+
font-size: 11px;
|
|
5555
|
+
line-height: 1;
|
|
5556
|
+
padding: 7px 8px;
|
|
5557
|
+
cursor: pointer;
|
|
5558
|
+
}
|
|
5559
|
+
.ai-vp-preset-btn:hover,
|
|
5560
|
+
.ai-vp-preset-btn.active {
|
|
5561
|
+
background: #f4f4f5;
|
|
5562
|
+
}
|
|
5563
|
+
.ai-dev-ft {
|
|
5564
|
+
display: flex;
|
|
5565
|
+
justify-content: flex-end;
|
|
5566
|
+
padding: 4px 12px;
|
|
5567
|
+
}
|
|
5568
|
+
.ai-apply-btn {
|
|
5569
|
+
border: 1px solid #c7d2fe;
|
|
5570
|
+
background: #eef2ff;
|
|
5571
|
+
color: #3730a3;
|
|
5572
|
+
border-radius: 6px;
|
|
5573
|
+
height: 30px;
|
|
5574
|
+
padding: 0 10px;
|
|
5575
|
+
font-size: 12px;
|
|
5576
|
+
font-weight: 600;
|
|
5577
|
+
cursor: pointer;
|
|
5578
|
+
}
|
|
5579
|
+
.ai-apply-btn:hover {
|
|
5580
|
+
background: #e0e7ff;
|
|
5581
|
+
border-color: #a5b4fc;
|
|
5582
|
+
}
|
|
5583
|
+
|
|
5584
|
+
` }),
|
|
5585
|
+
/* @__PURE__ */ jsxs("div", { className, children: [
|
|
5586
|
+
showHeader ? renderHeader?.({
|
|
5587
|
+
title: title ?? experiment?.name,
|
|
5588
|
+
status: status ?? experiment?.status,
|
|
5589
|
+
tabs,
|
|
5590
|
+
activeTab,
|
|
5591
|
+
onTabClick,
|
|
5592
|
+
onClose
|
|
5593
|
+
}) ?? /* @__PURE__ */ jsxs("div", { className: "h-12 border-b border-slate-200 bg-white flex items-center justify-between px-4 shadow-[0_1px_3px_rgba(0,0,0,0.04)] shrink-0", children: [
|
|
5594
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 min-w-0", children: [
|
|
5595
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] font-bold tracking-wide px-1.5 py-0.5 rounded bg-indigo-50 text-indigo-600 border border-indigo-100 shrink-0", children: "AI" }),
|
|
5596
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold text-sm text-slate-800 truncate", children: title ?? experiment?.name ?? "AI Editor" }),
|
|
5597
|
+
status ? /* @__PURE__ */ jsx("span", { className: "hidden sm:inline-flex text-[10px] px-2 py-0.5 rounded-full border border-slate-200 text-slate-500 font-medium bg-slate-50 capitalize", children: status }) : null
|
|
5272
5598
|
] }),
|
|
5273
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
5274
|
-
{ key: "desktop", icon: "bi-display", title: "Desktop \u2014 full width" },
|
|
5275
|
-
{ key: "tablet", icon: "bi-tablet", title: "Tablet \u2014 768px" },
|
|
5276
|
-
{ key: "mobile", icon: "bi-phone", title: "Mobile \u2014 390px" }
|
|
5277
|
-
].map((vp) => /* @__PURE__ */ jsx(
|
|
5599
|
+
tabs.length > 0 ? /* @__PURE__ */ jsx("div", { className: "hidden md:flex items-center gap-1 absolute left-1/2 -translate-x-1/2", children: tabs.map((tab) => /* @__PURE__ */ jsx(
|
|
5278
5600
|
"button",
|
|
5279
5601
|
{
|
|
5280
5602
|
type: "button",
|
|
5281
|
-
onClick: () =>
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
|
-
children: /* @__PURE__ */ jsx("i", { className: `bi ${vp.icon} text-[12px]` })
|
|
5603
|
+
onClick: () => onTabClick(tab),
|
|
5604
|
+
className: `text-[11px] font-semibold px-3 py-1 rounded-full border transition-all ${tab.label === activeTab ? "bg-indigo-600 text-white border-indigo-600 shadow-sm" : "bg-white text-slate-500 border-slate-200 hover:border-slate-300 hover:text-slate-700"}`,
|
|
5605
|
+
children: tab.label
|
|
5285
5606
|
},
|
|
5286
|
-
|
|
5287
|
-
)) })
|
|
5288
|
-
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5607
|
+
tab.hash
|
|
5608
|
+
)) }) : null,
|
|
5609
|
+
/* @__PURE__ */ jsxs("div", { className: "ai-dev-toolbar", children: [
|
|
5610
|
+
/* @__PURE__ */ jsxs(
|
|
5611
|
+
"div",
|
|
5612
|
+
{
|
|
5613
|
+
ref: viewportLabelRef,
|
|
5614
|
+
role: "button",
|
|
5615
|
+
tabIndex: 0,
|
|
5616
|
+
className: "ai-tb-viewport",
|
|
5617
|
+
onClick: () => setIsViewportMenuOpen((prev) => !prev),
|
|
5618
|
+
onKeyDown: (event) => {
|
|
5619
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
5620
|
+
event.preventDefault();
|
|
5621
|
+
setIsViewportMenuOpen((prev) => !prev);
|
|
5622
|
+
}
|
|
5623
|
+
},
|
|
5624
|
+
children: [
|
|
5625
|
+
/* @__PURE__ */ jsx("span", { children: viewportLabel }),
|
|
5626
|
+
/* @__PURE__ */ jsx("i", { className: "bi bi-chevron-down" })
|
|
5627
|
+
]
|
|
5628
|
+
}
|
|
5629
|
+
),
|
|
5630
|
+
/* @__PURE__ */ jsxs("div", { className: "ai-tb-dev-wrap", children: [
|
|
5631
|
+
/* @__PURE__ */ jsxs("div", { className: "ai-tb-dev-btns", children: [
|
|
5632
|
+
[
|
|
5633
|
+
{ key: "desktop", icon: "bi-display", title: "Desktop \u2014 full width" },
|
|
5634
|
+
{ key: "tablet", icon: "bi-tablet", title: "Tablet \u2014 768px" },
|
|
5635
|
+
{ key: "mobile", icon: "bi-phone", title: "Mobile \u2014 390px" }
|
|
5636
|
+
].map((vp) => /* @__PURE__ */ jsx(
|
|
5637
|
+
"button",
|
|
5638
|
+
{
|
|
5639
|
+
type: "button",
|
|
5640
|
+
onClick: () => setDevicePreset(vp.key),
|
|
5641
|
+
title: vp.title,
|
|
5642
|
+
className: `ai-tb-dk-btn ${currentDevice === vp.key ? "active" : ""}`,
|
|
5643
|
+
children: /* @__PURE__ */ jsx("i", { className: `bi ${vp.icon}` })
|
|
5644
|
+
},
|
|
5645
|
+
vp.key
|
|
5646
|
+
)),
|
|
5647
|
+
/* @__PURE__ */ jsx(
|
|
5648
|
+
"button",
|
|
5649
|
+
{
|
|
5650
|
+
ref: viewportMenuButtonRef,
|
|
5651
|
+
type: "button",
|
|
5652
|
+
onClick: () => setIsViewportMenuOpen((prev) => !prev),
|
|
5653
|
+
title: "More options",
|
|
5654
|
+
className: `ai-tb-dk-btn ${isViewportMenuOpen ? "active" : ""}`,
|
|
5655
|
+
children: /* @__PURE__ */ jsx("i", { className: "bi bi-three-dots" })
|
|
5656
|
+
}
|
|
5657
|
+
)
|
|
5658
|
+
] }),
|
|
5659
|
+
isViewportMenuOpen ? /* @__PURE__ */ jsxs(
|
|
5660
|
+
"div",
|
|
5661
|
+
{
|
|
5662
|
+
ref: viewportMenuRef,
|
|
5663
|
+
className: "ai-tb-dev-menu",
|
|
5664
|
+
children: [
|
|
5665
|
+
/* @__PURE__ */ jsxs("div", { className: "row row-zoom", children: [
|
|
5666
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "ai-dev-zoom-level", children: "Zoom" }),
|
|
5667
|
+
/* @__PURE__ */ jsx(
|
|
5668
|
+
"input",
|
|
5669
|
+
{
|
|
5670
|
+
id: "ai-dev-zoom-level",
|
|
5671
|
+
type: "number",
|
|
5672
|
+
min: 25,
|
|
5673
|
+
max: 200,
|
|
5674
|
+
step: 5,
|
|
5675
|
+
value: menuZoom,
|
|
5676
|
+
onChange: (event) => setMenuZoom(event.target.value),
|
|
5677
|
+
onBlur: (event) => {
|
|
5678
|
+
const nextZoomPct = clampViewportNumber(
|
|
5679
|
+
event.target.value,
|
|
5680
|
+
Math.round(appliedViewportZoom * 100),
|
|
5681
|
+
25,
|
|
5682
|
+
200
|
|
5683
|
+
);
|
|
5684
|
+
setViewportZoom(nextZoomPct / 100);
|
|
5685
|
+
setMenuZoom(String(nextZoomPct));
|
|
5686
|
+
}
|
|
5687
|
+
}
|
|
5688
|
+
)
|
|
5689
|
+
] }),
|
|
5690
|
+
/* @__PURE__ */ jsxs("div", { className: "row row-split row-width height-width-row", children: [
|
|
5691
|
+
/* @__PURE__ */ jsxs("div", { className: "row", style: { margin: 0 }, children: [
|
|
5692
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "ai-dev-custom-width", children: "Width" }),
|
|
5693
|
+
/* @__PURE__ */ jsx(
|
|
5694
|
+
"input",
|
|
5695
|
+
{
|
|
5696
|
+
id: "ai-dev-custom-width",
|
|
5697
|
+
type: "number",
|
|
5698
|
+
min: 240,
|
|
5699
|
+
max: 3840,
|
|
5700
|
+
step: 1,
|
|
5701
|
+
value: menuWidth,
|
|
5702
|
+
onChange: (event) => setMenuWidth(event.target.value)
|
|
5703
|
+
}
|
|
5704
|
+
)
|
|
5705
|
+
] }),
|
|
5706
|
+
/* @__PURE__ */ jsxs("div", { className: "row", style: { margin: 0 }, children: [
|
|
5707
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "ai-dev-custom-height", children: "Height" }),
|
|
5708
|
+
/* @__PURE__ */ jsx(
|
|
5709
|
+
"input",
|
|
5710
|
+
{
|
|
5711
|
+
id: "ai-dev-custom-height",
|
|
5712
|
+
type: "number",
|
|
5713
|
+
min: 320,
|
|
5714
|
+
max: 3840,
|
|
5715
|
+
step: 1,
|
|
5716
|
+
value: menuHeight,
|
|
5717
|
+
onChange: (event) => setMenuHeight(event.target.value)
|
|
5718
|
+
}
|
|
5719
|
+
)
|
|
5720
|
+
] })
|
|
5721
|
+
] }),
|
|
5722
|
+
/* @__PURE__ */ jsx("div", { className: "ai-vp-presets vp-presets", id: "dev-preset-list", children: [
|
|
5723
|
+
{ key: "desktop", label: "Desktop" },
|
|
5724
|
+
{ key: "mobile", label: "iPhone 13" },
|
|
5725
|
+
{ key: "galaxy-s22", label: "Galaxy S22" },
|
|
5726
|
+
{ key: "tablet", label: "iPad" },
|
|
5727
|
+
{ key: "galaxy-j1", label: "Galaxy J1" },
|
|
5728
|
+
{ key: "iphone-7", label: "iPhone 7" },
|
|
5729
|
+
{ key: "responsive", label: "Responsive" }
|
|
5730
|
+
].map((preset) => /* @__PURE__ */ jsx(
|
|
5731
|
+
"button",
|
|
5732
|
+
{
|
|
5733
|
+
type: "button",
|
|
5734
|
+
onClick: () => setViewportFromPreset(preset.key),
|
|
5735
|
+
className: `ai-vp-preset-btn ${viewportPreset === preset.key ? "active" : ""}`,
|
|
5736
|
+
children: preset.label
|
|
5737
|
+
},
|
|
5738
|
+
preset.key
|
|
5739
|
+
)) }),
|
|
5740
|
+
/* @__PURE__ */ jsx("div", { className: "ai-dev-ft", children: /* @__PURE__ */ jsx(
|
|
5741
|
+
"button",
|
|
5742
|
+
{
|
|
5743
|
+
type: "button",
|
|
5744
|
+
onClick: applyCustomViewport,
|
|
5745
|
+
className: "ai-apply-btn",
|
|
5746
|
+
children: "Apply"
|
|
5747
|
+
}
|
|
5748
|
+
) })
|
|
5749
|
+
]
|
|
5750
|
+
}
|
|
5751
|
+
) : null
|
|
5752
|
+
] })
|
|
5753
|
+
] }),
|
|
5754
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
5755
|
+
variations.length > 0 ? /* @__PURE__ */ jsx(
|
|
5756
|
+
"select",
|
|
5757
|
+
{
|
|
5758
|
+
className: "h-8 max-w-[220px] rounded-md border border-slate-200 bg-white px-2 text-xs text-slate-700",
|
|
5759
|
+
value: activeVariationId ?? "",
|
|
5760
|
+
onChange: (event) => handleVariationSelectChange(event.target.value || null),
|
|
5761
|
+
"aria-label": "Select variation",
|
|
5762
|
+
children: variations.map((variation) => /* @__PURE__ */ jsx("option", { value: variation._id, children: variation.name }, variation._id))
|
|
5763
|
+
}
|
|
5764
|
+
) : null,
|
|
5765
|
+
onRequestSave ? /* @__PURE__ */ jsx(
|
|
5766
|
+
"button",
|
|
5767
|
+
{
|
|
5768
|
+
type: "button",
|
|
5769
|
+
className: "text-[11px] font-medium px-3 py-1.5 rounded-md border border-indigo-200 text-indigo-700 bg-indigo-50 hover:bg-indigo-100 hover:border-indigo-300 transition-all disabled:opacity-60 disabled:cursor-not-allowed",
|
|
5770
|
+
onClick: () => void handleSave(),
|
|
5771
|
+
disabled: isSaving,
|
|
5772
|
+
children: isSaving ? "Saving..." : "Save"
|
|
5773
|
+
}
|
|
5774
|
+
) : null,
|
|
5775
|
+
showCloseButton ? /* @__PURE__ */ jsx(
|
|
5776
|
+
"button",
|
|
5777
|
+
{
|
|
5778
|
+
type: "button",
|
|
5779
|
+
className: "text-[11px] font-medium px-3 py-1.5 rounded-md border border-slate-200 text-slate-600 hover:bg-slate-50 hover:border-slate-300 transition-all",
|
|
5780
|
+
onClick: () => onClose?.(),
|
|
5781
|
+
children: closeLabel
|
|
5782
|
+
}
|
|
5783
|
+
) : null
|
|
5784
|
+
] })
|
|
5785
|
+
] }) : null,
|
|
5786
|
+
/* @__PURE__ */ jsxs("div", { className: `${editorClassName} relative`, children: [
|
|
5787
|
+
/* @__PURE__ */ jsx("div", { ref: iframePanelRef, className: "w-full h-full bg-slate-100 overflow-auto flex justify-center items-start p-3", children: /* @__PURE__ */ jsx(
|
|
5788
|
+
"div",
|
|
5312
5789
|
{
|
|
5313
|
-
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5790
|
+
className: "h-full bg-white border border-slate-200 shadow-sm overflow-hidden",
|
|
5791
|
+
style: {
|
|
5792
|
+
width: `${viewportWidth}px`,
|
|
5793
|
+
minWidth: `${viewportWidth}px`,
|
|
5794
|
+
height: `${viewportHeight}px`,
|
|
5795
|
+
maxWidth: "none",
|
|
5796
|
+
zoom: String(appliedViewportZoom)
|
|
5797
|
+
},
|
|
5798
|
+
children: /* @__PURE__ */ jsx(
|
|
5799
|
+
"iframe",
|
|
5800
|
+
{
|
|
5801
|
+
ref: iframeRef,
|
|
5802
|
+
src: editorSrc,
|
|
5803
|
+
onLoad: handleIframeLoad,
|
|
5804
|
+
className: "w-full h-full border-0",
|
|
5805
|
+
title: "AI Editor Preview",
|
|
5806
|
+
allow: "same-origin"
|
|
5807
|
+
},
|
|
5808
|
+
iframeKey
|
|
5809
|
+
)
|
|
5317
5810
|
}
|
|
5318
|
-
)
|
|
5811
|
+
) }),
|
|
5812
|
+
isIframeLoading ? /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-slate-100/95 backdrop-blur-[1px]", children: /* @__PURE__ */ jsxs("div", { className: "w-[560px] max-w-[88vw]", children: [
|
|
5813
|
+
/* @__PURE__ */ jsx("p", { className: "mb-3 text-center text-base font-semibold text-slate-700", children: "Loading changes..." }),
|
|
5814
|
+
/* @__PURE__ */ jsx("div", { className: "h-4 w-full rounded-full border border-slate-300 bg-white/90 p-1 shadow-sm", children: /* @__PURE__ */ jsx("div", { className: "h-full w-full overflow-hidden rounded-full bg-slate-200", children: /* @__PURE__ */ jsx("div", { className: "h-full w-1/3 rounded-full bg-gradient-to-r from-emerald-300 via-sky-500 to-indigo-600 animate-pulse" }) }) })
|
|
5815
|
+
] }) }) : null,
|
|
5816
|
+
chatComponent ?? null
|
|
5319
5817
|
] })
|
|
5320
|
-
] }) : null,
|
|
5321
|
-
/* @__PURE__ */ jsxs("div", { className: `${editorClassName} relative`, children: [
|
|
5322
|
-
/* @__PURE__ */ jsx("div", { className: "w-full h-full bg-slate-100 overflow-auto flex justify-center items-start p-3", children: /* @__PURE__ */ jsx(
|
|
5323
|
-
"div",
|
|
5324
|
-
{
|
|
5325
|
-
className: "h-full bg-white border border-slate-200 shadow-sm overflow-hidden",
|
|
5326
|
-
style: {
|
|
5327
|
-
width: iframeWidth,
|
|
5328
|
-
minWidth: iframeWidth,
|
|
5329
|
-
maxWidth: "100%"
|
|
5330
|
-
},
|
|
5331
|
-
children: /* @__PURE__ */ jsx(
|
|
5332
|
-
"iframe",
|
|
5333
|
-
{
|
|
5334
|
-
ref: iframeRef,
|
|
5335
|
-
src: editorSrc,
|
|
5336
|
-
onLoad: handleIframeLoad,
|
|
5337
|
-
className: "w-full h-full border-0",
|
|
5338
|
-
title: "AI Editor Preview",
|
|
5339
|
-
allow: "same-origin"
|
|
5340
|
-
},
|
|
5341
|
-
iframeKey
|
|
5342
|
-
)
|
|
5343
|
-
}
|
|
5344
|
-
) }),
|
|
5345
|
-
isIframeLoading ? /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-slate-100/95 backdrop-blur-[1px]", children: /* @__PURE__ */ jsxs("div", { className: "w-[560px] max-w-[88vw]", children: [
|
|
5346
|
-
/* @__PURE__ */ jsx("p", { className: "mb-3 text-center text-base font-semibold text-slate-700", children: "Loading changes..." }),
|
|
5347
|
-
/* @__PURE__ */ jsx("div", { className: "h-4 w-full rounded-full border border-slate-300 bg-white/90 p-1 shadow-sm", children: /* @__PURE__ */ jsx("div", { className: "h-full w-full overflow-hidden rounded-full bg-slate-200", children: /* @__PURE__ */ jsx("div", { className: "h-full w-1/3 rounded-full bg-gradient-to-r from-emerald-300 via-sky-500 to-indigo-600 animate-pulse" }) }) })
|
|
5348
|
-
] }) }) : null,
|
|
5349
|
-
chatComponent ?? null
|
|
5350
5818
|
] })
|
|
5351
5819
|
] });
|
|
5352
5820
|
}
|
package/dist/vite.cjs
CHANGED
|
@@ -17,22 +17,114 @@ var DEFAULT_TRACKING_MARKERS = [
|
|
|
17
17
|
"googletagmanager",
|
|
18
18
|
"google-analytics",
|
|
19
19
|
"googleads",
|
|
20
|
+
"googleadservices",
|
|
21
|
+
"googlesyndication",
|
|
20
22
|
"doubleclick",
|
|
21
23
|
"gtag(",
|
|
22
24
|
"ga(",
|
|
23
25
|
"fbq(",
|
|
24
|
-
"
|
|
26
|
+
"connect.facebook.net",
|
|
27
|
+
"clarity.ms",
|
|
25
28
|
"hotjar",
|
|
26
29
|
"segment.com",
|
|
30
|
+
"segment.io",
|
|
31
|
+
"segmentapis",
|
|
27
32
|
"mixpanel",
|
|
28
|
-
"amplitude",
|
|
33
|
+
"amplitude.com",
|
|
34
|
+
"api.amplitude",
|
|
29
35
|
"fullstory",
|
|
30
36
|
"northbeam",
|
|
31
37
|
"nb-collector",
|
|
38
|
+
"j.northbeam.io",
|
|
32
39
|
"/api/collect",
|
|
33
40
|
"/nb-collector",
|
|
34
41
|
'"r":"periodic"',
|
|
35
|
-
'"r": "periodic"'
|
|
42
|
+
'"r": "periodic"',
|
|
43
|
+
"shopify-pixel",
|
|
44
|
+
"config-security.com",
|
|
45
|
+
"heap.io",
|
|
46
|
+
"heapanalytics",
|
|
47
|
+
"posthog",
|
|
48
|
+
"matomo",
|
|
49
|
+
"piwik",
|
|
50
|
+
"plausible.io",
|
|
51
|
+
"umami",
|
|
52
|
+
"statcounter",
|
|
53
|
+
"kissmetrics",
|
|
54
|
+
"pendo.io",
|
|
55
|
+
"mouseflow",
|
|
56
|
+
"quantserve",
|
|
57
|
+
"quantcast",
|
|
58
|
+
"chartbeat",
|
|
59
|
+
"parse.ly",
|
|
60
|
+
"parsely",
|
|
61
|
+
"optimizely",
|
|
62
|
+
"logrocket",
|
|
63
|
+
"smartlook",
|
|
64
|
+
"inspectlet",
|
|
65
|
+
"crazyegg",
|
|
66
|
+
"lucky-orange",
|
|
67
|
+
"luckyorange",
|
|
68
|
+
"vwo.com",
|
|
69
|
+
"contentsquare",
|
|
70
|
+
"decibel",
|
|
71
|
+
"medallia",
|
|
72
|
+
"bat.bing.com",
|
|
73
|
+
"bing.com/action",
|
|
74
|
+
"analytics.tiktok.com",
|
|
75
|
+
"tiktok-pixel",
|
|
76
|
+
"snap.licdn.com",
|
|
77
|
+
"/li/track",
|
|
78
|
+
"ads-twitter.com",
|
|
79
|
+
"static.ads-twitter",
|
|
80
|
+
"pinimg.com",
|
|
81
|
+
"pinterest-tag",
|
|
82
|
+
"reddit.com/api/v2/conversions",
|
|
83
|
+
"redditstatic",
|
|
84
|
+
"criteo",
|
|
85
|
+
"adroll",
|
|
86
|
+
"outbrain",
|
|
87
|
+
"amazon-adsystem",
|
|
88
|
+
"adsystem.amazon",
|
|
89
|
+
"q.quora.com",
|
|
90
|
+
"quora-pixel",
|
|
91
|
+
"tealium",
|
|
92
|
+
"rudderstack",
|
|
93
|
+
"mparticle",
|
|
94
|
+
"freshpaint",
|
|
95
|
+
"jitsu",
|
|
96
|
+
"customer.io",
|
|
97
|
+
"hs-analytics",
|
|
98
|
+
"hsforms",
|
|
99
|
+
"hubspot",
|
|
100
|
+
"marketo",
|
|
101
|
+
"munchkin",
|
|
102
|
+
"pardot",
|
|
103
|
+
"intercom",
|
|
104
|
+
"drift",
|
|
105
|
+
"klaviyo",
|
|
106
|
+
"omnisend",
|
|
107
|
+
"attentive",
|
|
108
|
+
"sentry",
|
|
109
|
+
"bugsnag",
|
|
110
|
+
"datadog",
|
|
111
|
+
"dd-rum",
|
|
112
|
+
"browser-intake-datadoghq",
|
|
113
|
+
"newrelic",
|
|
114
|
+
"nr-data",
|
|
115
|
+
"rollbar",
|
|
116
|
+
"cloudflareinsights",
|
|
117
|
+
"vercel-insights",
|
|
118
|
+
"_vercel/insights",
|
|
119
|
+
"vercel-speed-insights",
|
|
120
|
+
"plausible",
|
|
121
|
+
"usermaven",
|
|
122
|
+
"freshmarketer",
|
|
123
|
+
"mc.yandex",
|
|
124
|
+
"yandex.ru/metrika",
|
|
125
|
+
"hm.baidu.com",
|
|
126
|
+
"getclicky",
|
|
127
|
+
"clicky.com"
|
|
36
128
|
];
|
|
37
129
|
function normalizeTrackingMarkers(input) {
|
|
38
130
|
if (!Array.isArray(input)) return [];
|
|
@@ -67,8 +159,17 @@ function parseTrackingMarkersParam(raw) {
|
|
|
67
159
|
}
|
|
68
160
|
function hasTrackingMarker(input, markers) {
|
|
69
161
|
const text = String(input || "").toLowerCase();
|
|
162
|
+
const compactText = text.replace(/[^a-z0-9]/g, "");
|
|
70
163
|
for (let i = 0; i < markers.length; i += 1) {
|
|
71
|
-
|
|
164
|
+
const marker = String(markers[i] || "").toLowerCase().trim();
|
|
165
|
+
if (!marker) continue;
|
|
166
|
+
if (text.includes(marker)) return true;
|
|
167
|
+
const markerNoProto = marker.replace(/^https?:\/\//, "");
|
|
168
|
+
const markerNoWww = markerNoProto.replace(/^www\./, "");
|
|
169
|
+
const compactMarker = markerNoWww.replace(/[^a-z0-9]/g, "");
|
|
170
|
+
if (markerNoProto && text.includes(markerNoProto)) return true;
|
|
171
|
+
if (markerNoWww && text.includes(markerNoWww)) return true;
|
|
172
|
+
if (compactMarker && compactText.includes(compactMarker)) return true;
|
|
72
173
|
}
|
|
73
174
|
return false;
|
|
74
175
|
}
|
|
@@ -80,8 +181,30 @@ function patchKnownUnsafeEditorPatterns(scriptTag) {
|
|
|
80
181
|
);
|
|
81
182
|
return out;
|
|
82
183
|
}
|
|
184
|
+
function escapeHtmlAttribute(value) {
|
|
185
|
+
return String(value || "").replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
186
|
+
}
|
|
187
|
+
function getFirstMatchedTrackingMarker(input, markers) {
|
|
188
|
+
const text = String(input || "").toLowerCase();
|
|
189
|
+
for (let i = 0; i < markers.length; i += 1) {
|
|
190
|
+
if (text.includes(markers[i])) return markers[i];
|
|
191
|
+
}
|
|
192
|
+
return "";
|
|
193
|
+
}
|
|
194
|
+
function describeRemovedTrackingTag(tag, markers) {
|
|
195
|
+
const srcMatch = String(tag || "").match(/\bsrc\s*=\s*(["'])(.*?)\1/i);
|
|
196
|
+
const src = srcMatch?.[2]?.trim();
|
|
197
|
+
if (src) return `script:${src}`;
|
|
198
|
+
const idMatch = String(tag || "").match(/\bid\s*=\s*(["'])(.*?)\1/i);
|
|
199
|
+
const id = idMatch?.[2]?.trim();
|
|
200
|
+
if (id) return `tag#${id}`;
|
|
201
|
+
const marker = getFirstMatchedTrackingMarker(tag, markers);
|
|
202
|
+
if (marker) return `marker:${marker}`;
|
|
203
|
+
return "inline-script";
|
|
204
|
+
}
|
|
83
205
|
function stripTrackingScriptsFromScrapedHtml(html, markers) {
|
|
84
206
|
let removedCount = 0;
|
|
207
|
+
const removedScripts = [];
|
|
85
208
|
let out = html;
|
|
86
209
|
out = out.replace(/<script\b[\s\S]*?<\/script>/gi, (tag) => {
|
|
87
210
|
var patchedTag = patchKnownUnsafeEditorPatterns(tag);
|
|
@@ -89,6 +212,9 @@ function stripTrackingScriptsFromScrapedHtml(html, markers) {
|
|
|
89
212
|
const src = srcMatch?.[2] || "";
|
|
90
213
|
if (hasTrackingMarker(src, markers) || hasTrackingMarker(tag, markers)) {
|
|
91
214
|
removedCount += 1;
|
|
215
|
+
if (removedScripts.length < 25) {
|
|
216
|
+
removedScripts.push(describeRemovedTrackingTag(tag, markers).slice(0, 240));
|
|
217
|
+
}
|
|
92
218
|
return "";
|
|
93
219
|
}
|
|
94
220
|
return patchedTag;
|
|
@@ -96,13 +222,18 @@ function stripTrackingScriptsFromScrapedHtml(html, markers) {
|
|
|
96
222
|
out = out.replace(/<noscript\b[\s\S]*?<\/noscript>/gi, (tag) => {
|
|
97
223
|
if (!hasTrackingMarker(tag, markers)) return tag;
|
|
98
224
|
removedCount += 1;
|
|
225
|
+
if (removedScripts.length < 25) {
|
|
226
|
+
const marker = getFirstMatchedTrackingMarker(tag, markers);
|
|
227
|
+
removedScripts.push(`noscript:${(marker || "tracking").slice(0, 240)}`);
|
|
228
|
+
}
|
|
99
229
|
return "";
|
|
100
230
|
});
|
|
101
231
|
if (removedCount > 0) {
|
|
232
|
+
const dataScriptsValue = removedScripts.length ? ` data-scripts="${escapeHtmlAttribute(removedScripts.join(" | "))}"` : "";
|
|
102
233
|
out = out.replace(
|
|
103
234
|
/<head([^>]*)>/i,
|
|
104
235
|
`<head$1>
|
|
105
|
-
<meta name="conversion-editor-tracking-scripts-stripped" content="${removedCount}">
|
|
236
|
+
<meta name="conversion-editor-tracking-scripts-stripped" content="${removedCount}"${dataScriptsValue}>
|
|
106
237
|
`
|
|
107
238
|
);
|
|
108
239
|
}
|
|
@@ -1377,15 +1508,29 @@ function showEditorNotification(message, kind, durationMs) {
|
|
|
1377
1508
|
}, Math.max(1200, durationMs || 2600));
|
|
1378
1509
|
}
|
|
1379
1510
|
|
|
1511
|
+
function resolveSimulationId(source, keys) {
|
|
1512
|
+
var obj = source || {};
|
|
1513
|
+
var arr = Array.isArray(keys) ? keys : [];
|
|
1514
|
+
for (var i = 0; i < arr.length; i++) {
|
|
1515
|
+
var key = arr[i];
|
|
1516
|
+
var value = obj[key];
|
|
1517
|
+
if (value === undefined || value === null) continue;
|
|
1518
|
+
// Preserve numeric ids (including 0), but reject empty-string ids.
|
|
1519
|
+
if (typeof value === 'string' && value.trim() === '') continue;
|
|
1520
|
+
return value;
|
|
1521
|
+
}
|
|
1522
|
+
return null;
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1380
1525
|
function generatePreviewUrlString(args) {
|
|
1381
1526
|
var baseUrl = (args && args.url) || '';
|
|
1382
1527
|
var test = (args && args.test) || {};
|
|
1383
1528
|
var variation = (args && args.variation) || {};
|
|
1384
1529
|
if (!baseUrl) return '';
|
|
1385
|
-
var testId = test
|
|
1386
|
-
var variationId = variation
|
|
1387
|
-
if (
|
|
1388
|
-
var cId = String(testId
|
|
1530
|
+
var testId = resolveSimulationId(test, ['iid', 'experimentIid', 'experimentId', '_id', 'id']);
|
|
1531
|
+
var variationId = resolveSimulationId(variation, ['iid', 'platformIid', 'variationIid', '_id', 'id']);
|
|
1532
|
+
if (testId === null || variationId === null) return '';
|
|
1533
|
+
var cId = String(testId) + '_' + String(variationId);
|
|
1389
1534
|
var hasQueryParams = String(baseUrl).indexOf('?') >= 0;
|
|
1390
1535
|
return (
|
|
1391
1536
|
baseUrl +
|
|
@@ -1408,8 +1553,10 @@ function simulateExperiment() {
|
|
|
1408
1553
|
test.pageUrl ||
|
|
1409
1554
|
(test.metadata_1 && test.metadata_1.editor_url) ||
|
|
1410
1555
|
'';
|
|
1411
|
-
|
|
1412
|
-
|
|
1556
|
+
var testId = resolveSimulationId(test, ['iid', 'experimentIid', 'experimentId', '_id', 'id']);
|
|
1557
|
+
var variationId = resolveSimulationId(activeVariation, ['iid', 'platformIid', 'variationIid', '_id', 'id']);
|
|
1558
|
+
if (testId === null || !activeVariation || variationId === null) {
|
|
1559
|
+
showEditorNotification('Cannot simulate: missing test/variation id.', 'error', 3200);
|
|
1413
1560
|
return;
|
|
1414
1561
|
}
|
|
1415
1562
|
var url = generatePreviewUrlString({
|
|
@@ -6243,6 +6390,7 @@ function createVisualEditorMiddleware(options) {
|
|
|
6243
6390
|
const trackingMarkersForRequest = mergeTrackingMarkers(
|
|
6244
6391
|
extraTrackingMarkersForRequest
|
|
6245
6392
|
);
|
|
6393
|
+
console.log("trackingMarkersForRequest", trackingMarkersForRequest);
|
|
6246
6394
|
const strictFreezeParam = (url.searchParams.get("strictObserverFreeze") || "").toLowerCase();
|
|
6247
6395
|
const strictObserverFreezeForRequest = strictFreezeParam === "1" || strictFreezeParam === "true" || strictFreezeParam === "yes" ? true : strictFreezeParam === "0" || strictFreezeParam === "false" || strictFreezeParam === "no" ? false : strictObserverFreeze;
|
|
6248
6396
|
if (!targetUrl) {
|
|
@@ -6434,6 +6582,7 @@ var TARGET_PAGE_URL=${JSON.stringify(targetUrl)};
|
|
|
6434
6582
|
var PROXY_PASSWORD=${JSON.stringify(password)};
|
|
6435
6583
|
var PROXY_BASE_URL="";
|
|
6436
6584
|
var STRICT_OBSERVER_FREEZE=${JSON.stringify(strictObserverFreezeForRequest)};
|
|
6585
|
+
var EXTRA_TRACKING_MARKERS=${JSON.stringify(trackingMarkersForRequest)};
|
|
6437
6586
|
var PARENT_URL_CHANNEL="vvveb-proxy-url";
|
|
6438
6587
|
window.__CONVERSION_EDITOR_ACTIVE__=true;
|
|
6439
6588
|
window.__EDITOR_MODE__=true;
|
|
@@ -6474,9 +6623,11 @@ function isPeriodicCollectPayload(data){
|
|
|
6474
6623
|
}
|
|
6475
6624
|
function shouldBlockEditorTracking(rawUrl){
|
|
6476
6625
|
try{
|
|
6626
|
+
var rawString=String(rawUrl||"");
|
|
6477
6627
|
var u=new URL(String(rawUrl||""),window.location.href);
|
|
6478
6628
|
var host=(u.hostname||"").toLowerCase();
|
|
6479
6629
|
var path=(u.pathname||"").toLowerCase();
|
|
6630
|
+
var full=(u.toString()||"").toLowerCase();
|
|
6480
6631
|
var q=u.searchParams;
|
|
6481
6632
|
var hasViewportPing=q.has("vp")&&(q.has("pp_miy")||q.has("pp_may"));
|
|
6482
6633
|
var hasSessionIds=q.has("sid")||q.has("duid");
|
|
@@ -6486,11 +6637,12 @@ function shouldBlockEditorTracking(rawUrl){
|
|
|
6486
6637
|
var isTaboolaUnip=host==="trc-events.taboola.com"&&/\\/log\\/\\d+\\/unip(?:\\/|$)/.test(path);
|
|
6487
6638
|
var isCollectApiPath=path==="/api/collect"||path.indexOf("/api/collect/")===0;
|
|
6488
6639
|
var isNbCollectorPath=path==="/nb-collector"||path.indexOf("/nb-collector/")===0;
|
|
6489
|
-
|
|
6640
|
+
var hasExtraMarker=hasMarker(host,EXTRA_TRACKING_MARKERS)||hasMarker(path,EXTRA_TRACKING_MARKERS)||hasMarker(full,EXTRA_TRACKING_MARKERS)||hasMarker(rawString,EXTRA_TRACKING_MARKERS);
|
|
6641
|
+
return isCrossOriginCollector||(looksLikeHeartbeatPayload&&isSnowplowStylePath)||isCollectApiPath||isTaboolaUnip||isNbCollectorPath||hasExtraMarker;
|
|
6490
6642
|
}catch(_){
|
|
6491
6643
|
try{
|
|
6492
6644
|
var s=String(rawUrl||"").toLowerCase();
|
|
6493
|
-
return s.indexOf("snowplow")!==-1||s.indexOf("com.snowplowanalytics")!==-1||s.indexOf("collector")!==-1||s.indexOf("/api/collect")!==-1||s.indexOf("trc-events.taboola.com")!==-1||s.indexOf("/nb-collector")!==-1||s.indexOf("northbeam")!==-1;
|
|
6645
|
+
return s.indexOf("snowplow")!==-1||s.indexOf("com.snowplowanalytics")!==-1||s.indexOf("collector")!==-1||s.indexOf("/api/collect")!==-1||s.indexOf("trc-events.taboola.com")!==-1||s.indexOf("/nb-collector")!==-1||s.indexOf("northbeam")!==-1||hasMarker(s,EXTRA_TRACKING_MARKERS);
|
|
6494
6646
|
}catch(__){
|
|
6495
6647
|
return false;
|
|
6496
6648
|
}
|
package/dist/vite.js
CHANGED
|
@@ -9,22 +9,114 @@ var DEFAULT_TRACKING_MARKERS = [
|
|
|
9
9
|
"googletagmanager",
|
|
10
10
|
"google-analytics",
|
|
11
11
|
"googleads",
|
|
12
|
+
"googleadservices",
|
|
13
|
+
"googlesyndication",
|
|
12
14
|
"doubleclick",
|
|
13
15
|
"gtag(",
|
|
14
16
|
"ga(",
|
|
15
17
|
"fbq(",
|
|
16
|
-
"
|
|
18
|
+
"connect.facebook.net",
|
|
19
|
+
"clarity.ms",
|
|
17
20
|
"hotjar",
|
|
18
21
|
"segment.com",
|
|
22
|
+
"segment.io",
|
|
23
|
+
"segmentapis",
|
|
19
24
|
"mixpanel",
|
|
20
|
-
"amplitude",
|
|
25
|
+
"amplitude.com",
|
|
26
|
+
"api.amplitude",
|
|
21
27
|
"fullstory",
|
|
22
28
|
"northbeam",
|
|
23
29
|
"nb-collector",
|
|
30
|
+
"j.northbeam.io",
|
|
24
31
|
"/api/collect",
|
|
25
32
|
"/nb-collector",
|
|
26
33
|
'"r":"periodic"',
|
|
27
|
-
'"r": "periodic"'
|
|
34
|
+
'"r": "periodic"',
|
|
35
|
+
"shopify-pixel",
|
|
36
|
+
"config-security.com",
|
|
37
|
+
"heap.io",
|
|
38
|
+
"heapanalytics",
|
|
39
|
+
"posthog",
|
|
40
|
+
"matomo",
|
|
41
|
+
"piwik",
|
|
42
|
+
"plausible.io",
|
|
43
|
+
"umami",
|
|
44
|
+
"statcounter",
|
|
45
|
+
"kissmetrics",
|
|
46
|
+
"pendo.io",
|
|
47
|
+
"mouseflow",
|
|
48
|
+
"quantserve",
|
|
49
|
+
"quantcast",
|
|
50
|
+
"chartbeat",
|
|
51
|
+
"parse.ly",
|
|
52
|
+
"parsely",
|
|
53
|
+
"optimizely",
|
|
54
|
+
"logrocket",
|
|
55
|
+
"smartlook",
|
|
56
|
+
"inspectlet",
|
|
57
|
+
"crazyegg",
|
|
58
|
+
"lucky-orange",
|
|
59
|
+
"luckyorange",
|
|
60
|
+
"vwo.com",
|
|
61
|
+
"contentsquare",
|
|
62
|
+
"decibel",
|
|
63
|
+
"medallia",
|
|
64
|
+
"bat.bing.com",
|
|
65
|
+
"bing.com/action",
|
|
66
|
+
"analytics.tiktok.com",
|
|
67
|
+
"tiktok-pixel",
|
|
68
|
+
"snap.licdn.com",
|
|
69
|
+
"/li/track",
|
|
70
|
+
"ads-twitter.com",
|
|
71
|
+
"static.ads-twitter",
|
|
72
|
+
"pinimg.com",
|
|
73
|
+
"pinterest-tag",
|
|
74
|
+
"reddit.com/api/v2/conversions",
|
|
75
|
+
"redditstatic",
|
|
76
|
+
"criteo",
|
|
77
|
+
"adroll",
|
|
78
|
+
"outbrain",
|
|
79
|
+
"amazon-adsystem",
|
|
80
|
+
"adsystem.amazon",
|
|
81
|
+
"q.quora.com",
|
|
82
|
+
"quora-pixel",
|
|
83
|
+
"tealium",
|
|
84
|
+
"rudderstack",
|
|
85
|
+
"mparticle",
|
|
86
|
+
"freshpaint",
|
|
87
|
+
"jitsu",
|
|
88
|
+
"customer.io",
|
|
89
|
+
"hs-analytics",
|
|
90
|
+
"hsforms",
|
|
91
|
+
"hubspot",
|
|
92
|
+
"marketo",
|
|
93
|
+
"munchkin",
|
|
94
|
+
"pardot",
|
|
95
|
+
"intercom",
|
|
96
|
+
"drift",
|
|
97
|
+
"klaviyo",
|
|
98
|
+
"omnisend",
|
|
99
|
+
"attentive",
|
|
100
|
+
"sentry",
|
|
101
|
+
"bugsnag",
|
|
102
|
+
"datadog",
|
|
103
|
+
"dd-rum",
|
|
104
|
+
"browser-intake-datadoghq",
|
|
105
|
+
"newrelic",
|
|
106
|
+
"nr-data",
|
|
107
|
+
"rollbar",
|
|
108
|
+
"cloudflareinsights",
|
|
109
|
+
"vercel-insights",
|
|
110
|
+
"_vercel/insights",
|
|
111
|
+
"vercel-speed-insights",
|
|
112
|
+
"plausible",
|
|
113
|
+
"usermaven",
|
|
114
|
+
"freshmarketer",
|
|
115
|
+
"mc.yandex",
|
|
116
|
+
"yandex.ru/metrika",
|
|
117
|
+
"hm.baidu.com",
|
|
118
|
+
"getclicky",
|
|
119
|
+
"clicky.com"
|
|
28
120
|
];
|
|
29
121
|
function normalizeTrackingMarkers(input) {
|
|
30
122
|
if (!Array.isArray(input)) return [];
|
|
@@ -59,8 +151,17 @@ function parseTrackingMarkersParam(raw) {
|
|
|
59
151
|
}
|
|
60
152
|
function hasTrackingMarker(input, markers) {
|
|
61
153
|
const text = String(input || "").toLowerCase();
|
|
154
|
+
const compactText = text.replace(/[^a-z0-9]/g, "");
|
|
62
155
|
for (let i = 0; i < markers.length; i += 1) {
|
|
63
|
-
|
|
156
|
+
const marker = String(markers[i] || "").toLowerCase().trim();
|
|
157
|
+
if (!marker) continue;
|
|
158
|
+
if (text.includes(marker)) return true;
|
|
159
|
+
const markerNoProto = marker.replace(/^https?:\/\//, "");
|
|
160
|
+
const markerNoWww = markerNoProto.replace(/^www\./, "");
|
|
161
|
+
const compactMarker = markerNoWww.replace(/[^a-z0-9]/g, "");
|
|
162
|
+
if (markerNoProto && text.includes(markerNoProto)) return true;
|
|
163
|
+
if (markerNoWww && text.includes(markerNoWww)) return true;
|
|
164
|
+
if (compactMarker && compactText.includes(compactMarker)) return true;
|
|
64
165
|
}
|
|
65
166
|
return false;
|
|
66
167
|
}
|
|
@@ -72,8 +173,30 @@ function patchKnownUnsafeEditorPatterns(scriptTag) {
|
|
|
72
173
|
);
|
|
73
174
|
return out;
|
|
74
175
|
}
|
|
176
|
+
function escapeHtmlAttribute(value) {
|
|
177
|
+
return String(value || "").replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
178
|
+
}
|
|
179
|
+
function getFirstMatchedTrackingMarker(input, markers) {
|
|
180
|
+
const text = String(input || "").toLowerCase();
|
|
181
|
+
for (let i = 0; i < markers.length; i += 1) {
|
|
182
|
+
if (text.includes(markers[i])) return markers[i];
|
|
183
|
+
}
|
|
184
|
+
return "";
|
|
185
|
+
}
|
|
186
|
+
function describeRemovedTrackingTag(tag, markers) {
|
|
187
|
+
const srcMatch = String(tag || "").match(/\bsrc\s*=\s*(["'])(.*?)\1/i);
|
|
188
|
+
const src = srcMatch?.[2]?.trim();
|
|
189
|
+
if (src) return `script:${src}`;
|
|
190
|
+
const idMatch = String(tag || "").match(/\bid\s*=\s*(["'])(.*?)\1/i);
|
|
191
|
+
const id = idMatch?.[2]?.trim();
|
|
192
|
+
if (id) return `tag#${id}`;
|
|
193
|
+
const marker = getFirstMatchedTrackingMarker(tag, markers);
|
|
194
|
+
if (marker) return `marker:${marker}`;
|
|
195
|
+
return "inline-script";
|
|
196
|
+
}
|
|
75
197
|
function stripTrackingScriptsFromScrapedHtml(html, markers) {
|
|
76
198
|
let removedCount = 0;
|
|
199
|
+
const removedScripts = [];
|
|
77
200
|
let out = html;
|
|
78
201
|
out = out.replace(/<script\b[\s\S]*?<\/script>/gi, (tag) => {
|
|
79
202
|
var patchedTag = patchKnownUnsafeEditorPatterns(tag);
|
|
@@ -81,6 +204,9 @@ function stripTrackingScriptsFromScrapedHtml(html, markers) {
|
|
|
81
204
|
const src = srcMatch?.[2] || "";
|
|
82
205
|
if (hasTrackingMarker(src, markers) || hasTrackingMarker(tag, markers)) {
|
|
83
206
|
removedCount += 1;
|
|
207
|
+
if (removedScripts.length < 25) {
|
|
208
|
+
removedScripts.push(describeRemovedTrackingTag(tag, markers).slice(0, 240));
|
|
209
|
+
}
|
|
84
210
|
return "";
|
|
85
211
|
}
|
|
86
212
|
return patchedTag;
|
|
@@ -88,13 +214,18 @@ function stripTrackingScriptsFromScrapedHtml(html, markers) {
|
|
|
88
214
|
out = out.replace(/<noscript\b[\s\S]*?<\/noscript>/gi, (tag) => {
|
|
89
215
|
if (!hasTrackingMarker(tag, markers)) return tag;
|
|
90
216
|
removedCount += 1;
|
|
217
|
+
if (removedScripts.length < 25) {
|
|
218
|
+
const marker = getFirstMatchedTrackingMarker(tag, markers);
|
|
219
|
+
removedScripts.push(`noscript:${(marker || "tracking").slice(0, 240)}`);
|
|
220
|
+
}
|
|
91
221
|
return "";
|
|
92
222
|
});
|
|
93
223
|
if (removedCount > 0) {
|
|
224
|
+
const dataScriptsValue = removedScripts.length ? ` data-scripts="${escapeHtmlAttribute(removedScripts.join(" | "))}"` : "";
|
|
94
225
|
out = out.replace(
|
|
95
226
|
/<head([^>]*)>/i,
|
|
96
227
|
`<head$1>
|
|
97
|
-
<meta name="conversion-editor-tracking-scripts-stripped" content="${removedCount}">
|
|
228
|
+
<meta name="conversion-editor-tracking-scripts-stripped" content="${removedCount}"${dataScriptsValue}>
|
|
98
229
|
`
|
|
99
230
|
);
|
|
100
231
|
}
|
|
@@ -1369,15 +1500,29 @@ function showEditorNotification(message, kind, durationMs) {
|
|
|
1369
1500
|
}, Math.max(1200, durationMs || 2600));
|
|
1370
1501
|
}
|
|
1371
1502
|
|
|
1503
|
+
function resolveSimulationId(source, keys) {
|
|
1504
|
+
var obj = source || {};
|
|
1505
|
+
var arr = Array.isArray(keys) ? keys : [];
|
|
1506
|
+
for (var i = 0; i < arr.length; i++) {
|
|
1507
|
+
var key = arr[i];
|
|
1508
|
+
var value = obj[key];
|
|
1509
|
+
if (value === undefined || value === null) continue;
|
|
1510
|
+
// Preserve numeric ids (including 0), but reject empty-string ids.
|
|
1511
|
+
if (typeof value === 'string' && value.trim() === '') continue;
|
|
1512
|
+
return value;
|
|
1513
|
+
}
|
|
1514
|
+
return null;
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1372
1517
|
function generatePreviewUrlString(args) {
|
|
1373
1518
|
var baseUrl = (args && args.url) || '';
|
|
1374
1519
|
var test = (args && args.test) || {};
|
|
1375
1520
|
var variation = (args && args.variation) || {};
|
|
1376
1521
|
if (!baseUrl) return '';
|
|
1377
|
-
var testId = test
|
|
1378
|
-
var variationId = variation
|
|
1379
|
-
if (
|
|
1380
|
-
var cId = String(testId
|
|
1522
|
+
var testId = resolveSimulationId(test, ['iid', 'experimentIid', 'experimentId', '_id', 'id']);
|
|
1523
|
+
var variationId = resolveSimulationId(variation, ['iid', 'platformIid', 'variationIid', '_id', 'id']);
|
|
1524
|
+
if (testId === null || variationId === null) return '';
|
|
1525
|
+
var cId = String(testId) + '_' + String(variationId);
|
|
1381
1526
|
var hasQueryParams = String(baseUrl).indexOf('?') >= 0;
|
|
1382
1527
|
return (
|
|
1383
1528
|
baseUrl +
|
|
@@ -1400,8 +1545,10 @@ function simulateExperiment() {
|
|
|
1400
1545
|
test.pageUrl ||
|
|
1401
1546
|
(test.metadata_1 && test.metadata_1.editor_url) ||
|
|
1402
1547
|
'';
|
|
1403
|
-
|
|
1404
|
-
|
|
1548
|
+
var testId = resolveSimulationId(test, ['iid', 'experimentIid', 'experimentId', '_id', 'id']);
|
|
1549
|
+
var variationId = resolveSimulationId(activeVariation, ['iid', 'platformIid', 'variationIid', '_id', 'id']);
|
|
1550
|
+
if (testId === null || !activeVariation || variationId === null) {
|
|
1551
|
+
showEditorNotification('Cannot simulate: missing test/variation id.', 'error', 3200);
|
|
1405
1552
|
return;
|
|
1406
1553
|
}
|
|
1407
1554
|
var url = generatePreviewUrlString({
|
|
@@ -6235,6 +6382,7 @@ function createVisualEditorMiddleware(options) {
|
|
|
6235
6382
|
const trackingMarkersForRequest = mergeTrackingMarkers(
|
|
6236
6383
|
extraTrackingMarkersForRequest
|
|
6237
6384
|
);
|
|
6385
|
+
console.log("trackingMarkersForRequest", trackingMarkersForRequest);
|
|
6238
6386
|
const strictFreezeParam = (url.searchParams.get("strictObserverFreeze") || "").toLowerCase();
|
|
6239
6387
|
const strictObserverFreezeForRequest = strictFreezeParam === "1" || strictFreezeParam === "true" || strictFreezeParam === "yes" ? true : strictFreezeParam === "0" || strictFreezeParam === "false" || strictFreezeParam === "no" ? false : strictObserverFreeze;
|
|
6240
6388
|
if (!targetUrl) {
|
|
@@ -6426,6 +6574,7 @@ var TARGET_PAGE_URL=${JSON.stringify(targetUrl)};
|
|
|
6426
6574
|
var PROXY_PASSWORD=${JSON.stringify(password)};
|
|
6427
6575
|
var PROXY_BASE_URL="";
|
|
6428
6576
|
var STRICT_OBSERVER_FREEZE=${JSON.stringify(strictObserverFreezeForRequest)};
|
|
6577
|
+
var EXTRA_TRACKING_MARKERS=${JSON.stringify(trackingMarkersForRequest)};
|
|
6429
6578
|
var PARENT_URL_CHANNEL="vvveb-proxy-url";
|
|
6430
6579
|
window.__CONVERSION_EDITOR_ACTIVE__=true;
|
|
6431
6580
|
window.__EDITOR_MODE__=true;
|
|
@@ -6466,9 +6615,11 @@ function isPeriodicCollectPayload(data){
|
|
|
6466
6615
|
}
|
|
6467
6616
|
function shouldBlockEditorTracking(rawUrl){
|
|
6468
6617
|
try{
|
|
6618
|
+
var rawString=String(rawUrl||"");
|
|
6469
6619
|
var u=new URL(String(rawUrl||""),window.location.href);
|
|
6470
6620
|
var host=(u.hostname||"").toLowerCase();
|
|
6471
6621
|
var path=(u.pathname||"").toLowerCase();
|
|
6622
|
+
var full=(u.toString()||"").toLowerCase();
|
|
6472
6623
|
var q=u.searchParams;
|
|
6473
6624
|
var hasViewportPing=q.has("vp")&&(q.has("pp_miy")||q.has("pp_may"));
|
|
6474
6625
|
var hasSessionIds=q.has("sid")||q.has("duid");
|
|
@@ -6478,11 +6629,12 @@ function shouldBlockEditorTracking(rawUrl){
|
|
|
6478
6629
|
var isTaboolaUnip=host==="trc-events.taboola.com"&&/\\/log\\/\\d+\\/unip(?:\\/|$)/.test(path);
|
|
6479
6630
|
var isCollectApiPath=path==="/api/collect"||path.indexOf("/api/collect/")===0;
|
|
6480
6631
|
var isNbCollectorPath=path==="/nb-collector"||path.indexOf("/nb-collector/")===0;
|
|
6481
|
-
|
|
6632
|
+
var hasExtraMarker=hasMarker(host,EXTRA_TRACKING_MARKERS)||hasMarker(path,EXTRA_TRACKING_MARKERS)||hasMarker(full,EXTRA_TRACKING_MARKERS)||hasMarker(rawString,EXTRA_TRACKING_MARKERS);
|
|
6633
|
+
return isCrossOriginCollector||(looksLikeHeartbeatPayload&&isSnowplowStylePath)||isCollectApiPath||isTaboolaUnip||isNbCollectorPath||hasExtraMarker;
|
|
6482
6634
|
}catch(_){
|
|
6483
6635
|
try{
|
|
6484
6636
|
var s=String(rawUrl||"").toLowerCase();
|
|
6485
|
-
return s.indexOf("snowplow")!==-1||s.indexOf("com.snowplowanalytics")!==-1||s.indexOf("collector")!==-1||s.indexOf("/api/collect")!==-1||s.indexOf("trc-events.taboola.com")!==-1||s.indexOf("/nb-collector")!==-1||s.indexOf("northbeam")!==-1;
|
|
6637
|
+
return s.indexOf("snowplow")!==-1||s.indexOf("com.snowplowanalytics")!==-1||s.indexOf("collector")!==-1||s.indexOf("/api/collect")!==-1||s.indexOf("trc-events.taboola.com")!==-1||s.indexOf("/nb-collector")!==-1||s.indexOf("northbeam")!==-1||hasMarker(s,EXTRA_TRACKING_MARKERS);
|
|
6486
6638
|
}catch(__){
|
|
6487
6639
|
return false;
|
|
6488
6640
|
}
|