Skip to main content

AQL Journey

Purpose: Client journey analytics for Aqualona (AQL) ecommerce. Joins GA4 behavioural data with Shopify orders and customers to answer: where did this person come from, what did they do, and which campaign should get credit?

Where it runs: Google Cloud Run behind Cloudflare Access at aqljourney.pacing.agency. One Cloud Run instance per client (not multi-tenant in a single runtime).

Last verified: July 2026


Quick Reference​

FeatureCapability
Order explorerEvery Shopify order with attribution (_c_aql, gclid, fbclid, utm_*) and one-click GA4 journey
Customer lookupResolve Shopify customer to GA4 journey via _c_aql (written to GA4 user_id) or click IDs
ReportsEcommerce funnel, revenue, and channel mix
HealthGA4 freshness, user_id coverage, order match rate
ContentRetainer deliverables tracked against UTMs and discount codes
API + MCP/api/v1 REST API and MCP server for agent workflows

Overview​

AQL Journey is the live ecommerce deployment of the Pacing Journey CORE engine (core/ in the monorepo). The engine is client-agnostic; Aqualona supplies Shopify adapters and ClientConfig while FFI and other clients can share the same codebase without forking.

Key capabilities:

  • Orders and customers — Shopify mirror in BigQuery with MERGE upserts (permanent history beyond Shopify's ~60-day API window)
  • GA4 matching — _c_aql as primary user_id, with fallbacks via gclid, msclkid, and li_fat_id
  • Dual-hostname GA4 queries — aqualona.com and shop.aqualona.com (checkout events require both)
  • Ads reporting — 15 Google Ads reports, full-funnel blended view, daily scrape to BigQuery
  • AI chat — Gemini function-calling with 13 tools on /chat

Account Access​

  • Production URL: aqljourney.pacing.agency
  • Authentication: Cloudflare Access (Google SSO for authorised users)
  • Admin: /admin gated by BigQuery-backed allow-list (pacing_tool.admin_users)
  • API: X-API-Key header on /api/v1 (BQ-backed key table; PJ_API_KEY env fallback for dev)
  • Account type: CLIENT_ACCESS, INTERNAL

Technology Stack​

LayerTechnology
UIFlask (server-rendered Jinja templates)
APIFastAPI at /api/v1, mounted onto Flask
ServerGunicorn (Dockerfile)
GA4 dataBigQuery aql-web1.analytics_470464738
Shopify dataBigQuery aql-web1.shopify1 (orders, customers via daily sync)
AIGemini via Vertex AI (google-genai)
AuthCloudflare Access JWT (core/auth.py)
MCPclients/aql/mcp_server.py (FastMCP)
DeploymentGoogle Cloud Run + Cloudflare Access

Repository​

  • Source: Pacing-Agency/aql-journey
  • Engine: shared core/ package (client-agnostic; never hard-codes AQL)
  • Client config: clients/aql/config.py, clients/aql/adapters.py, clients/aql/main.py
  • Operator docs: docs/HANDBOOK.md, docs/DEPLOY.md

Data Architecture​

GA4 export ──────────────────â–ē aql-web1.analytics_470464738
Shopify orders + customers ──â–ē aql-web1.shopify1 (daily MERGE upsert)
│
Order note_attributes: â–ŧ
_c_aql, gclid, fbclid, utm_* → direct GA4 match
  • Primary identifier: GA4 user_id = _c_aql (first-party cookie from OPT-GTM-ECOM)
  • Shopify sync: connectors/shopify_to_bq/sync.py — accumulating MERGE, never WRITE_TRUNCATE
  • Hostname filter (mandatory): device.web_info.hostname IN ("aqualona.com", "shop.aqualona.com")

Local Development​

git clone https://github.com/Pacing-Agency/aql-journey.git
cd aql-journey

python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt

gcloud auth application-default login # quota project: aql-web1

cp .env.example .env # CF_DEV_MODE=true bypasses CF Access locally
set -a && . .env && set +a
PORT=8090 python clients/aql/main.py # http://localhost:8090

GA4, Shopify, and AI calls degrade gracefully without credentials so the UI loads for view development.


Deployment​

PJ_CLIENT=aql ./deploy.sh

Push to main also triggers .github/workflows/deploy.yml (Cloud Run build + deploy). The runtime service account needs BigQuery Job User + Data Viewer on aql-web1 and Vertex AI access if AI summaries are enabled.


CI / CD​

WorkflowTriggerPurpose
deploy.ymlPush to mainBuild and deploy aql-journey to Cloud Run
shopify-sync.ymlDailyShopify → BigQuery MERGE upsert (--delta-days 2)
ads-scrape.ymlDaily 07:00 UTCGoogle Ads → BigQuery scrape
audiences-warm.ymlDailyAudience snapshot warm-up
health-check.yml, ga4-export-check.ymlScheduledData health monitors


Last Updated: July 2026
Owner: Ben Power
Status: Active (production)