# LinkedIn Ads budget pacing dashboard for every client account

> See every LinkedIn ad account's spend against the budget you committed to, catch overspend early, and rebalance without rebuilding a spreadsheet.

- Workflow type: app
- Services: LinkedIn Ads, Google Sheets, Slack Bot
- Categories: Marketing, Operations
- Published: 2026-08-31

## What it does

- One screen listing every ad account you can access, with its campaign groups and campaigns underneath, showing month to date spend next to the budget you committed to.
- A pacing score for each campaign measured against its own run dates, so a campaign that started mid month is not judged against the calendar, plus projected end of month spend and dollars over or under.
- Change a daily budget or pause and resume a campaign right from the row, post the snapshot to a client channel, and save every snapshot to your spend history sheet automatically.
- A Rebalance button that has an assistant study the last 30 days and propose which campaigns to trim and which to fund, with its reasoning, for you to approve or reject line by line.

## What you'll need

- A LinkedIn Ads login with admin access in Campaign Manager for the accounts you want to track
- A Google Sheet holding the monthly budget you committed to for each account or campaign
- A Slack workspace, if you want to post pacing snapshots to a client channel

## Prompt

Build an internal app my paid social team opens every morning and again at month end, to see whether LinkedIn Ads spend is pacing against the budget we actually committed to for each client. Today that answer lives in a spreadsheet someone rebuilds by hand from Campaign Manager exports, and it is always a day or two stale.

## The main screen

The main screen is a pacing table listing every LinkedIn ad account the connected user has access to (Search Ad Accounts), with its campaign groups (Search Campaign Groups) and campaigns (Search Campaigns) nested underneath as expandable rows. Each account renders as a group header with its own rolled up totals, and each campaign row is where the detail lives.

For every row show month to date spend (Get Ad Analytics), the committed monthly budget read from our Google Sheet (Get Values), percent of the flight elapsed, a pacing index, projected end of month spend, and dollars over or under budget. Sort worst pacing first, meaning the largest absolute deviation from on pace, so the campaigns that need attention sit at the top without anyone filtering. Use semantic status colours for the pacing index: on pace, overspending, underspending.

The budget sheet is the source of truth for what we committed to. Read it with Get Values from a tab holding one row per account or per campaign with the identifier, the month, the committed amount, and the currency. Match sheet rows to LinkedIn entities by that identifier, and show a clear no budget set state on any row with no matching sheet entry rather than treating a missing budget as zero.

## How pacing is calculated

- Pace every campaign against its own run schedule, not the calendar month. Percent elapsed is how much of the time between the campaign's scheduled start and end has already passed as of today, not the day of the month.
- Pacing index is spend to date divided by committed budget, divided by percent elapsed. An index of 1.0 is exactly on pace, above 1.0 is overspending, below 1.0 is underspending.
- Projected end of month spend is the run rate to date extrapolated across the remainder of the flight.
- Dollars over or under is projected spend minus committed budget.
- Campaigns running with no end date have no flight to pace against. Flag these visibly as open ended, fall back to calendar month pacing for them, and let the user filter to just those rows, since an always on campaign with no end date is usually the thing quietly eating the budget.

## Inline actions

From any campaign row the user can change the daily budget or pause and resume the campaign inline, both through Update Campaign. The daily budget is an inline editable field on the row, and pause and resume toggles campaign status between ACTIVE and PAUSED. Both write immediately, reflect the result on the row, and surface any LinkedIn validation error inline rather than in a browser alert. Confirm before pausing a campaign that is currently active.

## Sharing and spend history

A Post snapshot action sends the current pacing snapshot for an account to a client channel with Slack Bot Send a Message, formatted as a readable summary of each campaign's spend, budget, pacing index, and projected finish rather than a raw table dump. Every snapshot also appends a timestamped row per campaign to the spend history tab with Append Values, so we accumulate a spend history over time that nobody has to rebuild by hand.

## Rebalance this account, a background agent

Each account header has a Rebalance this account button that kicks off a background agent. The agent pulls the last 30 days of per campaign analytics for that account (Get Ad Analytics pivoted by campaign), compares efficiency and pacing across the campaigns, works out which ones to trim and which to fund, and writes a proposed reallocation plan back into the app: one line per campaign with the current daily budget, the proposed daily budget, and a short written reason for the change. The plan must keep the account's total proposed spend within the committed budget.

The plan lands in the app as a pending proposal attached to that account, and nothing changes in LinkedIn when the agent finishes. The user reviews it line by line and approves or rejects each line individually. Only approved lines are applied, each through Update Campaign, and the app records which lines were approved, rejected, and applied so there is an audit trail. Show the agent's run state on the account row so people know a rebalance is in progress, and keep previously generated plans viewable.

## Rules to respect

- Keep every account in its own currency and never sum across accounts into a single blended total. A LinkedIn ad account's currency is fixed when the account is created and cannot change, so per account totals are the only honest rollup. Money values in the API are objects like {"amount":"100.00","currencyCode":"USD"} where the amount is a decimal string, and child entities must match the account currency.
- There is no update operation for campaign groups, so every budget edit, whether from an inline change or an approved rebalance line, happens at the campaign level through Update Campaign. Campaign group rows are display and rollup only.
- Update Campaign uses Rest.li partial update semantics: POST with the X-RestLi-Method: PARTIAL_UPDATE header and a body of {"patch":{"$set":{...}}}. A successful update returns 204 with no content, so treat 204 as success rather than waiting for a response body.
- Analytics endpoints are throttled harder than the CRUD ones. Pull each date range in a single Get Ad Analytics call using timeGranularity and the appropriate pivot instead of looping day by day or campaign by campaign, and back off on 429 responses and on 403 responses carrying a throttling service error code.
- Ad account, campaign group, and campaign identifiers are URNs, and the search endpoints use cursor pagination. Page through with pageSize and the returned next page token so the dashboard lists every account rather than just the first page.

## How to customize

- Set how far off pace a campaign has to be before it gets flagged as at risk
- Choose which Slack channel each account posts its pacing snapshot to
- Point it at your own budget sheet layout, whether you keep budgets per account or per campaign
- Decide whether the rebalance assistant can suggest pausing campaigns or only shifting daily budgets

## FAQ

### Will this change my budgets automatically?

No. Every budget change is something you trigger. Inline edits happen only when you change a value on a row, and the rebalance assistant only writes a proposal into the app. You approve or reject each proposed line individually, and nothing reaches LinkedIn until you approve it.

### Can it handle client accounts in different currencies?

Yes. Each LinkedIn ad account has a currency that is fixed when the account is created and cannot be changed afterward, so the dashboard keeps every account in its own currency and never blends them into one combined total. You get an honest per account rollup instead of a misleading grand total.

### What happens to campaigns that have no end date?

They get flagged. A campaign with no end date has no flight to pace against, so the app marks it as open ended, falls back to calendar month pacing, and lets you filter to just those rows. Always on campaigns are usually the ones quietly consuming the budget, so they are called out rather than hidden.

### Does my budget spreadsheet need a specific format?

It needs one row per account or per campaign with the identifier, the month, the committed amount, and the currency, but the exact layout is adjustable. If a row in LinkedIn has no matching budget in the sheet, the app shows a clear no budget set state rather than pretending the budget is zero.

### Does this work if I manage several client accounts?

That is the main use case. The dashboard lists every ad account you have access to in one place, sorted worst pacing first, so you check one screen instead of opening each account separately in Campaign Manager.

Use this prompt in General Input: https://www.generalinput.com/prompts/linkedin-ads-budget-pacing-dashboard-for-every-client-account