Marketing Analytics
96 lines

Plan 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

API CP

What it solves

GA4 reporting means clicking through the UI every week and hand-copying numbers into a deck instead of getting a typed, repeatable dataset.

Replaces weekly manual GA4 exports with a repeatable plan.

Preserves raw numeric values for trustworthy charts.

Returns chart-ready rows you can drop straight into a report.

Workflow

1

Fetch acquisition, engagement, and cohort-retention reports from GA4.

2

Aggregate each into per-day chart rows with exact numeric values.

3

Return structured summaries and trends for acquisition, engagement, retention.

Implementation

Review the underlying FML plan — the sessions, tools, and typed schemas that define this workflow — and see exactly how it is instructed for repeatable execution.

FML Plan

google-analytics.fml

96 lines

Copy
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").
        }[]
    }
}