Diagnosing and Resolving a Multi-Site Deployment Pipeline: GA4 Integration, Booking Widget Fixes, and Daemon Health Monitoring

This session involved debugging and deploying updates across three separate properties while simultaneously diagnosing infrastructure health issues on our Lightsail orchestrator daemon. The work touched GA4 analytics integration, front-end template rendering bugs, and remote service diagnostics—each requiring a different approach but all pointing back to our core deployment and monitoring practices.

What Was Done

  • Debugged and fixed a Jinja2/template rendering issue in the booking widget on sailjada.com/index.html
  • Deployed corrected markup to staging and production CloudFront distributions
  • Created and deployed a new SEO landing page for 86from.com (renamed from 86dfrom.com
  • Established Google Analytics 4 (GA4) API authentication for the dangerouscentaur account across multiple properties
  • Diagnosed jada-agent orchestrator daemon health on Lightsail instance 34.239.233.28, identifying a persistent OAuth token expiration issue

Technical Details: Template Rendering Bug and Fix

The core issue was in /Users/cb/Documents/repos/sites/sailjada.com/index.html. The booking widget contained unescaped double-brace syntax ({{ }}) intended for client-side JavaScript template processing, but the HTML was being parsed by our server-side templating engine first, causing a conflict.

Root Cause: Double braces outside of a properly escaped context triggered Jinja2 variable interpolation, which failed silently or threw parsing errors when the engine couldn't resolve the variable names.

Solution: We performed a surgical replacement of all {{ and }} sequences within the booking widget section only—converting them to single braces where they served as literal output markers. The key decision was to limit the scope: rather than globally replacing all double-braces (which could break legitimate template logic elsewhere), we:

  • Located the booking widget JavaScript block by identifying its script tag line numbers
  • Extracted only that section for syntax validation
  • Applied brace replacement only within that defined boundary
  • Re-validated the JavaScript AST before deployment

This approach prevented accidental breakage of other template logic while fixing the immediate rendering issue. The corrected file was deployed to the staging S3 bucket first, with CloudFront cache invalidation applied immediately afterward.

SEO Page Deployment and Directory Restructuring

The property at 86dfrom.com was renamed to 86from.com to match a preferred domain naming convention. Rather than maintaining two separate site directories, we:

  • Renamed the local directory from /Users/cb/Documents/repos/sites/86dfrom.com to /Users/cb/Documents/repos/sites/86from.com
  • Created a new SEO-focused landing page at /Users/cb/Documents/repos/sites/86from.com/site/what-does-86d-mean
  • Updated the primary index.html with improved metadata and internal linking
  • Deployed the updated site structure to S3 and invalidated the CloudFront distribution cache

The new SEO page targets the long-tail search query "what does 86d mean," capturing organic traffic for users searching for industry terminology. The page was structured with proper heading hierarchy, semantic HTML5 tags, and internal links back to the main property—standard SEO practices but critical for discoverability.

GA4 Analytics Authentication Architecture

To pull analytics data programmatically for the dangerouscentaur Google account across multiple properties, we implemented OAuth 2.0 service account authentication via /Users/cb/Documents/repos/tools/auth_ga.py.

Architecture Decision: Rather than storing bearer tokens directly, we:

  • Used the Google OAuth2 library (google-auth-oauthlib) to manage token refresh automatically
  • Stored client credentials (client_id and client_secret) in a secure, permissions-locked secrets file
  • Implemented token caching to minimize re-authentication calls
  • Queried the GA4 Data API to enumerate all properties under the account programmatically

This eliminated manual property discovery and created a self-service analytics pipeline. Commands like the following became possible:

python3 ~/Documents/repos/tools/auth_ga.py --account dangerouscentaur@gmail.com
# Returns: list of GA4 properties with their measurement IDs

We pulled a full 7-day analytics report for 86from.com (formerly 86dfrom.com) to establish a baseline for organic traffic and user behavior post-deployment.

Infrastructure: Lightsail Daemon Diagnostics

The jada-agent orchestrator daemon running on Lightsail instance 34.239.233.28 required health verification. Since the private SSH key wasn't available locally, we used AWS Lightsail's temporary credential API to generate ephemeral access credentials, then SSH'd in to inspect the running service.

Commands executed (redacted):

# Check service status
systemctl status jada-agent.service

# Verify daemon uptime and resource usage
ps aux | grep jada-agent
free -h
df -h

# Pull recent logs for errors
journalctl -u jada-agent.service --since "2 hours ago"

# Query task queue and session counts
# (Application-specific health checks)

Findings:

  • Service Health: jada-agent.service is active and running since May 10 (3 days uptime)
  • Resource Usage: CPU ~0.65%, Memory 144MB/914MB, Disk 6.2GB/39GB (17% used) — all healthy
  • Load Pattern: Three agent sessions ran today; two hit the 30-turn Claude API limit (exit code 1, but non-fatal); one completed successfully and processed task items
  • Critical Issue: The port_sheet_sync.py OAuth token for Google Sheets integration expired, causing 30-minute sync operations to fail with HTTP 400 Bad Request errors since at least this afternoon

Key Decisions and Rationale

Why we limited template brace replacement to the booking widget only: Global find-and-replace of double-braces could break legitimate Jinja2 template logic elsewhere in the codebase. A surgical, scoped fix reduced risk and was easier to audit.

Why we renamed 86dfrom.com to 86from.com: Shorter, more memorable domain names improve brand recall and are easier to type. The rename aligned with the property's marketing goals and required only a local directory rename plus CloudFront invalidation—no DNS changes were necessary because the old domain redirected to the new one via a 301 HTTP status check we performed beforehand.

Why we used temporary Lightsail credentials instead of storing persistent SSH keys: Storing long-lived SSH keys introduces rotation overhead and security risk. AWS's temporary credential API (valid for ~600 seconds) provides just-in-time access without persistent secrets in the filesystem.