Skip to main content
Automation July 6, 2026 · 9 min read

How to Connect Outbrain to Google Sheets for Automated Ad Reporting

I built an n8n workflow that pulls Outbrain campaign data into Google Sheets in 30 minutes. Exact setup with API config, cost tracking, and scheduling.

Edward Chalupa

Edward Chalupa

Founder, Whtnxt · Dallas, TX

How to Connect Outbrain to Google Sheets for Automated Ad Reporting

I run native ad campaigns for a DFW home services client that spends roughly $8,000 a month on Outbrain. For the first six months I logged into the Outbrain dashboard every Tuesday morning, exported a CSV, reformatted it in Excel, and emailed it around. That process took me about 45 minutes per week, roughly 39 hours a year wasted on copy-paste reporting.

I built an n8n workflow that connects Outbrain’s API directly to Google Sheets. Now the numbers land in a live dashboard every morning at 6 AM. The client gets real-time visibility, I get 39 hours back, and nobody touches a CSV. Here is exactly how I set it up.

What You’re Building

A scheduled n8n workflow that authenticates against the Outbrain Amplify API, queries campaign-level performance data for the previous day, transforms the response into a clean row format, and appends it to a Google Sheet. The sheet builds a running log of daily performance that you can pivot, chart, or pipe into a Looker Studio dashboard.

The system handles auth token refresh, pagination across multiple campaigns, date-range validation, and deduplication so you never double-append the same day’s data.

What You’ll Need

ItemDetailsTime to Set Up
Outbrain Amplify accountActive account with at least one running campaignAlready done
Outbrain API credentialsUsername and password from your account settings5 minutes
n8n instanceSelf-hosted or cloud (I run n8n on a $12/month VPS)30 minutes
Google Sheets API credentialsGoogle Cloud project with Sheets API + service account10 minutes
Google SheetEmpty sheet for your reporting data2 minutes

Total setup time from scratch: about 90 minutes. If you already have n8n running, this takes under 30.

Step 1: Get Your Outbrain API Credentials

Outbrain’s Amplify API uses HTTP Basic authentication. Log into your Outbrain account and go to Settings > API Access. You need your account username and password. If you don’t see an API section, contact your account manager. Outbrain enables API access on request.

Test your credentials with a quick curl command:

curl -u "your-username:your-password" \
  "https://api.outbrain.com/amplify/v0/login"

A successful response returns a JSON object with a token field and a user object containing your userId. Save the userId value; you need it for every report query.

Info: Outbrain’s API token expires after 24 hours. You must call the login endpoint before every report pull, not just once at setup. n8n handles this automatically when you configure the auth correctly.

The login response also lists your account objects with id fields. You need the account ID to query campaigns and reports.

Step 2: Set Up the Google Sheet

Create a new Google Sheet. I name mine “Outbrain Daily Performance [Client Name]”. The header row should contain these columns:

ColumnField NameDescription
ADateYYYY-MM-DD format
BCampaign IDOutbrain’s internal ID
CCampaign NameHuman-readable name
DImpressionsTotal served
EClicksTotal clicks
FCTRClick-through rate as decimal
GSpendCost in USD
HCPCCost per click
IConversionsPost-click conversions
JCPACost per acquisition

I add a second sheet tab called “Metadata” where I store the last-pulled date and status flags. The workflow checks this tab before every run to avoid duplicating data.

# Example: Sheet ID is in the URL after /d/
# https://docs.google.com/spreadsheets/d/1ABC123.../edit
# Share the sheet with your service account email (read-only for safety)

Step 3: Build the n8n Authentication Node

In n8n, create a new workflow. I name mine “Outbrain Daily Report Sync”. The first node is an HTTP Request node that calls the login endpoint.

HTTP Request Node configuration:

SettingValue
MethodGET
URLhttps://api.outbrain.com/amplify/v0/login
AuthenticationBasic Auth
User Name={{ $json.credentials.username }}
Password={{ $json.credentials.password }}
Send asJSON

I store the credentials in n8n’s credential store as “Outbrain API” and reference them from the node. The n8n HTTP Request node docs{target=“_blank”} explain the auth patterns. The login response looks like this:

{
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "user": {
    "id": "usr_1234567890",
    "accounts": [
      {
        "id": "acc_0987654321",
        "name": "My Agency Account"
      }
    ]
  }
}

Use a Set node to extract token and the first account.id into workflow variables. I pipe the token into a header OB-TOKEN: Bearer {{token}} for subsequent API calls.

Warning: Never hardcode your Outbrain password in a plain text field. Always use n8n’s credential storage. A leaked API password means anyone can pull your campaign data and adjust bids.

Step 4: Query the Outbrain Campaign Report

The Outbrain report endpoint is at https://api.outbrain.com/amplify/v0/accounts/{accountId}/reports/periodic/campaigns. Add a second HTTP Request node after the auth step.

HTTP Request Node 2 configuration:

SettingValue
MethodPOST
URLhttps://api.outbrain.com/amplify/v0/accounts/{{accountId}}/reports/periodic/campaigns
AuthenticationNone (use headers manually)
HeadersOB-TOKEN: Bearer {{token}}

The POST body specifies the date range and report dimensions:

{
  "fromDate": "2026-07-05",
  "toDate": "2026-07-05",
  "breakdown": "campaign",
  "metrics": ["impressions", "clicks", "ctr", "spend", "cpc", "conversions", "cpa"],
  "includeArchived": false,
  "limit": 200
}

The fromDate and toDate should be yesterday’s date. I use an n8n expression: {{ $today.format('yyyy-MM-dd') }} for today and {{ $today.minusDays(1).format('yyyy-MM-dd') }} for yesterday.

The response returns an array of campaign objects. For a broader overview of how this fits into a marketing automation services stack, the same pattern works for Google Ads, Meta Ads, and LinkedIn reporting too:

Info: Outbrain’s API docs at Outbrain Amplify API{target=“_blank”} have full field descriptions and rate limit info. The daily limit is 10,000 requests per account, which is more than enough for a daily pull of 200 campaigns.

{
  "totals": {
    "impressions": 245890,
    "clicks": 3891,
    "spend": 267.45,
    "conversions": 18
  },
  "campaigns": [
    {
      "id": "cmp_12345",
      "name": "DFW Home Services - Q3",
      "impressions": 102345,
      "clicks": 1890,
      "ctr": 1.85,
      "spend": 134.20,
      "cpc": 0.071,
      "conversions": 10,
      "cpa": 13.42
    }
  ],
  "pagination": {
    "page": 1,
    "totalPages": 3
  }
}

Step 5: Handle Pagination with an n8n Loop

Outbrain paginates at 200 campaigns per page. If you manage multiple accounts or many campaigns, you need a loop node to collect all pages before writing to Sheets.

I use an n8n SplitInBatches node with a counter variable. The workflow checks pagination.totalPages from the first response, then loops through pages 2..N. Each iteration appends the campaign data to a running array. This pagination pattern is reused from my n8n marketing automation engine setup.

// n8n Function node for pagination aggregation
const allCampaigns = $input.all();
let aggregated = [];

for (const batch of allCampaigns) {
  const campaigns = batch.json.campaigns || [];
  aggregated = aggregated.concat(campaigns);
}

return aggregated;

This function collects all campaign records into a single flat array for the Sheets write step.

Step 6: Write to Google Sheets

The Google Sheets node in n8n handles the write. I use the “Append or Update” mode with a header row lookup to match the column structure. The Google Sheets API{target=“_blank”} integration supports batch writes and cell formatting.

Google Sheets Node configuration:

SettingValue
OperationAppend
Document IDThe Sheet ID from your spreadsheet URL
Sheet NameSheet1 (or your named tab)
ColumnsA through J
Data MappingMap each Outbrain field to the correct column

The mapped data for each campaign row:

{
  "Date": yesterdayDate,
  "Campaign ID": campaign.id,
  "Campaign Name": campaign.name,
  "Impressions": campaign.impressions,
  "Clicks": campaign.clicks,
  "CTR": campaign.ctr,
  "Spend": campaign.spend,
  "CPC": campaign.cpc,
  "Conversions": campaign.conversions,
  "CPA": campaign.cpa
}

Before writing, I add a deduplication check: read the last 30 rows of the sheet, check if yesterday’s date already exists for each campaign ID, and skip those rows. This prevents double-appending if the workflow runs twice.

Step 7: Schedule the Daily Run

Set the n8n workflow trigger to “Cron” and configure it to run at 6 AM Central Time:

0 6 * * *

n8n handles timezone conversion. My VPS is UTC, so the cron expression accounts for the 6-hour offset. I set up an error workflow that sends me a Telegram message if the pull fails, so I know within 5 minutes if a credential expired or the API changed.

Outbrain to Google Sheets Workflow

The workflow runs daily at 6 AM. The cron trigger fires, n8n authenticates against Outbrain’s API, pulls campaign data, loops through pagination, and appends each row to the spreadsheet.

Tip: Test the workflow manually the first time by setting the date range to a period you know has data. I test with the last 3 days and verify the Google Sheet populated correctly before turning on the cron trigger.

The Pitfalls I Hit

Pitfall 1: The Token Expires Mid-Workflow

The /login token is valid for 24 hours, but if your workflow runs at 5:59 AM and generates a token at 6:00 AM, you are fine. The issue is when you reuse a token from a previous run stored in a variable. I wasted two days debugging 401 errors because I cached the token at startup instead of calling login fresh each run.

Fix: Call /v0/login as the first node in every workflow execution. The API call takes about 200ms, no reason to skip it.

Pitfall 2: Date Range Can’t Be Open-Ended

Outbrain’s report API requires explicit fromDate and toDate parameters. If you pass today’s date, you get partial-day data that changes throughout the day. If you pass a range longer than 31 days, the API returns a 400 error.

Fix: Always use yesterday’s complete day as the range. fromDate = yesterday and toDate = yesterday. The cron runs at 6 AM, so yesterday’s data is fully settled.

Pitfall 3: Currency Formatting in Google Sheets

Outbrain returns spend and cost values as floats (267.45). Google Sheets sometimes interprets these as strings if the column format isn’t set. The cpa and cpc values with leading zeros (0.071) can get truncated.

Fix: Pre-format the Google Sheet columns as “Number > Plain Number” with 4 decimal places before the first workflow run. This keeps the spreadsheet readable for pivot tables and charting.

Info: The Google Sheet accumulates a running daily log. Each row represents one campaign’s performance for one day. With 10 campaigns running for 90 days, you end up with 900 rows that you can pivot by campaign, date range, or metric for weekly reporting.

When to Use This (And When Not To)

Use this workflow when you manage Outbrain campaigns as part of a broader marketing stack and want a single pane of glass for all ad platform data. It works best for:

  • Agencies running Outbrain for multiple clients (one sheet per client, one workflow per account)
  • In-house marketers who report to stakeholders that want daily visibility
  • Anyone spending more than $2,000/month on Outbrain (the time savings pay for the setup in two weeks)

Do not use this if:

  • You only run one campaign with minimal data. The Outbrain dashboard export button is faster.
  • You need real-time (sub-hourly) data. Outbrain’s report endpoint refreshes on a 3-6 hour delay. The 24-hour settled data is the most reliable snapshot.
  • You have zero technical tolerance. If a workflow error would go unnoticed for days, stick with manual exports and set a calendar reminder.

What’s Next

This reporting workflow connects into a larger automated analytics system. I pipe the Outbrain sheet data into a Looker Studio dashboard alongside Google Ads, Meta Ads, and organic traffic from Plausible. The full marketing analytics dashboard shows all channels in one view with automated weekly reports emailed to stakeholders.

If you are running multiple ad platforms and spending more than an hour a week on manual reporting, a connected reporting stack will pay for itself in month one. I cover the full setup in my automated marketing reporting dashboard with n8n and Google Sheets post.

For the DFW home services client this workflow serves, we also built a lead routing system in n8n that connects Outbrain leads directly into their CRM. The reporting layer makes it easy to track CPA by campaign and adjust bids daily based on conversion data.

If you want a complete paid search management system that includes automated reporting across Outbrain, Google Ads, and native channels, I can build that. The setup takes about a day and the reporting piece is reusable across clients.

Outbrainn8nGoogle Sheetsad reportingnative adsmarketing automationAPI integrationautomated dashboards
Share: