

Automated Client Reporting Presentations for Agencies (2026)
Automated client reporting presentations for agencies work in four steps: export last month's metrics from GA4, Google Ads, Meta and Search Console; compute every delta in your own code; let an LLM phrase the story around those computed numbers; and send one brief per client to the 2Slides API. Fast PPT returns an editable PPTX built on the template you picked, at 10 credits per page, so a 12-page monthly deck is 120 credits, about $0.30 on the starter pack. An account manager reviews each deck before it goes to the client.
Key takeaways
- 60 clients × a 12-page Fast PPT monthly deck = 7,200 credits, which fits inside the $12.50/month Pro plan (10,000 credits), or about $0.15 per client deck.
- A 6-page narrated two-speaker recap video on the image-designed path costs 1,870 credits (610 for slides + 1,260 for narration), about $3.74 per client at the $80 pack rate.
- Numbers are computed in code, never by the LLM; a guard rejects any narrative that contains a number not in your computed facts.
- The generation rate limit is 6 requests per minute per key, so 60 decks take about 10 minutes to submit. Schedule the run on the 2nd of the month with cron, n8n, Zapier or Make.
- Only send aggregate metrics (sessions, spend, CPA, clicks), never customer lists or personal data, and cover the processing in your client DPA.
Who this is for, and the problem it removes
You run or operate an SEO, PPC, paid social or full-service digital agency with somewhere between 20 and 200 retainer clients, and each one expects an agency monthly report presentation. You probably already have dashboards: Looker Studio reports wired to GA4 and Google Ads, or a client reporting platform such as AgencyAnalytics, DashThis or Whatagraph. Those tools are good at what they do. AgencyAnalytics, for example, advertises white-labeled automated reports, a branded client portal and an "Ask AI" feature that surfaces trends across accounts.
The gap is the monthly review meeting. A dashboard is data; a client meeting needs a story: what happened, why, what you did about it, and what you are doing next. So on the first working days of each month, account managers screenshot charts, paste them into last month's deck, rewrite the commentary, and fix the dates. At 60 clients and 60 to 90 minutes a deck, that is 60 to 90 hours of senior time every month spent on layout.
This recipe automates the deck, not the thinking. Your code produces the facts, an LLM drafts the commentary, 2Slides lays it out, and the account manager spends 10 minutes editing a finished draft instead of an hour building one.
Do not use it if your clients only want the live dashboard link, or if a deck would need raw customer-level data to make its point.
The workflow at a glance
| Step | Tool | What happens | 2Slides endpoint / credits |
|---|---|---|---|
| 1. Trigger | cron, n8n, Zapier or Make | Fires on the 2nd of the month, after platforms finalize last month | none |
| 2. Pull metrics | GA4 Data API, Google Ads API, Meta Insights API, Search Console API (or your warehouse) | One JSON per client: this month, last month, same month last year | none |
| 3. Compute deltas | Your code | MoM and YoY changes, pacing vs. budget, top movers | none |
| 4. Write the narrative | Any LLM, constrained to the computed facts | 8 to 12 titled sections, numbers copied verbatim | none |
| 5. Generate the deck | 2Slides Fast PPT, in a white label template | Editable PPTX per client | themes/search (free), slides/generate (10/page) |
| 6. Optional designed or narrated version | 2Slides image-designed path | Deck in the client's brand look, two-voice recap MP4 | create-like-this (10 + 100/page at 2K), generate-narration (210/page) |
| 7. Review and send | Account manager | Edit, add logo if needed, send or present | none |
Step 1: Pull the metrics you actually report on
Pick the 15 to 25 numbers that appear in every monthly report, not everything the platforms expose. A typical mix:
- SEO: organic sessions and key events from the GA4 Data API; clicks, impressions, CTR and average position from the Search Console searchAnalytics.query method; top 5 gaining and losing queries or pages.
- PPC: spend, conversions, CPA, ROAS and impression share by campaign type from the Google Ads API reporting interface.
- Paid social: spend, results, cost per result and the top three ads from the Meta Marketing API Insights endpoint.
- Agency context: budget for the month, work completed (from your project tool), tests running, next month's plan.
If you already centralize data in BigQuery, Supermetrics or a reporting platform's export, read from there instead. The deck job does not care where the numbers come from, only that each client resolves to one flat JSON object with current, previous and year-ago values.
Step 2: Compute deltas in code, then let the LLM write around them
This is the rule that keeps automated reports trustworthy: the LLM never does arithmetic. Your code computes month-over-month and year-over-year changes, pacing and rankings, and hands the model a list of finished facts like Organic clicks: 18,420 (+12.4% MoM, +31.0% YoY). The model's only job is to group those facts into sections and explain them in plain English: "Organic clicks grew 12.4% month over month, driven by the new pricing guides."
Two guards make this safe at 60 clients:
- A number check. Extract every number from the LLM's text and reject the narrative if any number does not appear in the computed facts. A rejected client falls back to a facts-only deck, which is still useful.
- A cause-language check in review. The model may say "driven by" when it only knows correlation. Account managers are the right people to fix that, which is why review stays mandatory.
A prompt that works well for the narrative step:
You are writing commentary for a monthly SEO and PPC client report for {client_name}.
Use ONLY the facts below. Copy every number exactly as written. Do not calculate,
round or estimate anything new. If a fact has no obvious explanation, describe it
without inventing a cause.
Return 10 sections, each with a title and 2-3 sentences (max 50 words):
1. Month at a glance 2. Organic search 3. Top organic movers 4. Paid search
5. Paid social 6. Conversions and revenue 7. Work completed 8. Tests and learnings
9. Risks and watch items 10. Next month plan
FACTS:
{facts}
WORK COMPLETED: {work_log}
NEXT MONTH PLAN: {plan}Step 3: Choose a white label template once
"White label" here means the client sees a report in your agency's brand (or theirs), with no third-party product branding. With Fast PPT, the deck is a native PPTX built from the template you choose, and the text sits in normal PowerPoint text boxes. Two things are still yours to verify, because this guide will not make claims about output it cannot see in your account:
- Check the downloaded file. Open one generated PPTX, look through every slide, the slide master and layouts, footers, and File > Info properties (author, company) before you put the pipeline into production. Fix anything you do not want a client to see in your template or in a post-processing step.
- Logos are a post-processing step. Fast PPT fills a template's text placeholders; it does not take a client logo over the API. Either keep a neutral template and let the account manager drop the logo on the title slide, or add it automatically with python-pptx after download.
Find a template with themes/search and store its themeId per client, so a law-firm client gets a sober layout and a DTC brand gets something brighter:
curl -s "https://2slides.com/api/v1/themes/search?query=business%20report&limit=5" \
-H "Authorization: Bearer $SLIDES_API_KEY"Also try query=marketing, query=minimal and query=data. The templates library is the visual version of the same search; browse it once, then pin IDs in config.

Figure 1: The templates library. Each template has a themeId; pick one per client tier and reuse it every month.
Step 4: The Node.js script (metrics in, review folder out)
The script below reads clients.json (one object per client with metrics, themeId and language), computes deltas, calls your LLM through a writeNarrative() function you supply, runs the number guard, generates one Fast PPT deck per client, and saves each PPTX to review/<month>/ with a review.csv row. Nothing is sent to a client from this script. Node 18+ is enough; it uses the built-in fetch.
// monthly-decks.mjs — node monthly-decks.mjs 2026-09
import fs from "node:fs/promises";
import { writeNarrative } from "./llm.mjs"; // your LLM call, returns a string
const API = "https://2slides.com/api/v1";
const H = { Authorization: `Bearer ${process.env.SLIDES_API_KEY}`, "Content-Type": "application/json" };
const month = process.argv[2];
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
const pct = (cur, prev) => (prev ? (((cur - prev) / prev) * 100).toFixed(1) : "n/a");
const fmt = (n) => Number(n).toLocaleString("en-US");
function buildFacts(c) {
return Object.entries(c.metrics).map(([name, m]) =>
`${name}: ${fmt(m.cur)} (${pct(m.cur, m.prev)}% MoM, ${pct(m.cur, m.yoy)}% YoY)`
);
}
// Every number in the LLM text must already exist in the facts (section numbers 1-12 excepted)
function numbersOk(text, sourceText) {
const nums = (t) => (t.match(/\d[\d,.]*\d|\d/g) ?? []).map((n) => n.replace(/[.,]$/, ""));
const allowed = new Set(nums(sourceText));
return nums(text).every((n) => allowed.has(n) || Number(n) <= 12);
}
async function generate(c, userInput) {
const r = await fetch(`${API}/slides/generate`, {
method: "POST", headers: H,
body: JSON.stringify({ userInput, themeId: c.themeId, responseLanguage: c.language ?? "English", mode: "async" }),
});
if (!r.ok) throw new Error(`generate ${r.status}`);
return (await r.json()).jobId;
}
async function waitFor(jobId) {
for (;;) {
await sleep(8000); // stays under 10 polls/min
const job = await (await fetch(`${API}/jobs/${jobId}`, { headers: H })).json();
if (job.status === "success") return job.downloadUrl;
if (job.status === "failed") throw new Error(`job ${jobId} failed`);
}
}
const clients = JSON.parse(await fs.readFile("clients.json", "utf8"));
await fs.mkdir(`review/${month}`, { recursive: true });
for (const c of clients) {
const facts = buildFacts(c);
let story = await writeNarrative(c.name, facts, c.workLog, c.plan);
const source = [...facts, c.workLog, c.plan].join("\n");
if (!numbersOk(story, source)) story = facts.join("\n"); // facts-only fallback
const userInput = `Monthly SEO and PPC report for ${c.name}, ${month}. ` +
`Audience: ${c.audience}. One key number per slide, plain language.\n\n${story}`;
const jobId = await generate(c, userInput);
const url = await waitFor(jobId);
const file = `review/${month}/${c.slug}_${jobId}.pptx`;
await fs.writeFile(file, Buffer.from(await (await fetch(url)).arrayBuffer()));
await fs.appendFile(`review/${month}/review.csv`, `${c.slug},${c.accountManager},${jobId},${file},pending\n`);
await sleep(10000); // 6 generate requests per minute per key
}For 60 clients this runs sequentially in roughly 40 to 60 minutes, including polling, which is fine for an overnight job. If you want it faster, submit all jobs first (one every 10 seconds), store the jobIds, then poll the pending set; the batch generation guide shows that pattern.
A finished 12-page deck for a B2B SaaS client looks like this in practice. Source: September exports showing organic clicks 18,420 (+12.4% MoM), Google Ads spend $14,300 at a $96 CPA (-8.1% MoM), LinkedIn spend $4,200 with CPL up 22%, 14 blog posts and a pricing-page rewrite shipped. Output: a title slide, a month-at-a-glance slide with three headline numbers, separate organic, paid search and paid social slides, a work-completed slide, a risks slide flagging the LinkedIn CPL increase, and a next-month plan. Still done by hand: inserting two native charts (the template uses text and number callouts, not your live charts), correcting one "driven by" claim the model could not know, adding the client logo, and a 10-minute read before it goes out.
Step 5 (optional): A designed deck in the client's brand, and a narrated recap
Some clients, usually the larger retainers, expect a report that looks like their own brand rather than your template. For those, use Create Slides Like This over the API: pass a public URL of one of the client's own brand slides or campaign key visuals as referenceImageUrl, and the whole design is derived from it.
curl -s -X POST https://2slides.com/api/v1/slides/create-like-this \
-H "Authorization: Bearer $SLIDES_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"userInput": "Monthly performance recap for Northwind Outdoor, September 2026. Slide 1: Month at a glance. Revenue from paid channels $212,400 (+9.8% MoM). Slide 2: ...",
"referenceImageUrl": "https://cdn.your-agency.com/clients/northwind/brand-slide.png",
"aspectRatio": "16:9",
"resolution": "2K",
"page": 6,
"contentDetail": "concise",
"responseLanguage": "English",
"mode": "async"
}'These slides are images: they look designed, but the text is not editable in PowerPoint. If the account manager needs to tweak wording after review, fix the brief and regenerate, or keep that client on Fast PPT. You get a PDF and per-page PNGs.
Once that job succeeds, generate-narration with mode: "multi" adds a two-speaker recap (for example, your account manager persona and a strategist persona discussing the month). download-slides-pages-voices returns a free ZIP of PNG and WAV files that you stitch into an MP4 with ffmpeg, or you export the video from the Workspace. The full request bodies and the ffmpeg one-liner are in the marketing campaign report decks and narrated video recipe. Fast PPT jobs cannot be narrated, so the video always comes from the image-designed path.
Clients who skip the monthly call often watch a three-minute recap. Treat it as an add-on for retainers where attendance is the problem, not a default for every account.
Step 6: Schedule it without a server
You do not need your own infrastructure to run this monthly:
- cron or GitHub Actions:
cron: "0 5 2 * *"runs at 05:00 UTC on the 2nd, after most platforms have settled last month's conversions. - n8n: a Schedule Trigger, your data nodes, an LLM node, then HTTP Request nodes for
generateandjobs/{id}with a Wait loop. The n8n and 2Slides workflow guide walks through the polling loop. - Zapier or Make: fine for 10 to 30 clients with a Google Sheet as the client list; see automate weekly reports with Zapier for the Zap structure, then change the schedule to monthly.
Whichever you use, post a message to the account management channel when the review folder is ready, with a link per client.
What it costs
Assume 60 clients, a 12-page Fast PPT deck each, plus a 6-page narrated recap for the 15 largest retainers.
| Item | Credits each | Count | Credits per month |
|---|---|---|---|
| Fast PPT monthly deck, 12 pages | 120 | 60 | 7,200 |
Designed recap via create-like-this, 6 pages at 2K | 610 | 15 | 9,150 |
| Two-speaker narration, 6 pages | 1,260 | 15 | 18,900 |
| Total | 35,250 |
- Decks only (7,200 credits): the Pro plan at $12.50/month includes 10,000 credits, so each deck costs about $0.15 and you have room for regenerations. On packs, 7,200 credits is about $18.
- Decks plus narrated recaps (35,250 credits): one $80 pack of 40,000 credits covers it, roughly $70 of credits used, or about $3.74 per narrated recap.
- A full 12-page designed and narrated deck would be 1,210 + 2,520 = 3,730 credits, about $7.46 at the $80 pack rate, which is why most agencies narrate a short recap rather than the full report.
There is no per-seat pricing, so adding account managers who only review files costs nothing. New accounts get 500 free credits, enough to test four 12-page decks end to end. Current plans are on the pricing page.
Client data handling: aggregate only, and put it in the DPA
Everything this pipeline sends to 2Slides is the text of the brief: metric names, aggregate numbers and your commentary. Keep it that way.
- Aggregate metrics only. Sessions, clicks, spend, CPA, conversion counts and top queries are fine. Customer email lists, CRM exports, order-level data, and anything identifying an individual are not, and none of it improves a monthly deck anyway.
- Watch the free-text fields. Work logs and "notes" columns are where a lead's name or an internal client complaint slips in. Filter them before they reach
userInput. - Cover it contractually. If you work with EU or UK clients, your agreement with them likely already includes data processing terms under GDPR Article 28. List the third-party AI tools in your reporting stack (your LLM provider and 2Slides) where your DPA lists sub-processors, and tell clients which data categories they receive. Some clients will ask you to anonymize their name in the brief; using the client slug in the API call and adding the name in post-processing is an easy accommodation.
- No certification claims. 2Slides does not claim SOC 2 or similar certifications. If a client's procurement requires one for every vendor that touches their data, check with them before including that account.
- Keys stay server-side. Store
SLIDES_API_KEYin your scheduler's secrets, never in a shared Sheet.
Where 2Slides is not the right tool
Be clear about the limits before you pitch this internally:
- Live, interactive reporting. Clients who want to filter by date or drill into a campaign need a dashboard: Looker Studio, AgencyAnalytics, DashThis, Whatagraph and similar tools. A generated deck is a monthly snapshot. Many agencies keep the dashboard link on the last slide.
- Native charts. Fast PPT fills a template with text and number callouts. If your clients expect the exact chart from GA4 or your BI tool, insert it by hand or with python-pptx after download.
- Editable designed decks. The
create-like-thispath produces image slides. They look like the client's brand but are not editable text. - Deep in-app editing in a design tool. Canva and Gamma are stronger if your team wants to rework layouts visually in a browser after generation; Microsoft Copilot in PowerPoint is a better fit for one-off edits inside a deck your account manager already owns. Neither replaces a pipeline that builds 60 decks overnight, but if you have five clients, doing it by hand in one of them is reasonable.
- Judgment. The model will not know that conversions dipped because the client's checkout broke for three days. Review is not optional.
For broader context on how other teams use the same endpoints, see AI presentation API use cases by team and the overview of how marketing teams build decks at scale. If you want to offer report decks inside your own client portal or reporting product, integrating AI slide generation into a SaaS product covers multi-tenant keys and credit handling.
FAQ
Can I automate white label client report decks without a developer?
Yes, for up to about 30 clients. Use Zapier, Make or n8n with a Google Sheet of computed metrics per client, an LLM step for commentary, and HTTP steps for the 2Slides generate and jobs endpoints. Past that volume, a short script is easier to maintain and debug.
Does the generated PPTX show 2Slides branding?
Fast PPT builds the deck from the template you choose, as native PowerPoint text boxes. Before you send anything to clients, open a downloaded file and check every slide, the slide master and the file properties yourself, and adjust your template or post-processing if anything needs to change.
How do I stop the AI from getting the numbers wrong in SEO and PPC client report slides?
Compute every number in code and pass the model finished facts with an instruction to copy them verbatim. Then extract all numbers from its output and reject any narrative that contains a number not in your facts. Fall back to a facts-only deck when the check fails.
How much does an agency monthly report presentation cost to generate?
A 12-page Fast PPT deck is 120 credits: about $0.30 on the $5 pack or $0.15 on the Pro plan. A 6-page designed recap with two-speaker narration is 1,870 credits, about $3.74 at the $80 pack rate.
Can each client get a deck in their own language?
Yes. Set responseLanguage per client, for example "German" or "Spanish". 2Slides supports 20+ output languages. Have a fluent account manager review non-English decks, especially marketing terms that do not translate literally.
Should I replace AgencyAnalytics or Looker Studio with this?
No. Keep the dashboard for live data and self-serve access; use generated decks for the monthly story and the review meeting. The two work best together, with the dashboard link on the final slide.
Ready to stop rebuilding monthly decks by hand? Get an API key with 500 free credits at 2slides.com/api and run your first five client decks this week.
About 2Slides
Create stunning AI-powered presentations in seconds. Transform your ideas into professional slides with 2slides AI Agent.
Try For Free