|
467 | 467 | var VALID_PROVIDERS = ["x", "meta", "openai", "ga4", "linkedin"]; |
468 | 468 | var firedIds = /* @__PURE__ */ new Set(); |
469 | 469 | var isConversionMessage = (data) => !!data && data.type === CONVERSION_MESSAGE_TYPE && typeof data.id === "string" && VALID_PROVIDERS.includes(data.provider) && !!data.event && typeof data.response_id === "string"; |
470 | | - var handleConversionMessage = (event, log2) => { |
| 470 | + var handleConversionMessage = (event, log3) => { |
471 | 471 | const data = event.data; |
472 | 472 | if (!isConversionMessage(data)) return; |
473 | 473 | const ack = () => { |
|
492 | 492 | gclid: data.gclid, |
493 | 493 | li_fat_id: data.li_fat_id |
494 | 494 | }); |
495 | | - log2.info({ |
| 495 | + log3.info({ |
496 | 496 | message: "Conversion handled", |
497 | 497 | response: { provider: data.provider, responseId: data.response_id, fired } |
498 | 498 | }); |
|
578 | 578 | } |
579 | 579 | }; |
580 | 580 | } |
581 | | - function initializeUserJourneyTracking(environmentId3, log2, getJourneyId, setJourneyId, config = getSurfaceRuntimeConfig()) { |
| 581 | + function initializeUserJourneyTracking(environmentId3, log3, getJourneyId, setJourneyId, config = getSurfaceRuntimeConfig()) { |
582 | 582 | try { |
583 | 583 | if (typeof window === "undefined") return; |
584 | 584 | const existingId = getExistingJourneyId(); |
585 | 585 | setJourneyId(existingId); |
586 | | - log2.info({ message: "Existing journey ID", response: { id: existingId || "none" } }); |
| 586 | + log3.info({ message: "Existing journey ID", response: { id: existingId || "none" } }); |
587 | 587 | const currentUrl2 = window.location.href; |
588 | 588 | const recentVisit = getCookie(SURFACE_USER_JOURNEY_RECENT_VISIT_COOKIE_NAME); |
589 | 589 | if (recentVisit === currentUrl2) { |
590 | | - log2.info({ message: "Skipping duplicate page view (same as recent visit)" }); |
| 590 | + log3.info({ message: "Skipping duplicate page view (same as recent visit)" }); |
591 | 591 | return; |
592 | 592 | } |
593 | 593 | trackToRedis( |
594 | 594 | createPageViewEvent(currentUrl2, environmentId3), |
595 | | - log2, |
| 595 | + log3, |
596 | 596 | getJourneyId, |
597 | 597 | setJourneyId, |
598 | 598 | config |
|
602 | 602 | sameSite: "lax", |
603 | 603 | domain: getJourneyCookieDomain() |
604 | 604 | }); |
605 | | - log2.info({ message: "User journey tracking initialized" }); |
| 605 | + log3.info({ message: "User journey tracking initialized" }); |
606 | 606 | } catch (error) { |
607 | | - log2.error({ message: "Error initializing user journey tracking", error }); |
| 607 | + log3.error({ message: "Error initializing user journey tracking", error }); |
608 | 608 | } |
609 | 609 | } |
610 | | - async function trackToRedis(event, log2, getJourneyId, setJourneyId, config = getSurfaceRuntimeConfig()) { |
| 610 | + async function trackToRedis(event, log3, getJourneyId, setJourneyId, config = getSurfaceRuntimeConfig()) { |
611 | 611 | try { |
612 | 612 | const journeyId = getJourneyId(); |
613 | 613 | const payload = { ...event }; |
614 | 614 | if (journeyId) payload.id = journeyId; |
615 | | - log2.info({ message: "Tracking to Redis", response: payload }); |
| 615 | + log3.info({ message: "Tracking to Redis", response: payload }); |
616 | 616 | if (journeyId && typeof navigator !== "undefined" && navigator.sendBeacon) { |
617 | 617 | const blob = new Blob([JSON.stringify(payload)], { |
618 | 618 | type: "application/json" |
619 | 619 | }); |
620 | 620 | const sent = navigator.sendBeacon(config.userJourneyTrackingApi, blob); |
621 | 621 | if (sent) { |
622 | 622 | refreshJourneyCookie(journeyId); |
623 | | - log2.info({ message: "Tracking sent via sendBeacon", response: { sent } }); |
| 623 | + log3.info({ message: "Tracking sent via sendBeacon", response: { sent } }); |
624 | 624 | return { success: true }; |
625 | 625 | } |
626 | | - log2.warn({ message: "sendBeacon failed, falling back to fetch" }); |
| 626 | + log3.warn({ message: "sendBeacon failed, falling back to fetch" }); |
627 | 627 | } |
628 | 628 | const response = await fetch(config.userJourneyTrackingApi, { |
629 | 629 | method: "POST", |
630 | 630 | headers: { "Content-Type": "application/json" }, |
631 | 631 | body: JSON.stringify(payload) |
632 | 632 | }); |
633 | 633 | if (!response.ok) { |
634 | | - log2.warn({ message: "Tracking API returned status", response: { status: response.status } }); |
| 634 | + log3.warn({ message: "Tracking API returned status", response: { status: response.status } }); |
635 | 635 | return null; |
636 | 636 | } |
637 | 637 | const data = await response.json(); |
638 | 638 | if (data?.data?.id) { |
639 | 639 | setJourneyId(data.data.id); |
640 | | - log2.info({ message: "Journey ID stored", response: { id: data.data.id } }); |
| 640 | + log3.info({ message: "Journey ID stored", response: { id: data.data.id } }); |
641 | 641 | } |
642 | 642 | refreshJourneyCookie(getJourneyId()); |
643 | 643 | return data; |
644 | 644 | } catch (error) { |
645 | | - log2.error({ message: "Error tracking to Redis", error }); |
| 645 | + log3.error({ message: "Error tracking to Redis", error }); |
646 | 646 | return null; |
647 | 647 | } |
648 | 648 | } |
649 | | - function updateUserJourneyOnRouteChange(environmentId3, newUrl, log2, getJourneyId, setJourneyId, config = getSurfaceRuntimeConfig()) { |
| 649 | + function updateUserJourneyOnRouteChange(environmentId3, newUrl, log3, getJourneyId, setJourneyId, config = getSurfaceRuntimeConfig()) { |
650 | 650 | try { |
651 | 651 | if (typeof window === "undefined") return; |
652 | 652 | const currentUrl2 = newUrl || window.location.href; |
653 | 653 | const recentVisit = getCookie(SURFACE_USER_JOURNEY_RECENT_VISIT_COOKIE_NAME); |
654 | 654 | if (recentVisit === currentUrl2) { |
655 | | - log2.info({ message: "Skipping duplicate page view on route change" }); |
| 655 | + log3.info({ message: "Skipping duplicate page view on route change" }); |
656 | 656 | return; |
657 | 657 | } |
658 | 658 | trackToRedis( |
659 | 659 | createPageViewEvent(currentUrl2, environmentId3), |
660 | | - log2, |
| 660 | + log3, |
661 | 661 | getJourneyId, |
662 | 662 | setJourneyId, |
663 | 663 | config |
|
667 | 667 | sameSite: "lax", |
668 | 668 | domain: getJourneyCookieDomain() |
669 | 669 | }); |
670 | | - log2.info({ message: "User journey updated on route change", response: { url: currentUrl2 } }); |
| 670 | + log3.info({ message: "User journey updated on route change", response: { url: currentUrl2 } }); |
671 | 671 | } catch (error) { |
672 | | - log2.error({ message: "Error updating user journey on route change", error }); |
| 672 | + log3.error({ message: "Error updating user journey on route change", error }); |
673 | 673 | } |
674 | 674 | } |
675 | | - function clearUserJourney(log2, setJourneyId) { |
| 675 | + function clearUserJourney(log3, setJourneyId) { |
676 | 676 | const domain = getJourneyCookieDomain(); |
677 | 677 | deleteCookie(SURFACE_USER_JOURNEY_COOKIE_NAME, { domain }); |
678 | 678 | deleteCookie(SURFACE_USER_JOURNEY_RECENT_VISIT_COOKIE_NAME, { domain }); |
679 | 679 | setJourneyId(null); |
680 | | - log2.info({ message: "User journey cleared" }); |
| 680 | + log3.info({ message: "User journey cleared" }); |
681 | 681 | } |
682 | 682 |
|
683 | 683 | // src/store/store.ts |
|
1052 | 1052 | { name: "md", min: 768 }, |
1053 | 1053 | { name: "sm", min: 0 } |
1054 | 1054 | ]; |
1055 | | - function resolveEmbedType(input, log2) { |
| 1055 | + function resolveEmbedType(input, log3) { |
1056 | 1056 | if (typeof input === "string") return input; |
1057 | | - if (typeof input === "object") return resolveResponsiveType(input, log2); |
1058 | | - log2.error({ message: "Invalid embed type: must be string or object" }); |
| 1057 | + if (typeof input === "object") return resolveResponsiveType(input, log3); |
| 1058 | + log3.error({ message: "Invalid embed type: must be string or object" }); |
1059 | 1059 | return null; |
1060 | 1060 | } |
1061 | | - function resolveResponsiveType(config, log2) { |
| 1061 | + function resolveResponsiveType(config, log3) { |
1062 | 1062 | const withDefault = ensureDefault(config); |
1063 | 1063 | const breakpoint = getCurrentBreakpoint(); |
1064 | 1064 | if (!breakpoint) { |
1065 | | - log2.info({ message: "No matching breakpoint, using default embed type" }); |
| 1065 | + log3.info({ message: "No matching breakpoint, using default embed type" }); |
1066 | 1066 | return withDefault.default; |
1067 | 1067 | } |
1068 | 1068 | const embedType = withDefault[breakpoint]; |
1069 | 1069 | if (embedType) { |
1070 | | - log2.info({ message: "Using breakpoint embed type", response: { breakpoint, embedType } }); |
| 1070 | + log3.info({ message: "Using breakpoint embed type", response: { breakpoint, embedType } }); |
1071 | 1071 | return embedType; |
1072 | 1072 | } |
1073 | | - log2.warn({ message: "No embed type for breakpoint, using default", response: { breakpoint } }); |
| 1073 | + log3.warn({ message: "No embed type for breakpoint, using default", response: { breakpoint } }); |
1074 | 1074 | return withDefault.default; |
1075 | 1075 | } |
1076 | 1076 | function ensureDefault(config) { |
|
1947 | 1947 | this.src = new URL(src); |
1948 | 1948 | this.log = createLogger("Surface Embed"); |
1949 | 1949 | this.store = window.SurfaceTagStore; |
1950 | | - this.currentQuestionId = document.currentScript?.getAttribute("data-question-id") || null; |
| 1950 | + this.currentQuestionId = options.questionId || document.currentScript?.getAttribute("data-question-id") || null; |
1951 | 1951 | _SurfaceEmbed._instances.push(this); |
1952 | 1952 | if (this._isFormPreviewMode()) { |
1953 | 1953 | this.log.info({ message: "Form is in preview mode" }); |
|
2494 | 2494 | window.addEventListener("message", onMessage); |
2495 | 2495 | } |
2496 | 2496 |
|
| 2497 | + // src/stub-queue.ts |
| 2498 | + var RELAYED_METHODS = [ |
| 2499 | + "showSurfaceForm", |
| 2500 | + "hideSurfaceForm", |
| 2501 | + "initializeEmbed" |
| 2502 | + ]; |
| 2503 | + var log2 = createLogger("Surface Stub Queue"); |
| 2504 | + function drainStubQueue() { |
| 2505 | + const w3 = window; |
| 2506 | + if (!Array.isArray(w3.SurfaceTagQueue)) return; |
| 2507 | + const entries = w3.SurfaceTagQueue; |
| 2508 | + w3.SurfaceTagQueue = { push: processEntry }; |
| 2509 | + entries.forEach(processEntry); |
| 2510 | + } |
| 2511 | + function processEntry(entry) { |
| 2512 | + try { |
| 2513 | + if (entry?.type === "consent") { |
| 2514 | + setSurfaceConsent(entry.args?.[0] ?? {}); |
| 2515 | + return; |
| 2516 | + } |
| 2517 | + if (entry?.type !== "embed") return; |
| 2518 | + const [src, embedType, targetClass, options] = Array.from(entry.args ?? []); |
| 2519 | + const embed = new SurfaceEmbed( |
| 2520 | + src, |
| 2521 | + embedType, |
| 2522 | + targetClass, |
| 2523 | + { |
| 2524 | + // The captured script attribute only fills in when the caller didn't |
| 2525 | + // pass questionId explicitly — same precedence as direct construction. |
| 2526 | + ...entry.questionId ? { questionId: entry.questionId } : {}, |
| 2527 | + ...options ?? {} |
| 2528 | + } |
| 2529 | + ); |
| 2530 | + for (const method of entry.calls ?? []) { |
| 2531 | + if (RELAYED_METHODS.includes(method)) embed[method](); |
| 2532 | + } |
| 2533 | + if (entry.stub && typeof entry.stub === "object") { |
| 2534 | + for (const method of RELAYED_METHODS) { |
| 2535 | + entry.stub[method] = () => embed[method](); |
| 2536 | + } |
| 2537 | + } |
| 2538 | + } catch (error) { |
| 2539 | + log2.error({ message: "Failed to replay queued call", error }); |
| 2540 | + } |
| 2541 | + } |
| 2542 | + |
2497 | 2543 | // src/index.ts |
2498 | 2544 | var scriptTag = document.currentScript; |
2499 | 2545 | var runtimeConfig2 = initializeSurfaceRuntimeConfig(scriptTag); |
|
2515 | 2561 | }); |
2516 | 2562 | void resolveOpenTriggersOnLoad(environmentId2, runtimeConfig2); |
2517 | 2563 | initReview(); |
| 2564 | + drainStubQueue(); |
2518 | 2565 | })(); |
0 commit comments