Blueprint overview
GA4 Traffic Report
Pull GA4 acquisition, engagement, and cohort-retention data through an API connection point and turn it into chart-ready, day-by-day structured insights.
Best for
Marketing · Growth · Founders
Runs with
Google Analytics 4 · Acquisition · Retention cohorts
At a glance
04
Outputs
01
Capabilities
03
Teams
Core outputs
Acquisition insights
Engagement insights
Retention cohorts
Chart-ready rows
Capability requirements
What it solves
Clicking through GA4 every week, hand-copying numbers into a deck. Instead of a typed dataset.
A repeatable blueprint. Not a weekly manual export.
Raw numeric values preserved — charts you can actually trust.
Chart-ready rows, dropped straight into a report.
Workflow
Fetch acquisition, engagement, and cohort-retention reports from GA4.
Aggregate each into per-day chart rows with exact numeric values.
Return structured summaries and trends for acquisition, engagement, retention.
Implementation
Review the underlying FML Blueprint— the sessions, tools, and typed schemas that define this workflow — and see exactly how it is instructed for repeatable execution.
FML Blueprint
google-analytics.fml
96 lines
system(`You are an expert data analyst. Review the provided Google Analytics 4 data and generate clear, insightful, structured reports for the end user. When extracting rows for chart data, preserve raw numeric values verbatim — never round or invent figures. `) parameter("property", type=string, default="484780505") # A Google Analytics GA4 property identifier (numeric ID only, e.g. 484780505). require apicp google_analytics call("google_analytics_runReport") -> acquisitionData { property = "{{ .params.property }}" body = {dateRanges: [{startDate: "7daysAgo", endDate: "today"}], dimensions: [{name: "date"}, {name: "firstUserDefaultChannelGroup"}], metrics: [{name: "newUsers"}, {name: "sessions"}, {name: "totalUsers"}], orderBys: [{dimension: {dimensionName: "date"}}]} } call("google_analytics_runReport") -> engagementData { property = "{{ .params.property }}" body = {dateRanges: [{startDate: "7daysAgo", endDate: "today"}], dimensions: [{name: "date"}, {name: "sessionDefaultChannelGroup"}], metrics: [{name: "engagedSessions"}, {name: "engagementRate"}, {name: "averageSessionDuration"}, {name: "screenPageViews"}], orderBys: [{dimension: {dimensionName: "date"}}]} } # Retention uses a `code:` block instead of declarative args because GA4 # cohortSpec requires absolute YYYY-MM-DD dates (relative "7daysAgo" # strings are rejected). Diaphora's `{{ .params.X }}` substitution only # works on top-level args, not deeply-nested body fields, so the dates are # computed in JS at runtime here and passed to the apicp tool with a fully # resolved body. call("ga_runReport_retention") -> retentionData { property = "{{ .params.property }}" code( const today = new Date(); const sevenDaysAgo = new Date(); sevenDaysAgo.setDate(today.getDate() - 7); const fmt = (d) => d.toISOString().slice(0, 10); runFunction("google_analytics_runReport", { property: args.property, body: { cohortSpec: { cohorts: [{ name: "last_7_days", dimension: "firstSessionDate", dateRange: { startDate: fmt(sevenDaysAgo), endDate: fmt(today), }, }], cohortsRange: { granularity: "DAILY", endOffset: 6 }, }, dimensions: [{ name: "cohort" }, { name: "cohortNthDay" }], metrics: [ { name: "cohortActiveUsers" }, { name: "cohortTotalUsers" }, ], orderBys: [{ dimension: { dimensionName: "cohortNthDay" } }], }, }); ) } session("analyze_acquisition", target="acquisition") { - Analyze the following Google Analytics User Acquisition data (last 7 days, broken down by date AND channel) and extract structured insights. For `summary` and `keyChannels`: identify the top performing acquisition channels across the entire week (aggregate newUsers across days). For `data` (chart-ready rows): emit ONE row per day, in chronological order. `label` = a short date like "Nov 19" derived from the `date` dimension (GA returns YYYYMMDD strings — convert to "MMM D"). `value` = the SUM of `newUsers` across ALL channels for that day (integer). `detail` = the top channel that day plus its share, e.g. "Direct led with 58 (62%)". Data: {{ .vars.acquisitionData }} schema { summary: string # Executive summary of acquisition performance. keyChannels: string[] # Top performing acquisition channels based on new users and sessions. data: { label: string # Channel name (e.g. "Organic Search", "Direct", "Referral"). value: int # New users for this channel (integer, taken directly from the report). detail?: string # Secondary metrics for this channel (e.g. sessions, total users). }[] } } session("analyze_engagement", target="engagement") { - Analyze the following Google Analytics Engagement data (last 7 days, broken down by date AND channel) and extract structured insights. For `summary` and `topChannels`: identify the top channels driving engaged sessions across the entire week. For `data` (chart-ready rows): emit ONE row per day, in chronological order. `label` = a short date like "Nov 19" (convert YYYYMMDD → "MMM D"). `value` = the SUM of `engagedSessions` across ALL channels for that day (integer). `detail` = an engagement-rate hint for that day, e.g. "engagement rate ~64.2% · avg session 1m 42s". Data: {{ .vars.engagementData }} schema { summary: string # Analysis of engagement metrics. topChannels: string[] # Channels driving the most engaged sessions. data: { label: string # Channel name. value: int # Engaged sessions for this channel (integer, taken directly from the report). detail?: string # Engagement rate, average session duration, and pageviews for this channel. }[] } } session("analyze_retention", target="retention") { - Analyze the following Google Analytics Retention/Cohort data (last 7 days) and extract structured insights AND chart-ready rows. For each cohortNthDay bucket, emit a `data` row with `label` = "Day N" (e.g. "Day 0", "Day 1") and `value` = the raw `cohortActiveUsers` count (integer). Put a short detail like "of 3,201 cohort users · 24.1% retained" in `detail`. Data: {{ .vars.retentionData }} schema { summary: string # Summary of user retention over the 7 day cohort. retentionTrend: string # Trend analysis of retention. data: { value: int # Active users in this cohort day (integer). detail?: string # Cohort size and retention percentage. label: string # Cohort day label (e.g. "Day 0", "Day 1"). }[] } }