# Add ad spend

Enter ad spend by hand or as CSV, tagged with the same channel, source, medium and campaign as your ad links, so ProductLense can subtract it from revenue.

Profit per channel needs the cost side. ProductLense takes ad spend in two ways: rows entered by hand and CSV files. Both live on the Profit page under Add spend, and both are on the Growth and Scale plans.

## How spend joins to revenue

Every payment carries the channel, source, medium and campaign of the customer's first visit (see [How payments are attributed](/docs/revenue/attribution)). A spend row is subtracted from revenue with exactly the same four values. For a Google Ads campaign whose links carry `utm_source=google&utm_medium=cpc&utm_campaign=brand_search`, enter:

| Channel | Source | Medium | Campaign |
|---|---|---|---|
| `paid` | `google` | `cpc` | `brand_search` |

- **Channel** is the channel ProductLense assigns to those visits. Ad clicks are `paid` when the URL has `gclid`, `fbclid` or `msclkid`, or `utm_medium` is `cpc`, `ppc`, `paid`, `paidsocial` or `display`. A newsletter sponsorship tagged `utm_medium=email` is `email`.
- **Source and medium** are stored in lower case on the revenue side. Enter them in lower case.
- **Campaign** is matched exactly, case included. `Brand_Search` and `brand_search` are different campaigns.

> [!IMPORTANT]
> If the four values differ by a single character, the spend shows up as its own row with no revenue and the campaign's revenue as a row with no spend. Pick one naming scheme for UTM tags and use it in both places.

## Manual entry

On the Profit page, choose Add spend → Manual and fill in:

| Field | Rules |
|---|---|
| From, To | The dates the spend covers, inclusive, up to 366 days apart. A single day is From = To. |
| Channel | One of `paid`, `social`, `email`, `referral`, `organic_search` |
| Source, Medium, Campaign | Up to 200 characters each, as in your UTM tags |
| Amount | 0 to 1,000,000,000 |
| Currency | USD, EUR, GBP or INR |

A row that covers several days is spread evenly across them. A 3,000 USD monthly sponsorship entered for 1 to 30 September counts as 100 USD a day, so a report for 1 to 15 September includes 1,500 USD of it.

Amounts are converted to USD at the European Central Bank rate for the From date. If there is no rate for that currency yet, the row is refused with a message; enter it in USD or try again the next day.

## CSV import

Choose Add spend → CSV import and upload a file whose first line is exactly:

```csv title="ad-spend.csv"
date,channel,source,medium,campaign,amount,currency
2026-10-01,paid,google,cpc,brand_search,42.50,USD
2026-10-01,paid,facebook,paidsocial,retargeting_oct,18.00,EUR
2026-10-02,email,newsletter_swap,email,oct_swap,150.00,USD
```

- The header is checked case-insensitively. A UTF-8 byte order mark from a spreadsheet export is ignored.
- Each row is one day of spend. `date` is `YYYY-MM-DD`.
- `channel` is required. `source`, `medium` and `campaign` may be empty and are limited to 200 characters.
- `amount` uses a dot for decimals and no thousands separator: `1250.00`, not `1,250.00`. From 0 to 1,000,000,000.
- `currency` is a three-letter ISO 4217 code. Amounts are converted to USD at the ECB rate for the row's date.
- A file holds at most 10,000 rows and 5 MB.

Rows that fail a rule, and rows in a currency without an exchange rate for their date, are skipped. The import reports how many rows were added and how many were skipped. A malformed file (wrong header, wrong number of columns, no rows) is refused as a whole.

Every import adds rows. To correct one, delete the wrong rows in the Ad spend table (click a row to delete it) before importing again, or the spend is counted twice.

## Exporting spend from ad platforms

Google Ads and Meta Ads both export daily campaign spend as CSV. Reshape the export to the seven columns above, with the UTM values your ads use as source, medium and campaign.

## Related

- [Profit per channel](/docs/profit/profit-per-channel)
- [CAC, ROAS and payback](/docs/profit/cac-roas-payback)
