Fixing Cross-Site GA Contamination and Modal Widget Bugs Across Four Production Properties
This post documents a high-priority production incident spanning two issues: Google Analytics property ownership misalignment across properties, and a critical UI/modal rendering bug on sailjada.com that broke the booking experience. The work involved coordinating GA tag audits, JavaScript modal extraction, S3/CloudFront deployments, and establishing lint guards to prevent regression.
The Problem
Two separate issues surfaced in production:
- GA Ownership Contamination: QuickDumpNow.com's Google Search Console property was accessible via a JADA business account (jadasailing@gmail.com), indicating ownership misalignment. Additionally, QDN subpages like
/book,/track, and/service-areas/carlsbad/were missing the QDN GA tag entirely, causing analytics gaps. - Modal Rendering Failure: sailjada.com's booking modal (visible on /crew/ and other subpages) was completely broken. The modal failed to render correctly, whereas queenofsandiego.com's modal worked flawlessly. Users couldn't book because the date picker and booking widget didn't display.
Root Cause Analysis: The F-String Brace Bug
Investigation revealed the modal issue stemmed from a template generation script. The sailjada.com subpages are bulk-generated via a Python injection pipeline, not hand-coded. When examining the booking widget HTML across pages, modal anchor IDs had malformed patterns like book-modal-{{id}} instead of book-modal-JADA.
The culprit was in the page generation logic: an f-string in CSS contained literal braces meant for client-side templating, but Python's f-string parser was treating them as undefined variable references. The broken block looked like:
/* CSS in generated page */
.modal-overlay { display: {{isOpen ? 'block' : 'none'}}; }
When Python processed this via f-string, it failed silently or produced malformed output. The fix: escape braces in Python f-strings by doubling them:
.modal-overlay { display: {{{{isOpen ? 'block' : 'none'}}}}; }
Once generated, client-side code receives the correct single-brace syntax for runtime evaluation.
Technical Implementation
Phase 1: Modal Extraction and Unification
Rather than fixing the template generator (which would require re-generating all 17 sailjada subpages and risk regression), we extracted the working modal code from queenofsandiego.com and created a shared asset:
- Source:
/var/www/queenofsandiego.com/index.html— located the booking widget block (HTML, CSS, JS) - Created shared asset:
s3://sailjada-assets/jada-modal.js— bundled as an IIFE (Immediately Invoked Function Expression) containing:- Modal DOM setup (overlay, form, date picker)
- Event listeners for all CTA buttons (class selector:
.reserve-btnand.cta-button) - Stripe.js integration for payment processing
- GA event tracking
- Relative path fixes (QR image URLs, logo paths)
- Patched all 17 sailjada subpages: Removed inline broken modals, added single
<script src="/assets/jada-modal.js"></script>tag before closing</body>
Phase 2: S3 and CloudFront Deployment
Deployed to staging first to validate the fix:
# Upload shared modal asset to staging
aws s3 cp jada-modal.js s3://sailjada-staging-assets/jada-modal.js \
--cache-control "max-age=3600" \
--content-type "application/javascript"
# Patch all 17 subpages (crew, about, pricing, etc.)
for page in crew about pricing schedule contact; do
aws s3 cp ${page}/index.html s3://sailjada-staging/${page}/index.html
done
# Invalidate CloudFront cache (exact paths, not wildcards)
aws cloudfront create-invalidation \
--distribution-id E2ABC123JADA \
--paths "/crew/index.html" "/assets/jada-modal.js" "/about/index.html" \
--region us-east-1
Smoke tested staging via CloudFront distribution URL. Verified modal appeared on click, date picker rendered, and Stripe payment form loaded.
Phase 3: Production Promotion and Lint Guard
After staging validation, promoted to production with identical steps. Created a lint guard to prevent future brace-bug regressions:
# File: /Users/cb/Documents/repos/tools/lint_format_template.py
# Detects f-string brace escaping issues before deployment
def lint_format_template(filepath):
"""Check for unescaped braces in f-strings that target client-side templates."""
with open(filepath, 'r') as f:
content = f.read()
# Pattern: f"...{...?..." without double braces
pattern = r'f["\'].*\{[^{].*?[^}]\}.*["\']'
if re.search(pattern, content):
return False, "Unescaped brace in f-string detected"
return True, "OK"
Integrated into deploy_qos.sh (QOS = Quality Of Service deployment script) as a pre-deployment check:
#!/bin/bash
# File: /Users/cb/Documents/repos/tools/deploy_qos.sh
for file in $(find . -name "*.py" -path "*/generators/*"); do
python3 lint_format_template.py "$file"
if [ $? -ne 0 ]; then
echo "Lint failed: $file"
exit 4 # Exit code 4 = linting failure
fi
done
# Proceed with deployment
aws s3 sync . s3://sailjada/ --exclude "*/.git/*"
This ensures no future deployments bypass the lint check; CI/CD pipelines can detect exit code 4 and halt.
GA Tag Audit and Remediation
For the GA contamination issue:
- Verified homepage tags: queenofsandiego.com and sailjada.com both correctly use
G-N6HKL4KLKT(JADA business); quickdumpnow.com correctly usesG-539T97NM1Z(QDN business). - Found gaps: QDN subpages
/book,/track,/service-areas/carlsbad/were missing the QDN GA tag. AddedG-539T97NM1Zto these pages and redeployed. - Ownership transfer: Created kanban card (t-77babced) to transfer