A lot of marketing agencies lose their Monday morning to reporting. Someone opens GA4, exports last week’s numbers, opens Meta Ads Manager, exports again, pastes both into a deck for each client, writes a paragraph of commentary, exports a PDF, and emails it. Multiply that by twelve retainer clients and Monday is gone.
This is a walkthrough of a setup that removes almost all of it. A Make.com scenario pulls GA4 and Meta Ads data every week, writes it to Airtable, and asks GPT-4o for three or four sentences of performance commentary. ActiveMerge fills a branded PowerPoint template with that row and emails the finished report to the client. Total Monday morning time: about five minutes to review and send.
The part that took the most iteration was not the plumbing. It was getting the AI commentary to say something a client would actually read. More on that in Step 4.
If you are a marketing agency you can automate this report generation workflow, this is step by step solution that you can implement fast.
The shape of the workflow
Monday 06:00
Make.com scenario runs
→ GA4 API: last 7 days + previous 7 days
→ Meta Ads API: last 7 days + previous 7 days
→ calculate WoW deltas
→ GPT-4o: draft commentary
→ write one row per client to Airtable
ActiveMerge picks up rows marked Ready
→ fills the PPTX report template
→ converts to PDF
→ emails each client their own report
Monday 09:00
You review the campaign list and send
Each piece does the thing it is good at. Make.com handles the API calls and scheduling. Airtable is the record of what was reported and when. ActiveMerge does the document assembly and delivery, which is the part that is genuinely tedious to build yourself.
Why PowerPoint instead of a dashboard link
Agencies keep getting told that a live dashboard replaces reporting. In practice, clients forward decks to people who don’t have dashboard logins, and marketing directors present them in meetings you are not in. A file that lives in an inbox gets read; a link that requires a login often does not.
PPTX also means the report matches the deck your designer already made. You aren’t fighting a reporting tool’s layout engine to get your brand colours right, because the layout is a slide you built in PowerPoint.
ActiveMerge supports PPTX templates fully, and converts to PDF on the way out. A common pattern is to send the PDF to the client and keep the PPTX for the accounts team, who sometimes need to add a slide before a quarterly review.
What you need
- A GA4 property and a Meta Ads account for each client
- A Make.com account (the free tier covers a handful of clients on a weekly schedule)
- An Airtable base
- An OpenAI API key for the commentary step
- A PowerPoint report template
- An ActiveMerge account with an email connection set up under Campaigns → Email Connections
Step 1: Build the report template in PowerPoint
Design the deck once, in PowerPoint, the way you would build it for a client by hand. Then replace every number with a placeholder in single curly braces.
A four-slide weekly report covers most retainers:
Slide 1: Cover
Weekly Performance Report
{Client_Name}
{Week_Start} to {Week_End}
Slide 2: Traffic (GA4)
| Metric | Last week | Previous week | Change |
|---|---|---|---|
| Sessions | {Sessions} |
{Sessions_Prev} |
{Sessions_WoW} |
| Users | {Users} |
{Users_Prev} |
{Users_WoW} |
| Conversions | {Conversions} |
{Conversions_Prev} |
{Conversions_WoW} |
| Conv. rate | {Conv_Rate} |
{Conv_Rate_Prev} |
{Conv_Rate_WoW} |
Slide 3: Paid social (Meta Ads)
| Metric | Last week | Previous week | Change |
|---|---|---|---|
| Spend | {Spend} |
{Spend_Prev} |
{Spend_WoW} |
| Impressions | {Impressions} |
{Impressions_Prev} |
{Impressions_WoW} |
| Clicks | {Clicks} |
{Clicks_Prev} |
{Clicks_WoW} |
| CPC | {CPC} |
{CPC_Prev} |
{CPC_WoW} |
| ROAS | {ROAS} |
{ROAS_Prev} |
{ROAS_WoW} |
Slide 4: Commentary and next steps
What happened last week
{Commentary}
Focus for this week
{Next_Steps}
Placeholder names can contain letters, numbers, underscores, and hyphens, but not spaces or symbols. Airtable field names with spaces are written with underscores, so a field called Client Name becomes {Client_Name}.
Adding charts
You do not need a charting library. Put an image placeholder in a shape on the slide and pass an image URL as the value:
{Sessions_Chart}
In PPTX templates, the image is sized to the box that contains the placeholder, so draw a rectangle where the chart belongs and put the placeholder inside it. Generate the chart URL in the Make.com scenario with a service like QuickChart, and write that URL into the Airtable row along with the numbers. Make the rectangle the exact aspect ratio you want, because the image fills the container.
Upload the finished PPTX to ActiveMerge and save it as a reusable template. Click Detect Placeholders after uploading and check that the list matches what you expect. Placeholders inside grouped shapes or embedded charts are a frequent source of surprises, and this is where you find them.
Step 2: Set up the Airtable base
Two tables are enough.
Clients
| Field | Type | Example |
|---|---|---|
| Client Name | Single line text | Northgate Dental |
| Client Email | marketing@northgate.example |
|
| GA4 Property ID | Single line text | properties/123456789 |
| Meta Ad Account ID | Single line text | act_987654321 |
| Report Active | Checkbox | ✅ |
| Account Manager | Collaborator |
Weekly Reports
One row per client per week. This is the table ActiveMerge reads.
| Field | Type | Example |
|---|---|---|
| Report ID | Formula | northgate-2026-W34 |
| Client Name | Single line text | Northgate Dental |
| Client Email | marketing@northgate.example |
|
| Week Start / Week End | Date | 2026-08-17 / 2026-08-23 |
| Sessions, Users, Conversions, Conv Rate | Number / Percent | |
| Sessions Prev, Users Prev, … | Number / Percent | |
| Sessions WoW, Users WoW, … | Formula or number | +12.4% |
| Spend, Impressions, Clicks, CPC, ROAS | Currency / Number | |
| Spend Prev, Clicks Prev, … | Currency / Number | |
| Sessions Chart | URL | Chart image URL |
| Commentary | Long text | Written by GPT-4o |
| Next Steps | Long text | Written by the account manager |
| Report Status | Single select | Draft, Ready to Send, Processing, Queued, Failed |
Report Status is the field that makes the whole thing controllable. Make.com writes rows as Draft. Nothing gets sent until a human moves a row to Ready to Send. That single gate is what keeps a broken API response from reaching a client.
A note on the WoW fields: format them as text in the shape you want on the slide, including the sign and the percent symbol. +12.4% reads better in a deck than 0.124, and doing the formatting in Airtable means you never touch it in the template.
Step 3: Build the Make.com scenario
Schedule it for early Monday, before anyone is at a desk.
- Schedule: every Monday at 06:00.
- Airtable → Search Records on
Clients, filtered toReport Active = true. Everything after this runs once per client. - Google Analytics 4 → Run a Report for the last 7 days: sessions, total users, key events, session conversion rate.
- Google Analytics 4 → Run a Report again for the 7 days before that.
- Facebook Ads → Get Insights for the last 7 days: spend, impressions, clicks, CPC, purchase ROAS.
- Facebook Ads → Get Insights for the previous 7 days.
- Tools → Set multiple variables: calculate each WoW change and format it as a string.
- Tools → Set variable: build the chart image URL from the daily sessions series.
- OpenAI → Create a Completion, which is covered in the next section.
- Airtable → Create a Record in
Weekly Reportswith everything above andReport Status = Draft.
Two things here are easy to skip and both bite later. The first is a filter in front of the OpenAI module, so it only runs when the GA4 and Meta responses actually contain data. If a client’s ad account was paused, the metrics come back as zeros and the model will write confidently about a 100% decline in spend as though it were a performance problem.
The second is rounding. Round the numbers in Make rather than in the template. Otherwise a session count arrives as 4831.0 and a CPC as 1.8399999999, and you spend your Monday fixing number formatting inside a PowerPoint text box.
Step 4: Make the AI commentary useful
This is where the setup either earns its keep or produces four sentences that every client learns to skip.
Left alone, GPT-4o writes reporting filler. “Performance remained steady this week with some fluctuations across channels. Engagement showed positive signs and there are opportunities to optimise going forward.” It’s grammatical, it’s about nothing, and a client who reads two of those stops reading the rest.
What fixed it was constraining the output format in the system prompt rather than asking for better writing. No generic observations. Every sentence has to reference a specific metric with a week-over-week comparison, or it does not get written.
System prompt
You write weekly performance commentary for a marketing agency's client reports.
Write 3 to 4 sentences. No heading, no bullet points, no preamble, no sign-off.
Rules:
1. Every sentence must name one specific metric, state its value, and state
its week-over-week change as a percentage or absolute difference.
2. Never write a sentence that would still be true if the numbers were
different. No "performance was steady", no "results were mixed", no
"there are opportunities to optimise".
3. Lead with the largest movement, up or down. Do not bury a decline.
4. If a metric moved less than 5%, describe it as flat and do not spend a
sentence on it unless nothing else moved.
5. State what changed. Do not speculate about why unless the data given
includes the cause.
6. No recommendations. A human writes those.
7. Plain British English. No marketing adjectives: no "strong", "impressive",
"significant", "robust".
You will receive last week's metrics and the previous week's metrics as JSON.
User message
Pass the numbers as JSON rather than as a sentence. The model handles structured input more reliably, and the scenario is easier to debug when the payload is readable.
{
"client": "Northgate Dental",
"week": "2026-08-17 to 2026-08-23",
"ga4": {
"sessions": {"current": 4831, "previous": 4297},
"users": {"current": 3902, "previous": 3611},
"conversions": {"current": 87, "previous": 94},
"conversion_rate": {"current": 1.8, "previous": 2.19}
},
"meta_ads": {
"spend": {"current": 2140.50, "previous": 2088.00},
"clicks": {"current": 1893, "previous": 1502},
"cpc": {"current": 1.13, "previous": 1.39},
"roas": {"current": 3.4, "previous": 4.1}
}
}
What comes back
Sessions rose 12.4% to 4,831, driven by 1,893 clicks from Meta Ads against
1,502 the week before. CPC fell from £1.39 to £1.13, so the extra traffic
came at roughly the same spend of £2,140. Conversions dropped 7.4% to 87 and
conversion rate fell from 2.19% to 1.80%. ROAS came down from 4.1 to 3.4.
That is a paragraph a client can act on, and an account manager can add one line of context to in about thirty seconds. Rules 2 and 7 do most of the work: banning sentences that would be true regardless of the numbers, and banning the adjectives that let the model sound confident without saying anything.
Set temperature to around 0.3. Higher and the model starts adding causal explanations it has no basis for, in defiance of rule 5.
Keep Commentary and Next Steps as separate fields. The AI drafts what happened; the human writes what to do about it. Clients notice when the recommendations are generic, and that is the part they pay for.
Step 5: Connect Airtable to ActiveMerge
In ActiveMerge, start a new document generation job:
- Choose Airtable as the data source and connect your account.
- Select the base and the
Weekly Reportstable. - Select the saved PPTX report template.
- Map each placeholder to its Airtable field. Auto-matching handles most of them if the field names line up with the placeholder names.
- Choose PDF as the output format.
- Generate a preview with one row before going further.
Check the preview slowly the first time. Look at currency symbols, decimal places, the sign on negative percentages, the chart image aspect ratio, and any text box where a long client name might overflow. These are much easier to fix in the template than to notice in a client’s inbox.
Then choose Save as Automation:
| Setting | Value |
|---|---|
| Name | Weekly client reports |
| Status column | Report Status |
| Trigger value | Ready to Send |
| In-progress value | Processing |
| Success value | Queued |
| Failure value | Failed |
| Check frequency | Every 15 minutes |
| Automatic email delivery | Enabled |
| Recipient email column | Client Email |
Status values are case sensitive, so type them exactly as they appear in the Airtable single-select options.
If you would rather trigger from Make.com
You can skip the polling automation and call the API from the scenario instead. Add an HTTP → Make a Request module:
POST https://activemerge.com/api/document-generation/generate
API-KEY: sk_live_your_key
{
"template_id": "your_template_id",
"data": {
"Client_Name": "Northgate Dental",
"Sessions": "4,831",
"Sessions_WoW": "+12.4%",
"Commentary": "Sessions rose 12.4% to 4,831..."
},
"format": "pptx"
}
The response comes back immediately with a job_id and status: in_progress. Register a webhook under Settings → API Access → Webhooks for document_generation.completed and the download URL arrives in the payload when the file is ready, usually within a few seconds. That is cleaner than a sleep-and-poll loop, and it means your Monday scenario is not sitting idle waiting for a file.
Download URLs are signed and valid for 24 hours, so if you want to archive reports, push the file to Drive or Dropbox in the same run rather than saving the link.
Step 6: Set up the client email
Under Campaigns → Email Templates, create the delivery template. Email placeholders use square brackets, not the curly braces used in documents:
| Location | Format | Example |
|---|---|---|
| PPTX template | Curly braces | {Client_Name} |
| Email subject and body | Square brackets | [Client Name] |
Subject: [Client Name]: weekly performance report, week ending [Week End]
Body:
Hi [Client Name],
Your report for the week ending [Week End] is attached.
Headline: sessions [Sessions_WoW] week over week, conversions [Conversions_WoW].
Anything you'd like to dig into before Thursday's call, just reply here.
[Account Manager]
Every [Field Name] you use has to exist in the Airtable row, or the automation fails validation before it sends. That is the intended behaviour: a report going out with [Client Name] unreplaced in the subject line is worse than one going out late.
Step 7: The five-minute Monday
By the time anyone opens a laptop, Make.com has written the rows and the commentary. What is left:
- Open the
Weekly Reportsview filtered to this week’sDraftrows. - Scan the numbers for anything obviously broken. Zeros where there should not be zeros, a spend figure ten times the usual, a missing chart URL.
- Read the four commentary sentences per client. Edit rarely, but do read them.
- Add one line to
Next Stepsfor each client. - Select the rows and switch
Report StatustoReady to Send.
ActiveMerge picks them up on the next check, generates each report, and emails it. The Airtable status moves Ready to Send → Processing → Queued. Queued means the report was generated and the email was created, not that the client received it. Confirm actual delivery in the Campaigns dashboard, where each report appears as its own one-recipient campaign with a sent or failed status.
For twelve clients, that is genuinely about five minutes, and most of it is step 4.
What it actually saves
Time the manual version before you build anything, because the honest number is lower than the one people quote and still large enough to justify the work. Count the GA4 export, the Meta export, the copy and paste into the deck, the commentary, the PDF export, the file rename, and the individual email. For most agencies that lands somewhere between 20 and 40 minutes per client, depending on how many channels the retainer covers and how much the account manager writes.
At twelve clients that is four to eight hours a week, concentrated on the one morning when everyone else also wants your attention. The setup above turns it into roughly five minutes of review plus a minute per client for the Next Steps line.
The hours are the obvious part. The less obvious part is that reports now go out at the same time every week whether or not the person who normally does them is ill, on holiday, or buried in a pitch. Late reports are a bigger source of client friction than mediocre ones.
Things that go wrong
GA4 data is not final on Monday morning
GA4 keeps adjusting recent numbers for a day or two. If a client compares your Monday report to what they see in GA4 on Wednesday, the figures will differ slightly. Either run the scenario on Tuesday, or put a line in the template footer stating the data pull timestamp. The second option is less work and heads off the question entirely.
Meta attribution windows shift the ROAS
Conversions attributed to last week’s ads keep landing for several days. Same fix: state the pull date, and be consistent about when you pull.
A client pauses their ads and the commentary panics
Rule 5 in the system prompt stops the model inventing reasons, but a 100% spend decline still leads the paragraph. Add a Make.com filter that routes zero-spend clients to a different, shorter prompt, or skip the paid slide for that week.
Long client names break the cover slide
PowerPoint does not reflow a text box the way Word reflows a paragraph. Set the text box to shrink text on overflow, and test with your longest client name rather than your shortest.
The chart image does not appear
In PPTX the image placeholder fills its container, so it has to sit inside a shape. A bare placeholder floating on the slide has no box to fill. Also check that the chart URL is publicly reachable, since the generator fetches it at render time.
Scaling past a dozen clients
The setup does not change much at thirty clients. What changes is the cost of the parts that scale one client at a time.
Make.com operations add up, since each client costs roughly ten operations per run. At thirty clients on a weekly schedule that is still modest, but check your plan before adding daily reports.
The commentary cost stays small. A few hundred tokens in, a hundred out, per client, per week. It isn’t a line item worth thinking about.
Review time is the real constraint. Reading thirty commentary paragraphs isn’t a five-minute job. At that point, split the Airtable view by account manager so each person reviews their own clients, and let them flip their own rows to Ready to Send.
Frequently asked questions
Can I use the same template for clients with different service mixes?
Yes, within reason. Keep one template per report type rather than one per client. If a client has no paid social, either send them a traffic-only template or leave the Meta fields empty and accept the blank slide. Two or three templates covering your standard retainer shapes is usually the right number.
Do I need Make.com, or can Airtable do the API calls?
Airtable automations can call APIs with scripting, but you would be writing and maintaining GA4 and Meta API code by hand, including token refresh. Make’s prebuilt modules handle authentication, and the scenario is easier for a non-developer on the team to adjust.
Can clients get the editable PowerPoint instead of a PDF?
Yes. Set format to pptx and the generated file is a PowerPoint deck. Most agencies send PDF to the client and keep the PPTX internally, since a client editing the deck and forwarding it is a support conversation nobody wants.
What if the AI commentary is wrong?
It shouldn’t be, because it only restates numbers you passed in. If it is wrong, the numbers were wrong, which is the useful thing about constraining it this way: a fabricated observation is very visible against the metrics table on the previous slide. That is a further argument for keeping recommendations out of the AI’s job.
Can I add a second document, like a one-page summary?
Yes. A generation job can produce more than one template per row, so you can attach a one-page PDF summary alongside the full deck from the same Airtable data.


