@magicfeedback/popup-sdk 1.0.9 → 1.0.11
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 +19 -16
- package/dist/index.d.mts +20 -13
- package/dist/index.d.ts +20 -13
- package/dist/index.js +300 -50
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +300 -50
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1787,7 +1787,7 @@ function ensureResponsiveStyles(popup) {
|
|
|
1787
1787
|
`;
|
|
1788
1788
|
popup.appendChild(style);
|
|
1789
1789
|
}
|
|
1790
|
-
async function renderPopup(container, surveyId, productId, actions, emit, onClose) {
|
|
1790
|
+
async function renderPopup(container, surveyId, productId, actions, emit, onClose, env = "production") {
|
|
1791
1791
|
let surveyCompletedEmitted = false;
|
|
1792
1792
|
let stylesInjected = false;
|
|
1793
1793
|
const popup = document.createElement("div");
|
|
@@ -1812,7 +1812,7 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
|
|
|
1812
1812
|
closeBtn.type = "button";
|
|
1813
1813
|
closeBtn.setAttribute("aria-label", "Close popup");
|
|
1814
1814
|
closeBtn.innerHTML = `
|
|
1815
|
-
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"
|
|
1815
|
+
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
1816
1816
|
<path d="M6 6L18 18M6 18L18 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
1817
1817
|
</svg>
|
|
1818
1818
|
`;
|
|
@@ -1863,6 +1863,20 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
|
|
|
1863
1863
|
main.style.cssText = "display:flex; flex-direction:column; width:100%; max-height:80vh; overflow-y:auto;";
|
|
1864
1864
|
const formWrapper = document.createElement("div");
|
|
1865
1865
|
formWrapper.style.cssText = "width:100%; flex: 1 1 auto;";
|
|
1866
|
+
const errorHint = document.createElement("div");
|
|
1867
|
+
errorHint.className = "deepdots-error-hint";
|
|
1868
|
+
errorHint.style.cssText = `
|
|
1869
|
+
display: none;
|
|
1870
|
+
margin: 12px 0 0 0;
|
|
1871
|
+
padding: 10px 12px;
|
|
1872
|
+
border-radius: 6px;
|
|
1873
|
+
background: #FEF3C7; /* amber-100 */
|
|
1874
|
+
color: #92400E; /* amber-700 */
|
|
1875
|
+
border: 1px solid #FCD34D; /* amber-300 */
|
|
1876
|
+
font-size: 13px;
|
|
1877
|
+
`;
|
|
1878
|
+
errorHint.setAttribute("role", "alert");
|
|
1879
|
+
errorHint.setAttribute("aria-live", "polite");
|
|
1866
1880
|
const spinnerEl = document.createElement("div");
|
|
1867
1881
|
spinnerEl.className = "mf-spinner";
|
|
1868
1882
|
spinnerEl.setAttribute("role", "status");
|
|
@@ -1876,6 +1890,7 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
|
|
|
1876
1890
|
formWrapper.appendChild(spinnerEl);
|
|
1877
1891
|
formWrapper.appendChild(formHost);
|
|
1878
1892
|
main.appendChild(formWrapper);
|
|
1893
|
+
main.appendChild(errorHint);
|
|
1879
1894
|
const footer = document.createElement("div");
|
|
1880
1895
|
footer.className = "deepdots-popup-footer";
|
|
1881
1896
|
footer.setAttribute("data-actions-wrapper", "true");
|
|
@@ -2020,7 +2035,6 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
|
|
|
2020
2035
|
setLoading(false);
|
|
2021
2036
|
break;
|
|
2022
2037
|
case "error":
|
|
2023
|
-
closeButton.style.display = "inline-flex";
|
|
2024
2038
|
setLoading(false);
|
|
2025
2039
|
break;
|
|
2026
2040
|
}
|
|
@@ -2057,13 +2071,13 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
|
|
|
2057
2071
|
setLoading(false);
|
|
2058
2072
|
return;
|
|
2059
2073
|
}
|
|
2060
|
-
import_native.default.init({ debug: true, env: "prod" });
|
|
2074
|
+
import_native.default.init({ debug: true, env: env === "production" ? "prod" : "dev" });
|
|
2061
2075
|
formInstance = import_native.default.form(surveyId, productId);
|
|
2062
2076
|
const generateOptions = {
|
|
2063
2077
|
addButton: false,
|
|
2064
2078
|
getMetaData: true
|
|
2065
2079
|
};
|
|
2066
|
-
generateOptions.onLoadedEvent = ({ formData
|
|
2080
|
+
generateOptions.onLoadedEvent = ({ formData }) => {
|
|
2067
2081
|
try {
|
|
2068
2082
|
} catch (e) {
|
|
2069
2083
|
}
|
|
@@ -2149,11 +2163,23 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
|
|
|
2149
2163
|
emit("popup_clicked", surveyId, { action: "before_submit" });
|
|
2150
2164
|
};
|
|
2151
2165
|
generateOptions.afterSubmitEvent = ({ error, completed, total, progress }) => {
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2166
|
+
const errText = error ? typeof error === "string" ? error : error.message ?? String(error) : "";
|
|
2167
|
+
if (errText) {
|
|
2168
|
+
setLoading(false);
|
|
2169
|
+
if (errText.toLowerCase().includes("no response")) {
|
|
2170
|
+
errorHint.textContent = "Please answer the required question to continue.";
|
|
2171
|
+
errorHint.style.display = "block";
|
|
2172
|
+
emit("popup_clicked", surveyId, { action: "validation_error_required" });
|
|
2173
|
+
updateButtons("in_progress_next");
|
|
2174
|
+
return;
|
|
2175
|
+
}
|
|
2176
|
+
errorHint.textContent = "An error occurred while submitting. Please try again or close the popup.";
|
|
2177
|
+
errorHint.style.display = "block";
|
|
2178
|
+
emit("popup_clicked", surveyId, { action: "submit_error", error: errText });
|
|
2155
2179
|
return;
|
|
2156
2180
|
}
|
|
2181
|
+
errorHint.style.display = "none";
|
|
2182
|
+
setLoading(false);
|
|
2157
2183
|
if (completed) {
|
|
2158
2184
|
emit("survey_completed", surveyId, { action: "completed" });
|
|
2159
2185
|
surveyCompletedEmitted = true;
|
|
@@ -2196,6 +2222,9 @@ function setupTrigger(popups, trigger) {
|
|
|
2196
2222
|
case "exit":
|
|
2197
2223
|
setupExitTrigger(popups, trigger);
|
|
2198
2224
|
break;
|
|
2225
|
+
case "click":
|
|
2226
|
+
setupClickTrigger(popups, trigger);
|
|
2227
|
+
break;
|
|
2199
2228
|
}
|
|
2200
2229
|
}
|
|
2201
2230
|
function setupTimeTrigger(popups, trigger) {
|
|
@@ -2218,23 +2247,120 @@ function setupScrollTrigger(popups, trigger) {
|
|
|
2218
2247
|
popups.debug(`Scroll trigger set for ${threshold}%`);
|
|
2219
2248
|
}
|
|
2220
2249
|
function setupExitTrigger(popups, trigger) {
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2250
|
+
let fired = false;
|
|
2251
|
+
let lastUrl = typeof window !== "undefined" ? window.location.href : "";
|
|
2252
|
+
const historyRef = typeof window !== "undefined" ? window.history : null;
|
|
2253
|
+
const originalPushState = historyRef ? historyRef.pushState.bind(historyRef) : null;
|
|
2254
|
+
const originalReplaceState = historyRef ? historyRef.replaceState.bind(historyRef) : null;
|
|
2255
|
+
const cleanup = () => {
|
|
2256
|
+
document.removeEventListener("click", handleNavClick, true);
|
|
2257
|
+
window.removeEventListener("popstate", handlePopState);
|
|
2258
|
+
if (historyRef && originalPushState) historyRef.pushState = originalPushState;
|
|
2259
|
+
if (historyRef && originalReplaceState) historyRef.replaceState = originalReplaceState;
|
|
2260
|
+
};
|
|
2261
|
+
const fireOnce = () => {
|
|
2262
|
+
if (fired) return;
|
|
2263
|
+
fired = true;
|
|
2264
|
+
popups.triggerSurvey(trigger.surveyId);
|
|
2265
|
+
cleanup();
|
|
2266
|
+
};
|
|
2267
|
+
const handleNavClick = (e) => {
|
|
2268
|
+
if (fired) return;
|
|
2269
|
+
if (e.defaultPrevented) return;
|
|
2270
|
+
if (e.button !== 0) return;
|
|
2271
|
+
if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
|
|
2272
|
+
const target = e.target?.closest?.("a");
|
|
2273
|
+
if (!target) return;
|
|
2274
|
+
const href = target.getAttribute("href");
|
|
2275
|
+
if (!href || href.startsWith("#")) return;
|
|
2276
|
+
const targetAttr = target.getAttribute("target");
|
|
2277
|
+
if (targetAttr && targetAttr !== "_self") return;
|
|
2278
|
+
let url;
|
|
2279
|
+
try {
|
|
2280
|
+
url = new URL(href, window.location.href);
|
|
2281
|
+
} catch {
|
|
2282
|
+
return;
|
|
2283
|
+
}
|
|
2284
|
+
if (url.origin !== window.location.origin) return;
|
|
2285
|
+
e.preventDefault();
|
|
2286
|
+
fireOnce();
|
|
2287
|
+
};
|
|
2288
|
+
const shouldBlockUrl = (rawUrl) => {
|
|
2289
|
+
if (!rawUrl) return false;
|
|
2290
|
+
let url;
|
|
2291
|
+
try {
|
|
2292
|
+
url = rawUrl instanceof URL ? rawUrl : new URL(rawUrl, window.location.href);
|
|
2293
|
+
} catch {
|
|
2294
|
+
return false;
|
|
2295
|
+
}
|
|
2296
|
+
if (url.origin !== window.location.origin) return false;
|
|
2297
|
+
if (url.href === window.location.href) return false;
|
|
2298
|
+
return true;
|
|
2299
|
+
};
|
|
2300
|
+
const handlePopState = () => {
|
|
2301
|
+
if (fired) return;
|
|
2302
|
+
fireOnce();
|
|
2303
|
+
if (historyRef && originalPushState && lastUrl) {
|
|
2304
|
+
originalPushState(null, document.title, lastUrl);
|
|
2225
2305
|
}
|
|
2226
2306
|
};
|
|
2227
|
-
|
|
2228
|
-
|
|
2307
|
+
if (historyRef && originalPushState && originalReplaceState) {
|
|
2308
|
+
historyRef.pushState = function(data, unused, url) {
|
|
2309
|
+
if (!fired && shouldBlockUrl(url)) {
|
|
2310
|
+
fireOnce();
|
|
2311
|
+
return;
|
|
2312
|
+
}
|
|
2313
|
+
const result = originalPushState(data, unused, url);
|
|
2314
|
+
lastUrl = window.location.href;
|
|
2315
|
+
return result;
|
|
2316
|
+
};
|
|
2317
|
+
historyRef.replaceState = function(data, unused, url) {
|
|
2318
|
+
if (!fired && shouldBlockUrl(url)) {
|
|
2319
|
+
fireOnce();
|
|
2320
|
+
return;
|
|
2321
|
+
}
|
|
2322
|
+
const result = originalReplaceState(data, unused, url);
|
|
2323
|
+
lastUrl = window.location.href;
|
|
2324
|
+
return result;
|
|
2325
|
+
};
|
|
2326
|
+
}
|
|
2327
|
+
document.addEventListener("click", handleNavClick, true);
|
|
2328
|
+
window.addEventListener("popstate", handlePopState);
|
|
2329
|
+
popups.debug("Exit intent trigger set (navigation/spa)");
|
|
2330
|
+
}
|
|
2331
|
+
function setupClickTrigger(popups, trigger) {
|
|
2332
|
+
const targetId = typeof trigger.value === "string" ? trigger.value : "";
|
|
2333
|
+
if (!targetId) {
|
|
2334
|
+
popups.debug("Click trigger missing element id", trigger);
|
|
2335
|
+
return;
|
|
2336
|
+
}
|
|
2337
|
+
const attach = () => {
|
|
2338
|
+
const el = document.getElementById(targetId);
|
|
2339
|
+
if (!el) {
|
|
2340
|
+
popups.debug("Click trigger target not found", targetId);
|
|
2341
|
+
return false;
|
|
2342
|
+
}
|
|
2343
|
+
const handler = (e) => {
|
|
2344
|
+
if (e.defaultPrevented) return;
|
|
2345
|
+
popups.triggerSurvey(trigger.surveyId);
|
|
2346
|
+
el.removeEventListener("click", handler);
|
|
2347
|
+
};
|
|
2348
|
+
el.addEventListener("click", handler);
|
|
2349
|
+
popups.debug(`Click trigger set for #${targetId}`);
|
|
2350
|
+
return true;
|
|
2351
|
+
};
|
|
2352
|
+
if (typeof document === "undefined") return;
|
|
2353
|
+
if (attach()) return;
|
|
2354
|
+
window.addEventListener("DOMContentLoaded", () => attach(), { once: true });
|
|
2229
2355
|
}
|
|
2230
2356
|
|
|
2231
2357
|
// src/config/env.ts
|
|
2232
2358
|
var ENVIRONMENT_MAP = {
|
|
2233
2359
|
development: {
|
|
2234
|
-
apiBaseUrl: "https://api-dev.
|
|
2360
|
+
apiBaseUrl: "https://api-dev.deepdots.com"
|
|
2235
2361
|
},
|
|
2236
2362
|
production: {
|
|
2237
|
-
apiBaseUrl: "https://api.
|
|
2363
|
+
apiBaseUrl: "https://api.deepdots.com"
|
|
2238
2364
|
}
|
|
2239
2365
|
};
|
|
2240
2366
|
function resolveEnvironment(nodeEnv) {
|
|
@@ -2316,10 +2442,10 @@ var BrowserPopupRenderer = class {
|
|
|
2316
2442
|
document.body.appendChild(this.container);
|
|
2317
2443
|
}
|
|
2318
2444
|
}
|
|
2319
|
-
show(surveyId, productId, actions, emit, onClose) {
|
|
2445
|
+
show(surveyId, productId, actions, emit, onClose, env = "production") {
|
|
2320
2446
|
if (!this.container) this.init();
|
|
2321
2447
|
if (!this.container) return;
|
|
2322
|
-
renderPopup(this.container, surveyId, productId, actions, emit, onClose);
|
|
2448
|
+
renderPopup(this.container, surveyId, productId, actions, emit, onClose, env);
|
|
2323
2449
|
}
|
|
2324
2450
|
hide() {
|
|
2325
2451
|
if (this.container) {
|
|
@@ -2352,8 +2478,12 @@ var DeepdotsPopups = class {
|
|
|
2352
2478
|
this.pendingAutoLaunch = false;
|
|
2353
2479
|
this.answeredSurveys = /* @__PURE__ */ new Set();
|
|
2354
2480
|
this.lastShown = /* @__PURE__ */ new Map();
|
|
2481
|
+
// popupId -> timestamp mostrado
|
|
2482
|
+
this.surveyToPopupId = /* @__PURE__ */ new Map();
|
|
2483
|
+
// surveyId -> popupId
|
|
2484
|
+
this.baseUrl = "";
|
|
2485
|
+
this.env = "production";
|
|
2355
2486
|
}
|
|
2356
|
-
// popupId -> timestamp mostrado
|
|
2357
2487
|
/** Initialize the SDK with configuration */
|
|
2358
2488
|
init(config) {
|
|
2359
2489
|
if (this.initialized) {
|
|
@@ -2361,12 +2491,14 @@ var DeepdotsPopups = class {
|
|
|
2361
2491
|
return;
|
|
2362
2492
|
}
|
|
2363
2493
|
const env = resolveEnvironment(config.nodeEnv);
|
|
2494
|
+
this.baseUrl = env.apiBaseUrl;
|
|
2495
|
+
this.env = config.nodeEnv || "production";
|
|
2364
2496
|
this.config = {
|
|
2365
2497
|
apiKey: config.apiKey || void 0,
|
|
2366
|
-
baseUrl: env.apiBaseUrl,
|
|
2367
2498
|
mode: config.mode || "client",
|
|
2368
2499
|
debug: config.debug || false,
|
|
2369
|
-
popups: config.popups || []
|
|
2500
|
+
popups: config.popups || [],
|
|
2501
|
+
userId: config.userId || void 0
|
|
2370
2502
|
};
|
|
2371
2503
|
this.initialized = true;
|
|
2372
2504
|
this.log("SDK initialized", this.config);
|
|
@@ -2415,8 +2547,9 @@ var DeepdotsPopups = class {
|
|
|
2415
2547
|
if (isDefinition) {
|
|
2416
2548
|
const def = options;
|
|
2417
2549
|
this.log("Showing popup (definition)", def);
|
|
2550
|
+
this.surveyToPopupId.set(def.surveyId, def.id);
|
|
2418
2551
|
this.renderPopup(def.surveyId, def.productId, def.actions);
|
|
2419
|
-
this.emitEvent("popup_shown", def.surveyId);
|
|
2552
|
+
this.emitEvent("popup_shown", def.surveyId, { popupId: def.id });
|
|
2420
2553
|
} else {
|
|
2421
2554
|
const opt = options;
|
|
2422
2555
|
this.log("Showing popup (legacy options)", opt);
|
|
@@ -2445,9 +2578,10 @@ var DeepdotsPopups = class {
|
|
|
2445
2578
|
configureTriggersFromDefinitions() {
|
|
2446
2579
|
const derived = [];
|
|
2447
2580
|
const validDefs = this.validatePopupDefinitions(this.popupDefinitions);
|
|
2581
|
+
console.log("validDefs", validDefs);
|
|
2448
2582
|
validDefs.forEach((def) => {
|
|
2449
|
-
if (!def.
|
|
2450
|
-
const t = def.
|
|
2583
|
+
if (!def.triggers) return;
|
|
2584
|
+
const t = def.triggers;
|
|
2451
2585
|
let type;
|
|
2452
2586
|
switch (t.type) {
|
|
2453
2587
|
case "time_on_page":
|
|
@@ -2459,11 +2593,14 @@ var DeepdotsPopups = class {
|
|
|
2459
2593
|
case "exit":
|
|
2460
2594
|
type = "exit";
|
|
2461
2595
|
break;
|
|
2596
|
+
case "click":
|
|
2597
|
+
type = "click";
|
|
2598
|
+
break;
|
|
2462
2599
|
default:
|
|
2463
2600
|
this.debug("Unsupported trigger type", t.type);
|
|
2464
2601
|
return;
|
|
2465
2602
|
}
|
|
2466
|
-
const value = type === "time" ? t.value * 1e3 : t.value;
|
|
2603
|
+
const value = type === "time" && typeof t.value === "number" ? t.value * 1e3 : t.value;
|
|
2467
2604
|
derived.push({ type, value, surveyId: def.surveyId });
|
|
2468
2605
|
});
|
|
2469
2606
|
if (derived.length) {
|
|
@@ -2485,10 +2622,52 @@ var DeepdotsPopups = class {
|
|
|
2485
2622
|
this.lastShown.set(def.id, Date.now());
|
|
2486
2623
|
}
|
|
2487
2624
|
shouldShow(def) {
|
|
2488
|
-
|
|
2625
|
+
if (!this.matchesSegmentsPath(def)) {
|
|
2626
|
+
return false;
|
|
2627
|
+
}
|
|
2628
|
+
const conditions = def.triggers.condition || [];
|
|
2489
2629
|
if (!conditions.length) return true;
|
|
2490
2630
|
return conditions.every((c) => this.evaluateCondition(def, c));
|
|
2491
2631
|
}
|
|
2632
|
+
matchesSegmentsPath(def) {
|
|
2633
|
+
const paths = def.segments?.path;
|
|
2634
|
+
if (!paths || paths.length === 0) return true;
|
|
2635
|
+
if (typeof window === "undefined" || !window.location) {
|
|
2636
|
+
this.debug("No window.location available for path comparison", { popupId: def.id, paths });
|
|
2637
|
+
return true;
|
|
2638
|
+
}
|
|
2639
|
+
const currentPath = window.location.pathname || "";
|
|
2640
|
+
const currentHref = window.location.href || "";
|
|
2641
|
+
const normalize = (value) => {
|
|
2642
|
+
if (value.length > 1 && value.endsWith("/")) return value.slice(0, -1);
|
|
2643
|
+
return value;
|
|
2644
|
+
};
|
|
2645
|
+
const normalizedPath = normalize(currentPath);
|
|
2646
|
+
const normalizedHref = normalize(currentHref);
|
|
2647
|
+
const matches = paths.some((rawCandidate) => {
|
|
2648
|
+
const candidate = normalize(rawCandidate);
|
|
2649
|
+
let match = false;
|
|
2650
|
+
if (candidate.startsWith("http://") || candidate.startsWith("https://")) {
|
|
2651
|
+
match = normalizedHref === candidate;
|
|
2652
|
+
} else if (candidate.startsWith("/")) {
|
|
2653
|
+
match = normalizedHref.includes(candidate);
|
|
2654
|
+
} else {
|
|
2655
|
+
match = normalizedPath === candidate;
|
|
2656
|
+
}
|
|
2657
|
+
this.debug("Path comparison", {
|
|
2658
|
+
popupId: def.id,
|
|
2659
|
+
candidate,
|
|
2660
|
+
currentPath: normalizedPath,
|
|
2661
|
+
currentHref: normalizedHref,
|
|
2662
|
+
match
|
|
2663
|
+
});
|
|
2664
|
+
return match;
|
|
2665
|
+
});
|
|
2666
|
+
if (!matches) {
|
|
2667
|
+
this.debug("No path match for popup", { popupId: def.id, paths, currentPath: normalizedPath });
|
|
2668
|
+
}
|
|
2669
|
+
return matches;
|
|
2670
|
+
}
|
|
2492
2671
|
evaluateCondition(def, condition) {
|
|
2493
2672
|
if (!condition.answered && this.answeredSurveys.has(def.surveyId)) {
|
|
2494
2673
|
return false;
|
|
@@ -2507,29 +2686,59 @@ var DeepdotsPopups = class {
|
|
|
2507
2686
|
markSurveyAnswered(surveyId) {
|
|
2508
2687
|
this.answeredSurveys.add(surveyId);
|
|
2509
2688
|
}
|
|
2510
|
-
/**
|
|
2689
|
+
/** Fetch al servidor para obtener popups */
|
|
2511
2690
|
async fetchPopupsFromServer() {
|
|
2512
|
-
|
|
2513
|
-
|
|
2691
|
+
const apiKey = this.config?.apiKey;
|
|
2692
|
+
const baseUrl = this.baseUrl;
|
|
2693
|
+
if (!apiKey || !baseUrl) {
|
|
2694
|
+
this.log("Missing apiKey or baseUrl. Skipping popups fetch.");
|
|
2695
|
+
return [];
|
|
2696
|
+
}
|
|
2697
|
+
const endpoint = `${baseUrl}/sdk/${encodeURIComponent(apiKey)}/popups`;
|
|
2698
|
+
try {
|
|
2699
|
+
const response = await fetch(endpoint);
|
|
2700
|
+
if (!response.ok) {
|
|
2701
|
+
this.log("Failed to fetch popups", response.status, response.statusText);
|
|
2702
|
+
return [];
|
|
2703
|
+
}
|
|
2704
|
+
const raw = await response.text();
|
|
2705
|
+
const parsed = JSON.parse(raw);
|
|
2706
|
+
if (!Array.isArray(parsed)) {
|
|
2707
|
+
this.log("Unexpected popups payload", parsed);
|
|
2708
|
+
return [];
|
|
2709
|
+
}
|
|
2710
|
+
console.log("res: ", parsed, this.validatePopupDefinitions(parsed));
|
|
2711
|
+
return parsed;
|
|
2712
|
+
} catch (error) {
|
|
2713
|
+
this.log("Error fetching popups", error);
|
|
2714
|
+
return [];
|
|
2715
|
+
}
|
|
2514
2716
|
}
|
|
2515
|
-
/**
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
},
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2717
|
+
/** Notifica eventos de popup a la API */
|
|
2718
|
+
async postPopupEvent(status, popupId, userId) {
|
|
2719
|
+
const apiKey = this.config?.apiKey;
|
|
2720
|
+
const baseUrl = this.baseUrl;
|
|
2721
|
+
if (!apiKey || !baseUrl) {
|
|
2722
|
+
return;
|
|
2723
|
+
}
|
|
2724
|
+
const endpoint = `${baseUrl}/sdk/popups`;
|
|
2725
|
+
try {
|
|
2726
|
+
const response = await fetch(endpoint, {
|
|
2727
|
+
method: "POST",
|
|
2728
|
+
headers: { "Content-Type": "application/json" },
|
|
2729
|
+
body: JSON.stringify({
|
|
2730
|
+
publicKey: apiKey,
|
|
2731
|
+
status,
|
|
2732
|
+
popupId,
|
|
2733
|
+
userId: userId || void 0
|
|
2734
|
+
})
|
|
2735
|
+
});
|
|
2736
|
+
if (!response.ok) {
|
|
2737
|
+
this.log("Failed to post popup event", response.status, response.statusText);
|
|
2531
2738
|
}
|
|
2532
|
-
|
|
2739
|
+
} catch (error) {
|
|
2740
|
+
this.log("Error posting popup event", error);
|
|
2741
|
+
}
|
|
2533
2742
|
}
|
|
2534
2743
|
/** Add an event listener */
|
|
2535
2744
|
on(eventType, listener) {
|
|
@@ -2569,11 +2778,26 @@ var DeepdotsPopups = class {
|
|
|
2569
2778
|
/** Render the popup UI */
|
|
2570
2779
|
renderPopup(surveyId, productId, actions) {
|
|
2571
2780
|
if (this.renderer) {
|
|
2572
|
-
this.renderer.show(
|
|
2781
|
+
this.renderer.show(
|
|
2782
|
+
surveyId,
|
|
2783
|
+
productId,
|
|
2784
|
+
actions,
|
|
2785
|
+
(type, id, payload) => this.emitEvent(type, id, payload),
|
|
2786
|
+
() => this.hidePopup(),
|
|
2787
|
+
this.env
|
|
2788
|
+
);
|
|
2573
2789
|
return;
|
|
2574
2790
|
}
|
|
2575
2791
|
if (!this.popupContainer) return;
|
|
2576
|
-
renderPopup(
|
|
2792
|
+
renderPopup(
|
|
2793
|
+
this.popupContainer,
|
|
2794
|
+
surveyId,
|
|
2795
|
+
productId,
|
|
2796
|
+
actions,
|
|
2797
|
+
(type, id, payload) => this.emitEvent(type, id, payload),
|
|
2798
|
+
() => this.hidePopup(),
|
|
2799
|
+
this.env
|
|
2800
|
+
);
|
|
2577
2801
|
}
|
|
2578
2802
|
/** Hide the popup */
|
|
2579
2803
|
hidePopup() {
|
|
@@ -2593,6 +2817,16 @@ var DeepdotsPopups = class {
|
|
|
2593
2817
|
if (type === "survey_completed") {
|
|
2594
2818
|
this.markSurveyAnswered(surveyId);
|
|
2595
2819
|
}
|
|
2820
|
+
if (type === "popup_shown" || type === "survey_completed") {
|
|
2821
|
+
const popupIdFromData = data?.popupId;
|
|
2822
|
+
const popupId = popupIdFromData || this.surveyToPopupId.get(surveyId);
|
|
2823
|
+
if (popupId) {
|
|
2824
|
+
const userIdFromData = data?.userId;
|
|
2825
|
+
void this.postPopupEvent(type === "popup_shown" ? "opened" : "completed", popupId, userIdFromData || this.config?.userId);
|
|
2826
|
+
} else {
|
|
2827
|
+
this.debug("No popupId available to post event", { type, surveyId });
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
2596
2830
|
const listeners = this.listeners.get(type);
|
|
2597
2831
|
if (listeners) {
|
|
2598
2832
|
listeners.forEach((listener) => {
|
|
@@ -2625,10 +2859,26 @@ var DeepdotsPopups = class {
|
|
|
2625
2859
|
isPopupDefinition(value) {
|
|
2626
2860
|
if (typeof value !== "object" || value === null) return false;
|
|
2627
2861
|
const v = value;
|
|
2628
|
-
|
|
2862
|
+
const trigger = v.triggers || v.triggers;
|
|
2863
|
+
if (!trigger) return false;
|
|
2864
|
+
return typeof v.id === "string" && typeof v.title === "string" && typeof v.message === "string" && typeof v.surveyId === "string" && typeof v.productId === "string";
|
|
2865
|
+
}
|
|
2866
|
+
normalizePopupDefinition(def) {
|
|
2867
|
+
if (typeof def !== "object" || def === null) return null;
|
|
2868
|
+
const raw = def;
|
|
2869
|
+
const trigger = raw.triggers || raw.triggers;
|
|
2870
|
+
if (!trigger) return null;
|
|
2871
|
+
const condition = trigger.condition ?? raw.conditions ?? [];
|
|
2872
|
+
return {
|
|
2873
|
+
...raw,
|
|
2874
|
+
triggers: {
|
|
2875
|
+
...trigger,
|
|
2876
|
+
condition
|
|
2877
|
+
}
|
|
2878
|
+
};
|
|
2629
2879
|
}
|
|
2630
2880
|
validatePopupDefinitions(defs) {
|
|
2631
|
-
return defs.filter((
|
|
2881
|
+
return defs.map((def) => this.normalizePopupDefinition(def)).filter((def) => !!def && this.isPopupDefinition(def));
|
|
2632
2882
|
}
|
|
2633
2883
|
};
|
|
2634
2884
|
//# sourceMappingURL=index.js.map
|