Skip to main content
Settings
Search
Appearance
Theme Mode
About
Jekyll v3.10.0
Environment Production
Last Build
2026-06-18 05:38 UTC
Current Environment Production
Build Time Jun 18, 05:38
Jekyll v3.10.0
Build env (JEKYLL_ENV) production
Quick Links
Page Location
Page Info
Layout quest
Collection quests
Path _quests/1010/automate-traffic-report.md
URL /quests/1010/automate-traffic-report/
Date 2026-06-14
Theme Skin
SVG Backgrounds
Layer Opacity
0.6
0.04
0.08

Automate a Weekly Traffic Report

Build a standalone analytics digest script and schedule it with launchd or cron to post a weekly traffic report as a dated file and a GitHub issue.

🔥 Lvl 1010Warrior 🏰 Main Quest 🔴 Hard 60-90 minutes

Automate a Weekly Traffic Report

Turn an on-demand query into a hands-off weekly digest that shows up where you work.

Primary Tech
🛠️ automation
Skill Focus
Devops
Series
Measure & Master Your Site
Author
Quest Master IT-Journey
XP Range
⚡ 4500-5250

📖 The Legend Behind This Quest

A report you have to remember to run is a report you never run. In this final quest of the path you’ll turn the on-demand queries from the last quest into a hands-off weekly digest — a small script the scheduler runs for you, dropping a Markdown summary on disk and opening a GitHub issue so the numbers show up where you already work.

🎯 Quest Objectives

Primary Objectives (Required for Quest Completion)

  • Write a standalone Node script that queries GA and writes a Markdown digest
  • Deliver it as a dated file and a GitHub issue
  • Schedule it weekly with launchd (macOS) or cron (Linux)

Secondary Objectives (Bonus Achievements)

  • Filter the report to production traffic only
  • Add a week-over-week comparison

Mastery Indicators

  • You know why a cloud scheduler can’t reach a local key
  • Your job uses absolute paths and a defined environment

🗺️ Quest Prerequisites

📋 Knowledge Requirements

🛠️ System Requirements

  • Node.js 18+, the gh CLI authenticated, and a scheduler

🏗️ Chapter 1: A Self-Contained Digest Script

The script reads the same service-account key from ~/.config/gcloud/ (never the repo), queries GA, and writes Markdown. Keep it standalone so it doesn’t depend on your agent being online.

const fs = require("fs");
const os = require("os");
const path = require("path");
const { execFileSync } = require("child_process");
const { BetaAnalyticsDataClient } = require("@google-analytics/data");

const key = require(path.join(os.homedir(), ".config/gcloud/ga-reader.json"));
const client = new BetaAnalyticsDataClient({
  credentials: { client_email: key.client_email, private_key: key.private_key },
});
const property = "properties/" + process.env.GA_PROPERTY_ID;
const HOST = { filter: { fieldName: "hostName",
  stringFilter: { matchType: "EXACT", value: "your-site.dev" } } };

async function main() {
  const [r] = await client.runReport({
    property,
    dimensionFilter: HOST,
    dateRanges: [{ startDate: "7daysAgo", endDate: "today" }],
    metrics: [{ name: "activeUsers" }, { name: "sessions" }, { name: "screenPageViews" }],
  });
  const m = (r.rows?.[0]?.metricValues || []).map(v => v.value);
  const today = new Date().toISOString().slice(0, 10);
  const md = `# Weekly traffic — week ending ${today}\n\n` +
    `- Active users: ${m[0] ?? 0}\n- Sessions: ${m[1] ?? 0}\n- Page views: ${m[2] ?? 0}\n`;

  const dir = path.join(os.homedir(), "ga-reports");
  fs.mkdirSync(dir, { recursive: true });
  const file = path.join(dir, `report-${today}.md`);
  fs.writeFileSync(file, md);

  // Deliver as a GitHub issue (gh must be authenticated)
  execFileSync("/opt/homebrew/bin/gh", ["issue", "create", "--repo", "you/your-repo",
    "--title", `Weekly traffic — ${today}`, "--body-file", file], { stdio: "inherit" });
}
main().catch(e => { console.error(e.message); process.exit(1); });

Install the one dependency locally (outside the repo) and test it once:

npm install --prefix ~/.local/share/ga-report @google-analytics/data
GA_PROPERTY_ID=123456789 node ~/.local/share/ga-report/ga-weekly-report.js

⏰ Chapter 2: Schedule It (macOS — launchd)

A LaunchAgent runs the script on a calendar interval. Use absolute paths — scheduled jobs don’t inherit your interactive shell’s PATH.

<!-- ~/Library/LaunchAgents/com.you.ga-weekly-report.plist -->
<dict>
  <key>Label</key><string>com.you.ga-weekly-report</string>
  <key>ProgramArguments</key>
  <array>
    <string>/opt/homebrew/bin/node</string>
    <string>/Users/you/.local/share/ga-report/ga-weekly-report.js</string>
  </array>
  <key>EnvironmentVariables</key>
  <dict>
    <key>PATH</key><string>/opt/homebrew/bin:/usr/bin:/bin</string>
    <key>GA_PROPERTY_ID</key><string>123456789</string>
  </dict>
  <key>StartCalendarInterval</key>
  <dict><key>Weekday</key><integer>1</integer><key>Hour</key><integer>9</integer></dict>
</dict>
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.you.ga-weekly-report.plist
launchctl print gui/$(id -u)/com.you.ga-weekly-report | grep -i "state\|calendar"

Linux — cron

# Mondays at 09:00 — note the absolute paths and env var
0 9 * * 1 GA_PROPERTY_ID=123456789 /usr/bin/node /home/you/.local/share/ga-report/ga-weekly-report.js

☁️ Chapter 3: Why Not a Cloud Scheduler?

It’s tempting to run this as a hosted cron, but the script needs the local service-account key file. A cloud runner won’t have ~/.config/gcloud/ga-reader.json, so the job belongs on a machine that holds the key — a local launchd/cron job, or a CI runner with the key injected as a secret (never committed). Pick whichever matches where your key safely lives.

✅ Validation

  • Running the script by hand writes a dated digest and opens an issue
  • launchctl print (or crontab -l) shows the job registered
  • The report contains production-only numbers

🏆 Rewards

  • 🏆 Automation Architect — reporting now runs itself
  • Scheduler Sage — launchd/cron hold no mysteries

🎓 Path Complete

You’ve connected Google Analytics to your agent, learned to query it, and automated the reporting. Loop back to the series hub for more Monitoring & Observability quests — or read the full story in the post Auditing Site Analytics & SEO with an AI Agent and MCP.

🎁 Rewards

200 XP

Badges

  • 🏆 Automation Architect
  • ⏰ Scheduler Sage

Skills unlocked

  • 🛠️ Standalone GA Data API scripting
  • ⏰ Scheduling with launchd / cron
  • 🐙 Posting reports via the GitHub CLI

Features unlocked

  • Hands-off weekly reporting

🕸️ Quest Network

graph TD loading(["Loading quest graph…"])