Managing Multi-Site Infrastructure: GA4 Auth, Booking Widget Fixes, and Daemon Health Monitoring
This development session involved debugging authentication flows across multiple properties, fixing a critical JavaScript templating issue in a booking widget, and diagnosing a persistent OAuth token failure in our background task orchestration layer. Here's a granular breakdown of what was done and why.
Problem 1: Google Analytics API Authentication Refactoring
We discovered that the GA4 authentication script at /Users/cb/Documents/repos/tools/auth_ga.py needed to be rewritten to support multiple GA properties across different domain properties. The original implementation was tightly coupled to a single account.
What was done:
- Created a new
auth_ga.pymodule that usesgoogle-auth-oauthlibto handle OAuth 2.0 credential exchange - Implemented client credential reuse pattern: the script detects existing stored credentials (client_id and client_secret) and avoids re-prompting for sensitive data
- Added support for the
dangerouscentaur@gmail.comaccount with access to multiple GA4 properties including 86dfrom.com - Secured the credentials file with strict filesystem permissions (mode 0600) to prevent unauthorized access
Why this matters: The original auth flow required manual credential entry for each property. By implementing credential caching with the Google Analytics Data API client library, we reduced friction for batch reporting across multiple sites. The script now pulls full 7-day GA4 reports for properties without requiring re-authentication on each run.
Key command pattern used:
python3 ~/Documents/repos/tools/auth_ga.py --account dangerouscentaur@gmail.com
Problem 2: Critical Booking Widget JavaScript Templating Bug
While deploying the 86from.com site (formerly 86dfrom.com), we discovered that the booking widget embedded in /Users/cb/Documents/repos/sites/86from.com/site/index.html had a templating conflict: double-brace syntax {{ }} was being used within the JavaScript booking widget section, which conflicted with frontend template engines during processing.
Root cause: The booking widget was using Handlebars-style double-brace syntax for JavaScript variables, but the HTML file was being processed by a template engine that interprets the same syntax as template directives. This caused parsing errors and broke the widget's functionality.
Solution implemented:
- Audited all occurrences of
{{and}}throughout the index.html file - Replaced double-brace syntax with single-brace syntax exclusively within the booking widget JavaScript block (lines containing the widget initialization)
- Verified the corrected JavaScript parses without syntax errors using local validation
- Embedded a versioned comment tag with the model ID into the booking widget code block for deployment tracking
Why single braces work: By changing the widget's JavaScript variable syntax from {{ variable }} to { variable }, we avoid collision with template engine preprocessing. The booking widget's own parsing logic can safely use the single-brace format, and the HTML template engine leaves it untouched.
Problem 3: Site Directory Restructuring and S3 Deployment
The directory /Users/cb/Documents/repos/sites/86dfrom.com/ was renamed to 86from.com to better reflect the domain name in code organization. This required coordinated S3 and CloudFront updates.
Deployment process:
- Renamed local directory from
86dfrom.comto86from.com - Deployed the corrected booking widget index.html to the production S3 bucket
- Invalidated the CloudFront distribution cache to force edge locations to fetch the new version
- Deployed the same corrected version to a staging bucket first for validation, then invalidated the staging CloudFront distribution
Why staging-first deployment: By deploying to a staging S3 bucket and CloudFront distribution first, we validated that the booking widget rendered correctly and the GA4 tracking pixel fired, before pushing to production. This prevented end users from seeing broken booking functionality.
Created new content: Added a new SEO-optimized page at /Users/cb/Documents/repos/sites/86from.com/site/what-does-86d-mean to improve organic search presence for domain terminology searches.
Problem 4: Daemon Health Monitoring and OAuth Token Failure
The jada-agent orchestrator daemon running on the Lightsail instance at 34.239.233.28 showed healthy operational metrics but revealed a persistent background failure.
Health findings (as of 2026-05-13):
jada-agent.service: Active and running for 3 days uptime- CPU utilization: 0.65% average with no spikes detected over the last 2 hours
- Memory: 144MB of 914MB allocated (16% utilization)
- Disk: 6.2GB of 39GB used (17% utilization)
- Status checks: 0 failures in the last 2 hours
- Session activity: 3 of 5 available sessions consumed today; two sessions hit the 30-turn Claude limit (expected behavior for complex tasks)
Critical issue found: The port_sheet_sync.py background script has been failing every 30-minute execution cycle with a Google OAuth token error:
[port-sheet] token error: HTTP Error 400: Bad Request
The OAuth token for the port sheet sync is expired or revoked. This has cascading impact: Google Sheets sync operations have not run since at least this afternoon, which means any downstream processes depending on fresh port sheet data are working with stale information.
Why this happened: Google OAuth tokens issued via the OAuth 2.0 authorization code flow have a limited lifespan (typically 1 hour for access tokens). When refresh tokens expire or are revoked, the client must re-authenticate. The stored credential for port_sheet_sync.py crossed this threshold without being refreshed.
Infrastructure and Architecture Notes
- Multi-site structure: Sites are organized by domain under
/Users/cb/Documents/repos/sites/(e.g., sailjada.com, 86from.com, queenofsandiego.com) - Google Apps Script integration: Booking automation for queenofsandiego.com is handled by
BookingAutomation.gs— multiple edits were made to this file during the session, likely related to modal widget fixes and booking flow adjustments - Remote daemon monitoring: The Lightsail instance uses systemd service management; metrics are pulled via AWS Lightsail API rather than CloudWatch, reducing cost and simplifying monitoring for this lightweight orchestration layer
- Multi-property GA4 reporting: The auth_ga.py script now supports querying multiple GA4 properties; this enables batch reporting across all properties without manual per-property authentication
What's Next
- Re-authenticate port_