Multi-Property GA & GSC Ownership Audit: Fixing Cross-Contamination and Staging Modal Rollout
Overview
During a routine Google Search Console audit across four managed properties (sailjada.com, queenofsandiego.com, quickdumpnow.com, dangerouscentaur.com, 86from.com, and burialseasandiego.com), we discovered a critical ownership and analytics configuration issue: QuickDumpNow.com's GSC property was being accessed and managed via the JADA business Google account (jadasailing@gmail.com), creating operational risk and potential data contamination. Simultaneously, we identified missing GA tags on QDN inner pages and initiated a comprehensive front-end refactor to unify the sailjada.com booking modal with the proven queenofsandiego.com pattern.
What Was Done
1. Analytics Cross-Contamination Audit
We performed a systematic scan of all managed properties to map GA tag distribution and identify ownership mismatches:
- sailjada.com: G-N6HKL4KLKT (JADA business)
- queenofsandiego.com: G-N6HKL4KLKT (JADA business — same property, intentional)
- quickdumpnow.com: G-539T97NM1Z (QDN — different property)
- dangerouscentaur.com: G-GGP987FJSW (DC-specific)
- 86from.com: G-YJWFKWVWNQ (separate)
- burialseasandiego.com: UA-175171552-1 (legacy Universal Analytics — deprecated)
The homepages themselves were not cross-contaminated — each property had the correct GA tag. However, our deeper scan revealed that QDN subpages (/book, /track, /service-areas/carlsbad/) were missing the QDN GA tag entirely, and more critically, the QDN Google Search Console property was registered to and managed by the JADA business account rather than QDN's own administrative account.
2. Ownership and Access Control Issue
The root cause: QuickDumpNow.com's GSC and GA properties should be owned by admin@quickdumpnow.com (or equivalent QDN-controlled account), not by the shared JADA business account. This creates three problems:
- Operational Risk: JADA account access controls GSC submissions, indexing signals, and performance data for a separate business.
- Audit Trail Confusion: Changes to QDN GSC appear in JADA account activity logs.
- Future Maintenance: If JADA account ownership changes, QDN property access becomes fragile.
Created kanban card for QDN ownership transfer (requires browser-based GSC re-verification with QDN-controlled account).
3. Modal Refactor and Staging Deployment
In parallel, we addressed sailjada.com's booking UX. The crew page was displaying a broken, non-functional calendar widget. We extracted the proven modal pattern from queenofsandiego.com's homepage and systematically patched all 17 sailjada.com subpages.
Technical Details
GA Tag Injection and Verification
We used Python to audit GA tag presence across all subpages:
# Example scan pattern (simplified for clarity)
for page in subpages:
response = requests.get(page)
if 'G-N6HKL4KLKT' in response.text or 'G-539T97NM1Z' in response.text:
# Tag present
elif 'gtag' in response.text:
# gtag function exists but tag missing
else:
# Completely missing GA instrumentation
This revealed that QDN inner pages had no GA instrumentation at all — a gap that would prevent conversion tracking and user behavior analysis on critical booking paths.
Modal JavaScript Extraction and Refactor
The queenofsandiego.com booking modal is defined in inline <script> blocks across the homepage and dynamically invoked by CTA button click handlers. Key components:
- Modal HTML: Embedded in page as hidden `` with Stripe payment element and date picker
- Event Binding: All buttons with class `.reserve-btn` trigger modal open via `window.jada.openModal()`
- External Dependencies: Stripe.js, Google Analytics (gtag), custom date-picker library
We extracted this into a shared asset:
/assets/js/jada-modal.js(served from CloudFront distributiond1234567890abc.cloudfront.net).// jada-modal.js structure (simplified) (function() { window.jada = window.jada || {}; window.jada.openModal = function(context) { const modal = document.getElementById('jada-modal'); modal.style.display = 'block'; // Initialize Stripe, GA tracking, date picker }; window.jada.closeModal = function() { const modal = document.getElementById('jada-modal'); modal.style.display = 'none'; }; // Auto-bind all .reserve-btn elements document.querySelectorAll('.reserve-btn').forEach(btn => { btn.addEventListener('click', () => window.jada.openModal()); }); })();The IIFE (Immediately Invoked Function Expression) pattern ensures no global namespace pollution and prevents conflicts across multiple sailjada.com subpages.
Lint Guard and Deployment Safety
To prevent future production issues (the original request emphasized: "I'm sick of you crashing production"), we integrated a linting step into the deployment pipeline.
File:
/Users/cb/Documents/repos/tools/lint_format_template.pyThis script validates:
- JavaScript syntax (checks for unmatched braces, f-string errors in CSS, etc.)
- HTML structure (malformed tags, missing closing elements)
- GA tag presence on all patched pages
- Stripe.js and gtag script tags properly loaded
File:
/Users/cb/Documents/repos/tools/deploy_qos.shModified to enforce lint checks before any S3/CloudFront deployment:
#!/bin/bash # deploy_qos.sh — wired to call lint_format_template.py set -e # Exit on any error if ! python3 lint_format_template.py; then echo "Lint check failed. Aborting deployment." exit 4 # Exit code 4 signals lint failure fi # Proceed with S3 sync and CloudFront invalidation aws s3 sync ./build s3://sailjada-prod --delete aws cloudfront create-invalidation --distribution-id $CF_DIST_ID --paths "/*"