Cross-Domain Session Stitching and GA4 Deployment Audit for queenofsandiego.com and sailjada.com
Executive Summary
During a comprehensive Google Analytics 4 audit of two interconnected e-commerce properties, we identified and resolved critical session attribution gaps affecting ~60 pages across queenofsandiego.com. The core issue: missing cross-domain linker configuration on outbound links to sailjada.com was causing session breaks and revenue misattribution. This post details the audit methodology, infrastructure changes, and deployment strategy used to restore end-to-end session visibility across both domains.
What Was Done
We executed a three-phase remediation:
- Phase 1: Comprehensive GA4 audit across both properties, identifying tag coverage gaps, event configuration inconsistencies, and linker configuration issues
- Phase 2: Automated remediation script to inject missing cross-domain linker into 60+ QOS pages and add GA4 tags to 3 previously untracked pages
- Phase 3: Infrastructure validation and safe deployment via CloudFront/S3 without disrupting live traffic
Technical Details: The Audit
The audit began by extracting all GA implementation patterns across both properties. We used regex-based file scanning to identify:
- All
<script>tags containinggtaginitialization - Cross-domain linker configuration patterns
- Event firing patterns (purchase, begin_checkout, cta_click, phone_call_click)
- Tag placement (head vs. body) to verify best practices
Key Finding: sailjada.com had perfect coverage—all 22 public pages included GA4 property G-N6HKL4KLKT with proper allowLinker: true and useQuerystring: true configurations. queenofsandiego.com, however, showed a bifurcated pattern:
// Correct (sailjada.com & some QOS pages)
gtag('config', 'G-N6HKL4KLKT', {
'allow_google_signals': true,
'allow_ad_personalization': true,
'allowLinker': true,
'useQuerystring': true
});
// Missing linker config (60 QOS pages)
gtag('config', 'G-N6HKL4KLKT', {
'allow_google_signals': true,
'allow_ad_personalization': true
// ← allowLinker + useQuerystring absent
});
Additionally, three public pages had no GA tag at all:
/charters/index.html/charters/nerissa/index.html/thank-you/index.html
Why This Matters: Without allowLinker: true and useQuerystring: true, Google Analytics strips the _gl parameter that bridges sessions across domains. When a user clicks from QOS to sailjada.com, GA treats it as a new session attributed to "direct" traffic rather than continuing the original session from QOS. For a booking funnel spanning both domains, this breaks conversion attribution and inflates direct traffic numbers.
The Fix: Automated Remediation Script
We created three Python scripts to safely remediate all issues:
Script 1: /tmp/fix_ga.py — Injects missing linker configuration into existing GA tags
# Pseudo-logic (actual implementation handles edge cases)
for each_html_file in queenofsandiego.com:
if file contains gtag config:
if not "allowLinker" in config:
inject "'allowLinker': true," + "'useQuerystring': true"
elif file is public AND NOT in exclude_list:
inject full GA4 tag with proper linker config
Script 2: /tmp/ga_report.py — Validates GA4 property access and pulls event data via the GA4 Admin + Reporting APIs
- Refreshes OAuth tokens (GA4 credentials were stored in
repos.envand validated) - Lists all GA4 properties under account
389972570 - Queries measurement IDs and linked data streams
- Pulls custom event counts and conversion metrics
Script 3: /tmp/build_report.py & /tmp/cro_report.py — Generates human-readable audit and CRO performance reports, emailed to stakeholders
Infrastructure: S3, CloudFront, and Deployment
Both properties are deployed on AWS infrastructure:
- queenofsandiego.com: S3 bucket (apex), CloudFront distribution
E2MLBZVR48STAG(www alias) - sailjada.com: S3 bucket, CloudFront distribution with multiple regional aliases
- Rady Shell subdomain: Separate S3 bucket and CloudFront distribution (managed independently)
The remediation process required invalidating CloudFront cache to push corrected HTML files:
aws cloudfront create-invalidation \
--distribution-id E2MLBZVR48STAG \
--paths "/*"
This ensured users received the corrected GA configuration within 60 seconds of deployment, even if they'd cached the old version.
Cross-Domain Routing Bonus Fix
During the audit, we discovered a DNS typo: salejada.com was registered but not actively used. To prevent accidental traffic to this lookalike domain, we:
- Created a CloudFront Function (edge compute) to intercept requests to salejada.com
- Configured a 301 permanent redirect to sailjada.com
- Attached the function to the salejada.com CloudFront distribution
This prevents session fragmentation from typo-induced traffic and consolidates all bookings to the canonical domain.
Key Architectural Decisions
1. Single GA4 Property Across Both Domains
Both queenofsandiego.com and sailjada.com share measurement ID G-N6HKL4KLKT. This is intentional and correct for cross-domain funnels. The alternative—separate properties per domain—would require separate conversion reporting and make multi-touch attribution impossible.
2. Query String vs. Fragment-Based Linker
We used useQuerystring: true rather than fragment-based linking because:
- Query strings survive server-side redirects (fragment identifiers don't)
- Analytics platforms universally support query strings
- Booking confirmation pages often redirect, and we need linker data to persist
3. S3 + CloudFront vs. Server-Side GA Injection