Multi-Site Modal Unification & GA Tag Audit: Bringing Sailjada.com to Production Quality
What Was Done
Over the course of a focused development session, we identified and resolved a critical production issue on sailjada.com's booking experience, consolidated a fragmented modal widget across 17 subpages, and uncovered a Google Analytics ownership/tagging problem affecting two separate business units.
The core work:
- Extracted a shared booking modal widget from queenofsandiego.com's homepage
- Built a reusable
jada-modal.jsasset and refactored it into a proper IIFE (Immediately Invoked Function Expression) to avoid global scope pollution - Patched all 17 sailjada.com subpages to use the unified modal instead of inline, broken calendar code
- Staged the changes in an S3 bucket + CloudFront distribution for testing before promoting to production
- Discovered that QuickDumpNow.com (a different business) was being managed under the JADA Google account, creating GA/GSC ownership entanglement
- Identified missing GA tags on QDN inner pages and created remediation cards
Technical Details: Modal Consolidation
Source Analysis & Extraction
The queenofsandiego.com homepage at /index.html contained a sophisticated Stripe-integrated booking modal. We mapped the modal across four source files to understand the pattern:
- Modal trigger: CTA buttons with class
.reserve-btn - Modal container:
<div id="booking-modal">with anchor ID references for Stripe embedded forms - State management: Vanilla JavaScript event listeners on modal open/close
- Styling: Inline CSS within
<style>tags, using f-strings for dynamic values - External dependencies: Stripe.js loaded asynchronously, Google Analytics tag (G-N6HKL4KLKT)
Key discovery: The modal's f-string templating used Python-style braces {variable}, which required careful parsing to avoid CSS brace conflicts.
Widget Extraction & IIFE Wrapping
We extracted the modal's JavaScript into /assets/js/jada-modal.js and wrapped it in an IIFE to prevent global namespace contamination:
(function() {
// Modal open/close handlers
// Event delegation for all .reserve-btn elements
// Stripe form initialization
// GA event tracking
})();
This pattern allows the script to be loaded on any page without conflicts. The IIFE exposes only necessary globals: the modal container reference and the open/close methods are internal to the closure.
Dependency Resolution
The modal depends on three external libraries loaded before the IIFE:
<script src="https://js.stripe.com/v3/"></script>— Stripe payment form (must load before IIFE initializes)<script async src="https://www.googletagmanager.com/gtag/js?id=G-N6HKL4KLKT"></script>— Google Analytics- DOM availability — modal container must exist before IIFE runs
We ensured script load order in the patched subpages by placing jada-modal.js at the end of <body>, after the modal HTML.
Infrastructure: S3, CloudFront, and Staging
S3 Staging Bucket
We deployed to a separate S3 bucket for staging, with structure mirroring production:
s3://sailjada-staging/
├── index.html
├── crew/
│ └── index.html
├── about/
│ └── index.html
├── assets/
│ ├── js/
│ │ └── jada-modal.js (new shared asset)
│ └── css/
└── ... (15 more subpages)
All 17 HTML files were patched to reference /assets/js/jada-modal.js instead of inline scripts.
CloudFront Distribution & Cache Invalidation
We used a staging CloudFront distribution (separate from production) to test the changes over HTTPS with the same TLS/performance characteristics as production.
Critical lesson: We initially invalidated using wildcard paths (/*), which was inefficient. We switched to granular invalidation of exact paths:
aws cloudfront create-invalidation \
--distribution-id E1ABC2DEF34GHI \
--paths "/crew/index.html" "/assets/js/jada-modal.js" "/about/index.html" \
--region us-east-1
This approach reduces CloudFront processing and ensures targeted cache busting.
Production Promotion
Once staging verified correctly, we:
- Snapshotted the current production bucket state (for rollback ability)
- Synced staging bucket contents to production S3
- Invalidated the same 17 paths in the production CloudFront distribution (ID varies by region)
- Ran smoke tests against the production URL (https://sailjada.com/crew/, etc.) to verify modal functionality
GA Tag Audit: The Ownership Problem
While testing, we discovered a critical issue: QuickDumpNow.com's Google Search Console property was accessible via the JADA business account (jadasailing@gmail.com), not by QDN's own admin account.
Analysis:
- JADA properties (sailjada.com, queenofsandiego.com) correctly use GA tag
G-N6HKL4KLKT - QDN homepage correctly uses GA tag
G-539T97NM1Z - However, QDN inner pages (
/book,/track,/service-areas/carlsbad/) are missing the GA tag entirely - QDN's Google Search Console and GSC sitemap submissions are owned by jadasailing@gmail.com, not QDN's admin
This creates two problems:
- Analytics blind spot: QDN traffic on inner pages isn't tracked, making performance analysis impossible
- Ownership/compliance risk: JADA controls QDN's search visibility and can modify indexing rules without QDN's knowledge
We created two kanban cards to address this:
- t-77babced (GSC ownership transfer): Transfer quickdumpnow.com GSC property to admin@quickdumpnow.com
- t-77babcee (GA tag deployment on QDN inner pages): Audit and patch all QDN subpages to