# Meta Ads

See what your Facebook and Instagram ads really earn. twelvebit puts the spend of each Meta campaign next to the visitors, the customers and the revenue that the campaign brought, and shows the return on ad spend (ROAS).

> You connect with an access token that can only read your ad account (`ads_read`). twelvebit never changes a campaign, a budget or an ad. You need no Meta app review and no Meta Pixel for this report.

## What you get

- **Spend, clicks and impressions per campaign**, for every day, from the first day of the last 120 days.
- **Visitors, customers and revenue per campaign** from your own twelvebit data.
- **ROAS, cost per visitor and cost per customer** for each campaign and for the account.
- **Meta and Google side by side** on the **Ads page**, with a spend and revenue chart and one tile for each platform.
- **Spend in your site currency.** twelvebit converts the account currency for you.

## Before you start

You need four things:

1. **Edit access** to the site in twelvebit (owner or member).
2. **Access to the ad account** in Meta Business Settings, so that you can make a token for it.
3. **The ad account ID.** In Ads Manager, it shows next to the account name, for example `act_1234567890`.
4. **Payments in twelvebit**, so that revenue can count. See [Revenue](/docs/revenue). Without payments, the Ads page shows spend and visitors, but no revenue.

## Step 1: make an access token

**Best: a system user token.** It does not expire.

1. In Meta Business Settings, open **Users → System users** and click **Add**. Give the system user a name, for example "twelvebit", and the role **Employee**.
2. Click **Assign assets**, select **Ad accounts**, select your ad account, and turn on **View performance**.
3. Click **Generate new token**. Select your app (or make one in Meta for Developers), and select only the permission `ads_read`.
4. Copy the token. Meta shows it once.

**Or: a long-lived user token.** It expires after 60 days, so you must connect again then.

1. In the Graph API Explorer, generate a user token with `ads_read`.
2. In the Access Token Debugger, click **Extend Access Token**, and copy the long-lived token.

> The token gives read access to your ad data. Keep it private, as you keep a password. twelvebit stores it encrypted, and it never goes back to the browser.

## Step 2: connect in twelvebit

1. In [twelvebit](https://twelvebit.app/sites), open your site, then **Settings → Integrations → Meta Ads**.
2. Paste the token and the ad account ID, and click **Connect Meta Ads**.

twelvebit checks the token, then reads 120 days of spend. The account then shows on the Ads page.

## Step 3: tag your ads

This step is necessary. Meta reports spend per campaign, but it does not tell twelvebit which visitor clicked which ad. The tags in the ad's link do that.

1. Copy this line:

~~~text
utm_source=meta&utm_medium=paid-social&utm_campaign={{campaign.name}}&utm_id={{campaign.id}}&utm_content={{ad.id}}
~~~

2. In Meta Ads Manager, open the **Ads** tab (not Campaigns or Ad sets), select an ad and click **Edit**.
3. Scroll down to the **Tracking** section at the bottom of the ad. Paste the line into **URL parameters**, in place of any text that is there. Do you use your own `utm_campaign` names? Then keep your text, and add only `&utm_id={{campaign.id}}` to the end of it.
4. Click **Publish**. Do the same for each ad, and for each new ad that you make.

Keep the line as it is. Meta puts the real campaign name, campaign ID and ad ID into each click: you change nothing. The campaign ID in `utm_id` is the tag that matches the visit to its campaign. The **Website URL** of the ad stays the same. Meta can review the ad again after you publish; the ad keeps its results.

> **Your own `utm_campaign` names**, for example `utm_campaign=spring_sale`, do not match a campaign. The `utm_id` that you add does: the visit matches its campaign by the ID, and your other reports keep your names. Meta's own `campaign_id={{campaign.id}}` works too.
>
> **Did you tag your ads with the earlier line** (`utm_campaign={{campaign.id}}`, without `utm_id`)? Those ads still match. You do not have to change them. Use the new line if you want campaign names in your UTM reports.

**Check it:** in Settings → Integrations → Meta Ads, the tagging steps close and show "Your ads are tagged" after the first visit matches a campaign. If visits come from Facebook or Instagram but none matches, the card shows a warning.

## How visits match campaigns

A visit belongs to one Meta campaign. twelvebit uses the first of these tags that matches:

1. **`utm_id`** in the landing URL is the campaign ID. When the URL has no `utm_id`, `campaign_id` counts the same.
2. **`utm_campaign`** is the campaign ID.
3. **`utm_campaign`** is the campaign name (in any case). When two campaigns have the same name, the visit counts for both.

A **`utm_id` property** with the campaign ID, sent by your own code, also matches.

twelvebit reads `utm_id` and `campaign_id` from visits since 23 October 2026. Older visits match by `utm_campaign` only.

**Revenue** counts each payment whose credited visit (the last visit before the payment) belongs to the campaign. Refunds take money off. **Customers** counts the people whose first payment came from the campaign.

A visit with a Google click or a Google `utm_source` never counts for Meta, also when a Meta campaign and a Google campaign have the same name.

## The Ads page

- **Headline.** One sentence that says how much revenue each 1 of spend brought back, and which campaign did best.
- **Campaigns.** Spend, clicks, visitors, customers, revenue and ROAS for each campaign, sorted by spend. Click a campaign name to open the Overview for its visits. Click its visitor count to see those people.
- **Spend and revenue chart.** **Running total** shows where revenue stays above spend: there, the ads paid for themselves. **Per day** shows the spend of each day as bars, and the revenue as a line.

The filter `f_ad=meta:<campaign ID>` shows the visits of one campaign on every page. See [Filters](/docs/filters).

Spend days follow the time zone of the ad account. Revenue days follow the time zone of the site.

## When the data updates

- twelvebit reads the spend once a day, and again when someone opens the Ads page and the last read is more than 6 hours old. **Sync now** in Settings reads it at once.
- Each read gets the last 7 days again, because Meta still changes recent numbers.
- Meta reports spend some hours late. A new ad can show visits on the Ads page before it shows spend.

## Privacy

- twelvebit reads only campaign names and IDs, and the daily spend, impressions and clicks. It reads no audiences, no ad text and nothing about the people who clicked.
- The token is stored encrypted. It is used only to read spend, and it never shows in the dashboard or the API.

## When something is wrong

| What you see | Why | What to do |
|---|---|---|
| **The access token is invalid or expired** | A user token ended after 60 days, or someone removed it. | Make a new token (a system user token does not expire), and connect again. |
| **The token has no ads_read permission** | The token was made without `ads_read`, or the system user has no access to the ad account. | Give the system user the ad account, and make the token again with `ads_read`. |
| Spend shows, but **0 visitors** | The ads have no tags, or the tags have no campaign ID. | Do [Step 3](#step-3-tag-your-ads), or add `utm_id={{campaign.id}}` to your own tags. |
| Visits from Facebook, but **no spend** | Meta reports spend late, or the ad is still in review. | Wait some hours, or click **Sync now**. |
| Visitors show, but **no revenue** | Payments are not connected, or they do not carry the visitor. | See [Revenue](/docs/revenue). |
| **Meta reports that this ad account is not active** | The ad account is disabled or closed in Meta. | Check the account status in Meta Business Settings. |

## Disconnect

Click **Disconnect** in Settings → Integrations → Meta Ads. twelvebit deletes the token and the stored spend. To stop the token in Meta too, remove it from the system user in Meta Business Settings.

## API and MCP

`get_integrations` (MCP) and `GET /api/v1/integrations` (REST) show `meta_ads` with the account name, the currency and the days with spend. `disconnect_integration` (MCP) and `DELETE /api/v1/integrations/meta_ads` (REST) disconnect it. A token never shows in the API.

---

Source: https://twelvebit.app/docs/meta-ads · All docs: https://twelvebit.app/llms.txt
