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 containing gtag initialization
  • 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.env and 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