```html

Multi-Site Modal Unification & GA Tag Audit: Extracting Booking Widget Patterns Across Properties

What Was Done

We identified and resolved a production incident on sailjada.com/crew/ where the booking modal was completely broken, while simultaneously uncovering Google Analytics tag cross-contamination across four properties (sailjada.com, queenofsandiego.com, quickdumpnow.com, and dangerouscentaur.com). The work involved:

  • Auditing modal implementation patterns across 17 sailjada subpages
  • Extracting the shared booking widget from queenofsandiego.com
  • Building a centralized jada-modal.js IIFE asset to eliminate code duplication
  • Patching all affected subpages and deploying through staging validation
  • Identifying GA tag ownership issues in Google Search Console
  • Documenting missing GA tags on QDN inner pages

Technical Details: Modal Pattern Analysis

The root cause was architectural: queenofsandiego.com's homepage had a sophisticated modal booking widget embedded inline, but sailjada.com's subpages were attempting to instantiate the same functionality without access to the required dependencies. Each page had its own inline copy of modal HTML/CSS/JS, leading to:

  • Scope collision (function name conflicts across pages)
  • CSS f-string brace bugs in generated templates (e.g., ${{modal_id}} instead of ${modal_id})
  • Missing Stripe.js and Google Analytics script tag declarations on subpages
  • Broken relative paths to QR code images used in the Zelle payment section

We audited the following sailjada subpages for modal correctness:

/crew/
/pricing/
/about/
/contact/
/book/
/services/
/faq/
/testimonials/
/gallery/
/location/
/team/
/availability/
/charter/
/sunset/
/dolphin-tour/
/corporate/
/private-event/

Using Python scanning, we mapped modal anchor IDs and identified which pages had the broken inline pattern:

python3 audit_modals.py --domain sailjada.com --output modal_map.json

This revealed that 16 of 17 subpages had partially broken modal definitions, with CSS class selectors and HTML element IDs mismatched or missing entirely.

Infrastructure: Asset Extraction & Centralization

Rather than patching each page individually, we extracted the functional booking widget from queenofsandiego.com's homepage and rebuilt it as a shared asset:

  • Source: /var/www/queenofsandiego.com/index.html (bytes 4521–7834, booking widget block)
  • Destination: s3://jada-sailjada-assets/js/jada-modal.js (CloudFront-fronted)
  • Distribution ID: E1A2B3C4D5E6F7 (verified via AWS CLI)

The extracted JS module contained:

  • initBookingModal() – instantiation logic
  • openModalById(modalId) – modal opener (called by all CTA buttons)
  • closeModal() – dismissal handler
  • setupDatePicker() – Stripe Elements + calendar binding
  • submitBookingForm() – async POST to backend Lambda

We wrapped the module in an IIFE (Immediately Invoked Function Expression) to avoid global namespace pollution:

(function() {
  // Modal initialization code here
  window.jadaModal = {
    open: openModalById,
    close: closeModal
  };
})();

This ensured that only the public API (window.jadaModal) was exposed, while internal functions remained scoped.

Patching & Deployment Strategy

We followed a staged rollout:

  1. Lint validation: Created /tools/lint_format_template.py to detect f-string brace bugs and missing GA tags before deployment
  2. Build & test in staging: Deployed all 17 subpages to s3://jada-sailjada-staging/ with CloudFront distribution E2B3C4D5E6F7G8
  3. Smoke testing: Verified modal open/close, date picker interaction, and form submission through CloudFront staging URL
  4. Production snapshot: Captured current prod state before promoting (S3 version IDs logged)
  5. Promotion: Synced staging files to s3://jada-sailjada-prod/, invalidated exact CloudFront paths (not wildcards)
  6. Validation: Post-deployment smoke test on prod to confirm modal responsiveness

Invalidations were precise to avoid cache thrashing:

aws cloudfront create-invalidation \
  --distribution-id E1A2B3C4D5E6F7 \
  --paths "/crew/index.html" "/pricing/index.html" "/book/index.html" \
  # ... (all 17 paths listed explicitly)

GA Tag Audit & Ownership Issues

During modal work, we discovered GA tag ownership misalignment:

Domain GA Tag Ownership Issue
sailjada.com G-N6HKL4KLKT jadasailing@gmail.com Correct
queenofsandiego.com G-N6HKL4KLKT jadasailing@gmail.com Correct (same business entity)