@bigz-app/booking-widget 0.3.2 → 0.3.4

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 CHANGED
@@ -113,7 +113,8 @@ const config = {
113
113
  tagId: 'AW-XXXXXXX', // Your Google Ads Tag ID (required)
114
114
  conversionId: 'booking_conversion', // Your conversion label (required)
115
115
  conversionCurrency: 'EUR', // Optional, defaults to 'EUR'
116
- includeValue: true // Optional, defaults to true
116
+ includeValue: true, // Optional, defaults to true
117
+ consent: true // send the users consent to the widget when initializing.
117
118
  }
118
119
  };
119
120
  ```
@@ -295,7 +295,7 @@
295
295
  const themes = {
296
296
  // --- Light Themes ---
297
297
  "light-fresh": {
298
- highlight: "#00a8a1", // accent-strong
298
+ highlight: "#00b1aa", // accent-strong
299
299
  background: "#f8fdfe", // neutral-strong (background)
300
300
  surface: "#ffffff", // card (pure white)
301
301
  text: "#0e7490", // Turquoise 800
@@ -6839,7 +6839,6 @@
6839
6839
  }
6840
6840
  catch (error) {
6841
6841
  // Ignore removal errors - element may have already been removed
6842
- console.debug("Portal cleanup: Element already removed");
6843
6842
  }
6844
6843
  }
6845
6844
  document.body.style.overflow = "";
@@ -10360,312 +10359,116 @@
10360
10359
  /**
10361
10360
  * Google Ads Conversion Tracking Utility
10362
10361
  *
10363
- * This utility handles Google Ads conversion tracking for the booking widget.
10364
- * It includes consent checking, gtag initialization, and conversion tracking.
10362
+ * Simplified utility that waits 1500ms, checks/initializes gtag, and sends conversion.
10365
10363
  */
10366
10364
  /**
10367
- * Check if Google Consent Mode has granted the necessary permissions for ads tracking
10368
- * This checks multiple sources of consent state in order of preference
10365
+ * Check if gtag is available in current or parent window
10369
10366
  */
10370
- function checkGoogleConsent() {
10371
- console.log("[Google Ads Tracking] 🔍 Checking Google consent...");
10367
+ function isGtagAvailable() {
10372
10368
  if (typeof window === "undefined") {
10373
- console.log("[Google Ads Tracking] ❌ Window object not available (SSR context)");
10374
10369
  return false;
10375
10370
  }
10376
- console.log("[Google Ads Tracking] ✅ Window object available");
10377
- // Method 1: Check dataLayer for consent_update events (most reliable)
10378
- if (window.dataLayer && Array.isArray(window.dataLayer)) {
10379
- console.log("[Google Ads Tracking] 🔍 Checking dataLayer for consent events...");
10380
- const dataLayer = window.dataLayer;
10381
- // Debug: Show the entire dataLayer contents
10382
- console.log("[Google Ads Tracking] 🗂️ Complete dataLayer contents:", JSON.stringify(dataLayer, null, 2));
10383
- console.log("[Google Ads Tracking] 📊 dataLayer length:", dataLayer.length);
10384
- // Look for the most recent consent update in dataLayer
10385
- let latestConsentState = null;
10386
- const foundEvents = [];
10387
- // Search backwards through dataLayer for most recent consent state
10388
- for (let i = dataLayer.length - 1; i >= 0; i--) {
10389
- const event = dataLayer[i];
10390
- console.log(`[Google Ads Tracking] 🔍 Checking dataLayer[${i}]:`, event);
10391
- if (event && typeof event === "object") {
10392
- // Check for various consent event patterns
10393
- if (event.event === "consent_update" || event.event === "default_consent") {
10394
- console.log("[Google Ads Tracking] 📋 Found consent event:", event);
10395
- foundEvents.push(event);
10396
- if (event.consent_mode) {
10397
- latestConsentState = event.consent_mode;
10398
- break;
10399
- }
10400
- }
10401
- // Also check for direct consent_mode properties
10402
- if (event.consent_mode) {
10403
- console.log("[Google Ads Tracking] 📋 Found consent_mode property:", event);
10404
- foundEvents.push(event);
10405
- latestConsentState = event.consent_mode;
10406
- break;
10407
- }
10371
+ // Check current window
10372
+ if (typeof window.gtag === "function") {
10373
+ return true;
10374
+ }
10375
+ // Check parent window (for iframe/widget scenarios)
10376
+ if (window !== window.parent) {
10377
+ try {
10378
+ if (typeof window.parent?.gtag === "function") {
10379
+ return true;
10408
10380
  }
10409
10381
  }
10410
- console.log("[Google Ads Tracking] 📋 All found consent events:", foundEvents);
10411
- if (latestConsentState) {
10412
- const adStorageGranted = latestConsentState.ad_storage === "granted";
10413
- console.log("[Google Ads Tracking] 🔐 ad_storage from dataLayer:", latestConsentState.ad_storage);
10414
- console.log("[Google Ads Tracking] 🎯 Consent result from dataLayer:", adStorageGranted);
10415
- return adStorageGranted;
10382
+ catch (e) {
10383
+ // Cannot access parent window (cross-origin)
10416
10384
  }
10417
- console.log("[Google Ads Tracking] ❌ No consent events found in dataLayer");
10418
- }
10419
- console.log("[Google Ads Tracking] ❌ dataLayer not found or not an array");
10420
- // Method 2: Check for cookie-based consent (fallback for host implementation)
10421
- console.log("[Google Ads Tracking] 🔍 Checking cookie-based consent...");
10422
- try {
10423
- // Debug: Show all cookies
10424
- console.log("[Google Ads Tracking] 🍪 All cookies:", document.cookie);
10425
- const allCookies = document.cookie.split(";").map((cookie) => cookie.trim());
10426
- console.log("[Google Ads Tracking] 🍪 Parsed cookies:", allCookies);
10427
- // Check for the host page's conversion tracking consent cookie
10428
- const conversionTrackingCookie = document.cookie
10429
- .split(";")
10430
- .find((cookie) => cookie.trim().startsWith("conversionTrackingConsent="));
10431
- if (conversionTrackingCookie) {
10432
- const cookieValue = conversionTrackingCookie.split("=")[1];
10433
- const isGranted = cookieValue === "true";
10434
- console.log("[Google Ads Tracking] 🍪 Found conversionTrackingConsent cookie:", cookieValue);
10435
- console.log("[Google Ads Tracking] 🎯 Consent result from cookie:", isGranted);
10436
- return isGranted;
10437
- }
10438
- console.log("[Google Ads Tracking] ❌ conversionTrackingConsent cookie not found");
10439
- // Also check for other potential cookie names
10440
- const alternativeCookieNames = ["analyticsConsent", "ads_consent", "ad_storage"];
10441
- for (const cookieName of alternativeCookieNames) {
10442
- const alternativeCookie = allCookies.find((cookie) => cookie.startsWith(`${cookieName}=`));
10443
- if (alternativeCookie) {
10444
- console.log(`[Google Ads Tracking] 🍪 Found alternative cookie ${cookieName}:`, alternativeCookie);
10445
- }
10446
- }
10447
- }
10448
- catch (error) {
10449
- console.warn("[Google Ads Tracking] ⚠️ Error checking cookies:", error);
10450
- }
10451
- // Method 3: Check if gtag exists but no consent state found
10452
- if (typeof window.gtag === "function") {
10453
- console.log("[Google Ads Tracking] ⚠️ gtag function exists but no consent state found");
10454
- console.log("[Google Ads Tracking] 💡 This might indicate consent hasn't been set yet");
10455
- }
10456
- else {
10457
- console.log("[Google Ads Tracking] ❌ gtag function not found");
10458
10385
  }
10459
- // If no consent mechanism is found, assume consent is not granted
10460
- console.log("[Google Ads Tracking] 🚫 No valid consent state found, returning false");
10461
10386
  return false;
10462
10387
  }
10463
10388
  /**
10464
- * Check if gtag is already initialized on the host page
10389
+ * Initialize gtag if not already available
10465
10390
  */
10466
- function isGtagInitialized() {
10467
- console.log("[Google Ads Tracking] 🔍 Checking if gtag is initialized...");
10391
+ function initializeGtag(tagId) {
10468
10392
  if (typeof window === "undefined") {
10469
- console.log("[Google Ads Tracking] ❌ Window object not available (SSR context)");
10470
- return false;
10393
+ return;
10471
10394
  }
10472
- console.log("[Google Ads Tracking] Window object available");
10473
- // Check if gtag function exists
10474
- if (typeof window.gtag === "function") {
10475
- console.log("[Google Ads Tracking] ✅ gtag function exists");
10476
- return true;
10395
+ // Skip if gtag already exists
10396
+ if (isGtagAvailable()) {
10397
+ return;
10477
10398
  }
10478
- console.log("[Google Ads Tracking] gtag function not found, checking for scripts...");
10479
- // Check if Google Analytics or Google Ads scripts are already loaded
10480
- const scripts = document.querySelectorAll('script[src*="googletagmanager.com"]');
10481
- console.log("[Google Ads Tracking] 📜 Found", scripts.length, "Google Tag Manager scripts");
10482
- const isInitialized = scripts.length > 0;
10483
- console.log("[Google Ads Tracking] 🎯 gtag initialization status:", isInitialized);
10484
- return isInitialized;
10485
- }
10486
- /**
10487
- * Initialize Google Tag (gtag) if not already present
10488
- */
10489
- function initializeGtag(tagId) {
10490
- console.log("[Google Ads Tracking] 🚀 Starting gtag initialization with tagId:", tagId);
10491
- return new Promise((resolve, reject) => {
10492
- if (typeof window === "undefined") {
10493
- console.log("[Google Ads Tracking] ❌ Window object not available (SSR context)");
10494
- reject(new Error("Window object not available"));
10495
- return;
10496
- }
10497
- console.log("[Google Ads Tracking] ✅ Window object available");
10498
- // If gtag is already initialized, just resolve
10499
- if (isGtagInitialized()) {
10500
- console.log("[Google Ads Tracking] ⚡ gtag already initialized, skipping setup");
10501
- resolve();
10502
- return;
10503
- }
10504
- console.log("[Google Ads Tracking] 📦 gtag not found, creating new script element...");
10505
- try {
10506
- // Create the gtag script
10507
- const script = document.createElement("script");
10508
- script.async = true;
10509
- script.src = `https://www.googletagmanager.com/gtag/js?id=${tagId}`;
10510
- console.log("[Google Ads Tracking] 🌐 Script src set to:", script.src);
10511
- script.onload = () => {
10512
- console.log("[Google Ads Tracking] 📥 Script loaded successfully, initializing gtag...");
10513
- // Initialize gtag
10514
- window.dataLayer = window.dataLayer || [];
10515
- console.log("[Google Ads Tracking] 📊 dataLayer initialized");
10516
- window.gtag = (...args) => {
10517
- window.dataLayer.push(args);
10518
- };
10519
- console.log("[Google Ads Tracking] 🔧 gtag function created");
10520
- // Configure gtag
10521
- console.log("[Google Ads Tracking] ⚙️ Configuring gtag with privacy settings...");
10522
- window.gtag("js", new Date());
10523
- window.gtag("config", tagId, {
10524
- // Respect consent settings
10525
- anonymize_ip: true,
10526
- allow_google_signals: false,
10527
- allow_ad_personalization_signals: false,
10528
- });
10529
- console.log("[Google Ads Tracking] ✅ gtag initialized successfully with tagId:", tagId);
10530
- resolve();
10531
- };
10532
- script.onerror = (error) => {
10533
- console.error("[Google Ads Tracking] ❌ Failed to load Google Tag script:", error);
10534
- reject(new Error("Failed to load Google Tag script"));
10535
- };
10536
- console.log("[Google Ads Tracking] 📑 Adding script to document head...");
10537
- // Add script to head
10538
- document.head.appendChild(script);
10539
- console.log("[Google Ads Tracking] ✅ Script element appended to head");
10540
- }
10541
- catch (error) {
10542
- console.error("[Google Ads Tracking] ❌ Error during gtag initialization:", error);
10543
- reject(error);
10544
- }
10399
+ // Initialize dataLayer and gtag function
10400
+ window.dataLayer = window.dataLayer || [];
10401
+ window.gtag = (...args) => {
10402
+ window.dataLayer.push(args);
10403
+ };
10404
+ // Set current timestamp
10405
+ window.gtag("js", new Date());
10406
+ // Load gtag script
10407
+ const script = document.createElement("script");
10408
+ script.async = true;
10409
+ script.src = `https://www.googletagmanager.com/gtag/js?id=${tagId}`;
10410
+ document.head.appendChild(script);
10411
+ // Configure the tag
10412
+ window.gtag("config", tagId, {
10413
+ anonymize_ip: true,
10414
+ allow_google_signals: false,
10415
+ allow_ad_personalization_signals: false,
10545
10416
  });
10546
10417
  }
10547
10418
  /**
10548
- * Track a Google Ads conversion
10419
+ * Send conversion event using available gtag
10549
10420
  */
10550
- function trackConversion(config) {
10551
- console.log("[Google Ads Tracking] 🎯 Starting conversion tracking with config:", config);
10421
+ function sendConversion(config) {
10552
10422
  if (typeof window === "undefined") {
10553
- console.warn("[Google Ads Tracking] ❌ Window object not available");
10554
10423
  return;
10555
10424
  }
10556
- console.log("[Google Ads Tracking] ✅ Window object available");
10557
- if (!config.tagId || !config.conversionId) {
10558
- console.warn("[Google Ads Tracking] Missing tagId or conversionId", {
10559
- tagId: config.tagId,
10560
- conversionId: config.conversionId,
10561
- });
10562
- return;
10425
+ let gtag = window.gtag;
10426
+ // Try parent window gtag if current window doesn't have it
10427
+ if (typeof gtag !== "function" && window !== window.parent) {
10428
+ try {
10429
+ gtag = window.parent?.gtag;
10430
+ }
10431
+ catch {
10432
+ // Cannot access parent window (cross-origin)
10433
+ }
10563
10434
  }
10564
- console.log("[Google Ads Tracking] ✅ Required config fields present:", {
10565
- tagId: config.tagId,
10566
- conversionId: config.conversionId,
10567
- });
10568
- if (typeof window.gtag !== "function") {
10569
- console.warn("[Google Ads Tracking] ❌ gtag function not available");
10435
+ if (typeof gtag !== "function") {
10570
10436
  return;
10571
10437
  }
10572
- console.log("[Google Ads Tracking] ✅ gtag function is available");
10573
- try {
10574
- console.log("[Google Ads Tracking] 🔧 Building conversion data...");
10575
- const conversionData = {
10576
- send_to: `${config.tagId}/${config.conversionId}`,
10577
- };
10578
- console.log("[Google Ads Tracking] 📋 Base conversion data:", conversionData);
10579
- // Add optional parameters
10580
- if (config.conversionValue !== undefined) {
10581
- conversionData.value = config.conversionValue;
10582
- console.log("[Google Ads Tracking] 💰 Added conversion value:", config.conversionValue);
10583
- }
10584
- if (config.conversionCurrency) {
10585
- conversionData.currency = config.conversionCurrency;
10586
- console.log("[Google Ads Tracking] 💱 Added currency:", config.conversionCurrency);
10587
- }
10588
- if (config.transactionId) {
10589
- conversionData.transaction_id = config.transactionId;
10590
- console.log("[Google Ads Tracking] 🔖 Added transaction ID:", config.transactionId);
10591
- }
10592
- console.log("[Google Ads Tracking] 📦 Final conversion data:", conversionData);
10593
- // Track the conversion
10594
- console.log("[Google Ads Tracking] 🚀 Sending conversion event to gtag...");
10595
- window.gtag("event", "conversion", conversionData);
10596
- console.log("[Google Ads Tracking] ✅ Conversion tracked successfully:", conversionData);
10438
+ // Build conversion data
10439
+ const conversionData = {
10440
+ send_to: `${config.tagId}/${config.conversionId}`,
10441
+ };
10442
+ // Add optional parameters
10443
+ if (config.conversionValue !== undefined) {
10444
+ conversionData.value = config.conversionValue;
10597
10445
  }
10598
- catch (error) {
10599
- console.error("[Google Ads Tracking] ❌ Error tracking conversion:", error);
10446
+ if (config.conversionCurrency) {
10447
+ conversionData.currency = config.conversionCurrency;
10600
10448
  }
10449
+ if (config.transactionId) {
10450
+ conversionData.transaction_id = config.transactionId;
10451
+ }
10452
+ // Send conversion event
10453
+ gtag("event", "conversion", conversionData);
10601
10454
  }
10602
10455
  /**
10603
10456
  * Main function to handle Google Ads conversion tracking
10604
- * This function checks consent, initializes gtag if needed, and tracks the conversion
10457
+ * Waits 1500ms, checks/initializes gtag, then sends conversion
10605
10458
  */
10606
- async function handleGoogleAdsConversion(config) {
10607
- console.log("[Google Ads Tracking] 🎬 Starting handleGoogleAdsConversion with config:", config);
10608
- // Validate config
10459
+ function handleGoogleAdsConversion(config) {
10460
+ // Validate required config
10609
10461
  if (!config.tagId || !config.conversionId) {
10610
- console.log("[Google Ads Tracking] ❌ No tagId or conversionId provided, skipping conversion tracking", { tagId: config.tagId, conversionId: config.conversionId });
10611
- return;
10612
- }
10613
- console.log("[Google Ads Tracking] ✅ Config validation passed");
10614
- // Check consent first
10615
- console.log("[Google Ads Tracking] 🔐 Checking consent...");
10616
- if (!checkGoogleConsent()) {
10617
- console.log("[Google Ads Tracking] 🚫 Google consent not granted, skipping conversion tracking");
10618
10462
  return;
10619
10463
  }
10620
- console.log("[Google Ads Tracking] Consent check passed");
10621
- try {
10622
- // Initialize gtag if not already present
10623
- console.log("[Google Ads Tracking] 🔍 Checking if gtag needs initialization...");
10624
- if (!isGtagInitialized()) {
10625
- console.log("[Google Ads Tracking] 🚀 Initializing gtag...");
10626
- await initializeGtag(config.tagId);
10627
- console.log("[Google Ads Tracking] ✅ gtag initialization completed");
10464
+ // Wait 1500ms before proceeding
10465
+ setTimeout(() => {
10466
+ // Check if gtag is available, initialize if not
10467
+ if (!isGtagAvailable()) {
10468
+ initializeGtag(config.tagId);
10628
10469
  }
10629
- else {
10630
- console.log("[Google Ads Tracking] ⚡ gtag already initialized, proceeding...");
10631
- }
10632
- // Small delay to ensure gtag is ready
10633
- console.log("[Google Ads Tracking] ⏱️ Adding 100ms delay to ensure gtag is ready...");
10634
- setTimeout(() => {
10635
- console.log("[Google Ads Tracking] 🎯 Delay completed, tracking conversion...");
10636
- trackConversion(config);
10637
- }, 100);
10638
- }
10639
- catch (error) {
10640
- console.error("[Google Ads Tracking] ❌ Error handling conversion:", error);
10641
- }
10642
- }
10643
- /**
10644
- * Utility function to get conversion value from booking data
10645
- */
10646
- function getConversionValueFromBooking(bookingData) {
10647
- console.log("[Google Ads Tracking] 💰 Extracting conversion value from booking data:", bookingData);
10648
- // Try to get the total amount from various possible structures
10649
- const possiblePaths = [
10650
- { path: "order.total", value: bookingData?.order?.total },
10651
- { path: "booking.total", value: bookingData?.booking?.total },
10652
- { path: "total", value: bookingData?.total },
10653
- { path: "amount", value: bookingData?.amount },
10654
- { path: "payment.amount", value: bookingData?.payment?.amount },
10655
- { path: "stripePaymentIntent.amount", value: bookingData?.stripePaymentIntent?.amount },
10656
- ];
10657
- console.log("[Google Ads Tracking] 🔍 Checking possible value paths:", possiblePaths);
10658
- for (const { path, value } of possiblePaths) {
10659
- console.log(`[Google Ads Tracking] 📋 Checking path '${path}':`, value);
10660
- if (typeof value === "number" && value > 0) {
10661
- // Convert from cents to euros
10662
- const convertedValue = value / 100;
10663
- console.log(`[Google Ads Tracking] ✅ Found valid value at '${path}': ${value} cents = ${convertedValue} euros`);
10664
- return convertedValue;
10665
- }
10666
- }
10667
- console.log("[Google Ads Tracking] ❌ No valid conversion value found in booking data");
10668
- return undefined;
10470
+ sendConversion(config);
10471
+ }, 1500);
10669
10472
  }
10670
10473
 
10671
10474
  const BookingSuccessModal = ({ isOpen, onClose, config, onError, paymentIntentId, }) => {
@@ -10716,11 +10519,10 @@
10716
10519
  const finalPaymentStatus = data.stripePaymentIntent?.status || data.order.status;
10717
10520
  if (finalPaymentStatus === "succeeded" &&
10718
10521
  config.googleAds?.tagId &&
10719
- config.googleAds?.conversionId) {
10522
+ config.googleAds?.conversionId &&
10523
+ config.googleAds?.consent !== false) {
10720
10524
  // Prepare conversion tracking data
10721
- const conversionValue = config.googleAds.includeValue !== false
10722
- ? getConversionValueFromBooking(data)
10723
- : undefined;
10525
+ const conversionValue = data.order.total;
10724
10526
  const transactionId = data.order.id;
10725
10527
  // Track the conversion
10726
10528
  handleGoogleAdsConversion({
@@ -10729,8 +10531,6 @@
10729
10531
  conversionValue,
10730
10532
  conversionCurrency: config.googleAds.conversionCurrency || "EUR",
10731
10533
  transactionId,
10732
- }).catch((error) => {
10733
- console.warn("[BookingSuccessModal] Google Ads conversion tracking failed:", error);
10734
10534
  });
10735
10535
  }
10736
10536
  }
@@ -10812,7 +10612,7 @@
10812
10612
  fontWeight: "600",
10813
10613
  color: "var(--bw-highlight-color)",
10814
10614
  margin: "0px 10px",
10815
- }, children: "Buchung erfolgreich erstellt!" })] }), u$2("button", { onClick: handlePrint, style: {
10615
+ }, children: "Reservierung erfolgreich!" })] }), u$2("button", { onClick: handlePrint, style: {
10816
10616
  backgroundColor: "transparent",
10817
10617
  border: `1px solid var(--bw-border-color)`,
10818
10618
  color: "var(--bw-text-color)",