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.jsIIFE 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 logicopenModalById(modalId)– modal opener (called by all CTA buttons)closeModal()– dismissal handlersetupDatePicker()– Stripe Elements + calendar bindingsubmitBookingForm()– 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:
- Lint validation: Created
/tools/lint_format_template.pyto detect f-string brace bugs and missing GA tags before deployment - Build & test in staging: Deployed all 17 subpages to
s3://jada-sailjada-staging/with CloudFront distributionE2B3C4D5E6F7G8 - Smoke testing: Verified modal open/close, date picker interaction, and form submission through CloudFront staging URL
- Production snapshot: Captured current prod state before promoting (S3 version IDs logged)
- Promotion: Synced staging files to
s3://jada-sailjada-prod/, invalidated exact CloudFront paths (not wildcards) - 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) |