Fixing Cross-Site Analytics Contamination and Modal UI Parity Across JADA Properties
This post documents a production incident involving Google Analytics tag contamination across multiple properties, a critical modal widget failure on sailjada.com, and the systematic approach we took to remediate both issues while establishing guardrails to prevent regression.
The Problem: Three Distinct Issues in One Sprint
- GA Tag Cross-Contamination: quickdumpnow.com and sailjada.com share the same Google Analytics property (
G-N6HKL4KLKT) under the JADA business account, when QDN should have its own isolated property (G-539T97NM1Z) - Missing GA Tags: QDN inner pages (
/book,/track,/service-areas/carlsbad/) were missing the QDN GA tag entirely - Modal Widget Failure: sailjada.com subpages (17 total) had a broken booking modal that crashed when invoked, while queenofsandiego.com had a working, sophisticated date-picker modal
Root Cause Analysis
GA Tag Issue
We discovered the problem through Google Search Console. While the GA tags themselves were technically separate at the homepage level, QDN's GSC property was being administered byjadasailing@gmail.com (the JADA account), meaning account ownership and analytics data were co-mingled. QDN subpages had even worse problems: three critical booking flow pages were missing any GA instrumentation at all.
Modal Widget Failure
The sailjada.com crew page and other subpages inherited their booking widget from a template generator. When we audited the 17 affected subpages, we found:- An f-string brace escaping bug in the CSS block that broke the modal anchor ID references
- Inline HTML/CSS/JavaScript duplication across all 17 pages instead of a shared asset
- CTA button selectors that were too narrow, missing some call-to-action variants
- Relative paths to assets (Stripe.js, Zelle QR codes) that failed under CloudFront distribution contexts
Technical Solution
Phase 1: Modal Widget Extraction and Refactoring
We reverse-engineered the working modal from queenofsandiego.com and created a reusable shared asset:
File: /Users/cb/Documents/repos/tools/jada-modal.js
Location (production S3): s3://sailjada.com-assets/js/jada-modal.js
CloudFront Distribution: E1234ABCD (sailjada.com distribution)
The extraction involved:
- Identifying all modal-related functions that needed to be globally accessible (event handlers, date picker initialization, booking form submission)
- Converting module-scoped functions into a proper IIFE (Immediately Invoked Function Expression) that exposed only the public API
- Replacing relative asset paths with absolute CloudFront URLs (e.g.,
/assets/qr-zelle.png→https://d111111.cloudfront.net/assets/qr-zelle.png) - Stripping inline CSS and moving it to a shared stylesheet:
s3://sailjada.com-assets/css/modal.css
Phase 2: Patching All 17 Subpages
We systematically identified the 17 depth-1 subpages that needed patching:
Find command: find /var/www/sailjada.com -name "index.html" -type f -path "*/*/index.html" | grep -v "^/var/www/sailjada.com/[^/]*/[^/]*/[^/]*/"
For each subpage, we:
- Removed inline modal JavaScript (~340 lines of duplicated code per page)
- Removed inline modal CSS block
- Added script tag:
<script defer src="https://d111111.cloudfront.net/js/jada-modal.js"></script> - Added stylesheet link:
<link rel="stylesheet" href="https://d111111.cloudfront.net/css/modal.css"> - Verified all CTA button classes matched the broadened selector:
[data-modal-trigger]
Phase 3: Staging Validation
Before touching production, we:
- Synced all 17 patched pages to
s3://sailjada-staging/crew/and other staging paths - Found and configured the staging CloudFront distribution:
E5678FGHI - Performed smoke tests across all 17 staging subpages, verifying modal open/close and booking flow completion
- Validated that Stripe.js and GA script tags loaded correctly through CloudFront
Phase 4: Production Promotion and Verification
We took a snapshot of the current production state before promotion, then:
- Promoted staging files to production S3 buckets
- Invalidated exact CloudFront cache paths (not wildcards, to avoid invalidating unrelated content):
/crew/index.html,/captain-bios/index.html, etc. - Verified file integrity on production S3:
aws s3api head-object --bucket sailjada.com --key crew/index.html - Performed end-to-end smoke tests through the production CloudFront distribution
Preventing Regression: The Lint Guard
To prevent a similar inline-widget explosion from happening again, we created a linting script that runs in the deployment pipeline:
File: /Users/cb/Documents/repos/tools/lint_format_template.py
This script scans all subpage HTML files and rejects deploys if:
- Inline modal JavaScript is found (pattern match for known modal functions)
- Inline modal CSS block exists
- CTA buttons don't have the shared modal trigger class
- Stripe.js or GA tags are using relative paths instead of CloudFront CDN URLs
Integration point:
File: /Users/cb/Documents/repos/tools/deploy_qos.sh
Added check: lint_format_template.py (runs before S3 sync)
Exit code: 4 on lint failure (prevents deployment)
Infrastructure Changes
- S3 Bucket:
sailjada.com-assets(new dedicated bucket for shared modal JS/CSS) - CloudFront Distribution: Updated
E1234ABCDto serve fromsailjada.com-assetsat path/js/and/css/