Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
a4dbd06
docs(integrations): draft the Meta Ads performance marketing page
DreamingInBinary Aug 13, 2026
4fe48f1
docs(integrations): swap in the three Meta campaign screenshots
DreamingInBinary Aug 13, 2026
676ce92
docs(integrations): recommend sw_transaction_start as the conversion …
DreamingInBinary Aug 13, 2026
b956ff7
docs(integrations): rasterize the remaining MMP placeholders to JPEG
DreamingInBinary Aug 14, 2026
ec71429
Merge remote-tracking branch 'origin/main' into jordan/sw-5719-mmp-docs
DreamingInBinary Aug 14, 2026
6a9f000
docs(integrations): fix dataset creation path to match current Meta UI
DreamingInBinary Aug 14, 2026
936bbfa
docs(integrations): strip review highlighting from the Meta Ads page
DreamingInBinary Aug 14, 2026
d7c9f5c
docs(integrations): dataset creation goes through Connect data
DreamingInBinary Aug 14, 2026
4d9fe57
docs(integrations): document the Dataset Quality API choice before to…
DreamingInBinary Aug 14, 2026
ae193e7
docs(integrations): add three dashboard screenshots and fix the Revie…
DreamingInBinary Aug 14, 2026
809e9e7
docs(integrations): show the confirmed sw_ events state in Events Man…
DreamingInBinary Aug 14, 2026
9afa5fe
docs(integrations): tie event confirmation to the warning clearing, n…
DreamingInBinary Aug 14, 2026
efd5e5f
docs(integrations): clarify the default product page needs no URL
DreamingInBinary Aug 14, 2026
eb187e2
docs(integrations): add the Ads links screenshot, completing the imag…
DreamingInBinary Aug 14, 2026
80d8feb
docs(integrations): close step 5 with publishing the campaign
DreamingInBinary Aug 14, 2026
8774e8d
docs(integrations): illustrate the Advertising chart group
DreamingInBinary Aug 14, 2026
c668001
docs(charts): add the six Advertising chart pages
DreamingInBinary Aug 14, 2026
8a65b83
docs(integrations): name the exact Meta UI locations for placements a…
DreamingInBinary Aug 14, 2026
71f36f6
docs(integrations): restyle the Meta Ads cross-link as a standard note
DreamingInBinary Aug 14, 2026
b069371
docs: apply the claim audit fixes across the MMP pages
DreamingInBinary Aug 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions content/docs/dashboard/charts/ad-spend.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
title: "Ad Spend"
description: "Learn what the Ad Spend chart measures and when to use it."
---

<Frame>![Ad Spend chart](/images/charts/ad-spend.jpg)</Frame>

## What it shows

Ad Spend shows the daily spend reported by your connected ad network accounts, currently Meta.

## How to use it

Track what your campaigns cost alongside what they return. Break down by Acquisition Campaign to compare campaigns, or view it next to [ROAS](/dashboard/charts/roas).

## Good to know

Spend syncs from Meta once a day, starting from the date you connected your Meta account. Earlier spend is not imported.

Advertising charts appear once performance marketing is enabled for your app. See [Meta Ads](/integrations/meta-ads).
22 changes: 22 additions & 0 deletions content/docs/dashboard/charts/blended-cpt.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
title: "Blended CPT"
description: "Learn what the Blended CPT chart measures and when to use it."
---

<Frame>![Blended CPT chart](/images/charts/blended-cpt.jpg)</Frame>

## What it shows

Blended CPT shows your total ad spend across all campaigns divided by all trial starts, paid and organic.

## How to use it

Use it to see what a trial costs you overall, counting the organic trials that paid acquisition may also be driving.

## Good to know

Blended CPT is a single blended figure and intentionally has no breakdown. Splitting it per campaign would turn it into plain [CPT](/dashboard/charts/cpt).

Because values are cohorted by install date, the chart defaults to weekly intervals.

Advertising charts appear once performance marketing is enabled for your app. See [Meta Ads](/integrations/meta-ads).
20 changes: 20 additions & 0 deletions content/docs/dashboard/charts/cpm.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
title: "CPM"
description: "Learn what the CPM chart measures and when to use it."
---

<Frame>![CPM chart](/images/charts/cpm.jpg)</Frame>

## What it shows

CPM shows your cost per 1,000 ad impressions, from the spend and impressions your connected ad accounts report.

## How to use it

Monitor what reach costs over time and compare it across campaigns. A rising CPM with flat results means you're paying more for the same audience.

## Good to know

CPM comes from spend and impressions alone. It doesn't depend on install attribution, so it works even for campaigns with no attributed installs yet.

Advertising charts appear once performance marketing is enabled for your app. See [Meta Ads](/integrations/meta-ads).
20 changes: 20 additions & 0 deletions content/docs/dashboard/charts/cpp.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
title: "CPP (Cost per Paid User)"
description: "Learn what the CPP chart measures and when to use it."
---

<Frame>![CPP chart](/images/charts/cpp.jpg)</Frame>

## What it shows

CPP shows ad spend per new paying user, cohorted by install date.

## How to use it

Break down by Acquisition Campaign to compare what a paying user costs you from each campaign. This is the number to watch if your app sells without trials.

## Good to know

Because values are cohorted by install date, daily buckets miss most spend-to-purchase matches. The chart defaults to weekly intervals and warns you when Daily is selected.

Advertising charts appear once performance marketing is enabled for your app. See [Meta Ads](/integrations/meta-ads).
24 changes: 24 additions & 0 deletions content/docs/dashboard/charts/cpt.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
title: "CPT (Cost per Trial)"
description: "Learn what the CPT chart measures and when to use it."
---

<Frame>![CPT chart](/images/charts/cpt.jpg)</Frame>

*The example above is flat because this app doesn't offer trials.*

## What it shows

CPT shows ad spend per trial start, cohorted by install date.

## How to use it

Break down by Acquisition Campaign to compare what a trial costs you from each campaign.

## Good to know

Because values are cohorted by install date, daily buckets miss most spend-to-trial matches. The chart defaults to weekly intervals and warns you when Daily is selected.

If your app doesn't offer trials, use [CPP](/dashboard/charts/cpp) instead.

Advertising charts appear once performance marketing is enabled for your app. See [Meta Ads](/integrations/meta-ads).
8 changes: 8 additions & 0 deletions content/docs/dashboard/charts/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ Currently, we offer the following charts:
- [**Refund Rate**](/dashboard/charts/refund-rate): Ratio of refunds to gross proceeds, cohorted by first purchase date.
- [**Subscription Retention**](/dashboard/charts/subscription-retention): Subscription retention by cohort over time.

#### Advertising Charts
- [**Ad Spend**](/dashboard/charts/ad-spend): Daily spend from your connected ad network accounts.
- [**ROAS**](/dashboard/charts/roas): Return on ad spend: proceeds cohorted by install date, divided by spend.
- [**CPM**](/dashboard/charts/cpm): Cost per 1,000 ad impressions.
- [**CPT (Cost per Trial)**](/dashboard/charts/cpt): Ad spend per trial start.
- [**CPP (Cost per Paid User)**](/dashboard/charts/cpp): Ad spend per new paying user.
- [**Blended CPT**](/dashboard/charts/blended-cpt): Total ad spend divided by all trial starts, paid and organic.

### Filtering chart data
To filter data on a chart, **click** the **Filter** button at the top right:

Expand Down
9 changes: 8 additions & 1 deletion content/docs/dashboard/charts/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@
"---Retention & Churn---",
"subscriber-churn",
"refund-rate",
"subscription-retention"
"subscription-retention",
"---Advertising---",
"ad-spend",
"roas",
"cpm",
"cpt",
"cpp",
"blended-cpt"
]
}
22 changes: 22 additions & 0 deletions content/docs/dashboard/charts/roas.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
title: "ROAS"
description: "Learn what the ROAS chart measures and when to use it."
---

<Frame>![ROAS chart](/images/charts/roas.jpg)</Frame>

## What it shows

ROAS shows your return on ad spend: proceeds cohorted by install date, divided by ad spend.

## How to use it

Break down by Acquisition Campaign to see which campaigns pay back. A value above 1 means a cohort has earned back more than it cost to acquire.

## Good to know

ROAS defaults to an Acquisition Campaign breakdown so you can see which campaigns pay back. Without a breakdown it shows one blended figure across every network with ad spend, which hides how individual campaigns perform.

Because values are cohorted by install date, daily buckets read close to zero. The chart defaults to weekly intervals and warns you when Daily is selected.

Advertising charts appear once performance marketing is enabled for your app. See [Meta Ads](/integrations/meta-ads).
Binary file added content/docs/images/charts/ad-spend.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/docs/images/charts/blended-cpt.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/docs/images/charts/cpm.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/docs/images/charts/cpp.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/docs/images/charts/cpt.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/docs/images/charts/roas.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/docs/images/mmp_meta_ad_links.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/docs/images/mmp_meta_ad_website_url.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/docs/images/mmp_meta_dataset_token.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/docs/images/mmp_meta_events_to_send.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
232 changes: 232 additions & 0 deletions content/docs/integrations/meta-ads.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
---
title: "Meta Ads"
description: "Run Meta ads with Superwall as your mobile measurement partner. Superwall attributes installs to your campaigns and sends conversion events back to Meta."
---

The Meta Ads integration makes Superwall your mobile measurement partner (MMP) for Meta campaigns. Superwall generates the links you put in your ads, attributes installs to the campaign, ad set, and ad that drove them, and sends conversion events back to Meta so it can optimize delivery. Spend and results show up in [charts](/dashboard/charts) as ROAS, cost per trial, and cost per paid user.

This integration is separate from [Meta Conversion API](/integrations/meta-conversion-api), which forwards subscription webhook events to a Meta Pixel.

<Note>
We are gradually rolling out performance marketing. If you don't see
**Performance Marketing** under **Integrations**, reach out to us at
[support@superwall.com](mailto:support@superwall.com) and we'll enable it for
your app.
</Note>

## Requirements

- An iOS app using [SuperwallKit](/ios) 4.16.0 or later. Meta Ads attribution is iOS only for now.
- [Revenue tracking](/dashboard/dashboard-settings/overview-settings-revenue-tracking) configured for your app.
- A Meta ad account you have admin access to, and access to [Meta Events Manager](https://business.facebook.com/events_manager2).
- If you sell outside of Superwall paywalls, enable [observer mode](/ios/guides/advanced/observer-mode) so transactions are tracked.

<Warning>
Attribution only applies to new installs. The SDK matches an install once,
shortly after first launch, and only within 7 days of install. Users who
installed your app before it shipped with SDK 4.16.0 are never attributed, so
test with a fresh install.
</Warning>

## Step 1: Set up your Meta dataset

Superwall sends conversion events to a Meta dataset. Set it up before connecting Superwall:

1. Go to [Meta Events Manager](https://business.facebook.com/events_manager2). If you don't have a dataset, click **Connect data** and follow the prompts to create one.
2. Link the dataset to the ad account you'll run campaigns from.
3. Generate an access token: open your dataset, go to **Settings** > **Conversions API**, and find **Set up direct integration**. Leave **Set up with Dataset Quality API** selected, then click **Generate access token**. Copy it for the next step.

## Step 2: Connect Meta in Superwall

<Steps>
<Step title="Open the integration">
In your app's dashboard, go to **Integrations**, find **Performance Marketing**, and click the **Meta** card.

<Frame>![The Integrations page showing the Performance Marketing section with the Meta card](/images/mmp_performance_marketing_section.jpg)</Frame>
</Step>
<Step title="Connect your Meta account">
Click **Connect account** and sign in with a Facebook account that has admin access to your business portfolio.
</Step>
<Step title="Choose your dataset and paste the access token">
Pick your dataset from the **Dataset** dropdown. If it isn't listed, click **Refresh datasets** or paste the dataset ID manually. Paste the access token from step 1 into **Conversion API Access Token** and click **Save**. The button reads **Update** when you're editing an existing configuration. Superwall validates both against Meta before saving.

<Frame>![The Meta setup page with the Dataset dropdown and Conversion API Access Token field](/images/mmp_meta_dataset_token.jpg)</Frame>
</Step>
</Steps>

## Step 3: Choose events to send

Superwall sends these events to your dataset. All six are on by default; leave them on unless you have a reason not to.

| Dashboard label | Superwall event | Sent to Meta as |
|-----------------|-----------------|-----------------|
| Paywall Open | `paywall_open` | `sw_paywall_open` |
| Transaction Start | `transaction_start` | `sw_transaction_start` |
| Transaction Abandon | `transaction_abandon` | `sw_transaction_abandon` |
| Free Trial Start | `freeTrial_start` | `sw_freeTrial_start` |
| Subscription Start | `subscription_start` | `sw_subscription_start` |
| One-Time Purchase | `nonRecurringProduct_purchase` | `sw_nonRecurringProduct_purchase` |

<Frame>![The Events to send card with all six events checked](/images/mmp_meta_events_to_send.jpg)</Frame>

Events are sent for every user, not just users attributed to your ads. Meta uses them for delivery optimization and its own attribution.

Meta requires you to acknowledge new custom events and allow the domain they come from:

<Steps>
<Step title="Send test events">
Click **Save changes**, then **Send test events to Meta**. The button stays disabled until your event selection is saved. The events appear in your dataset's **Test events** tab within a few minutes.
</Step>
<Step title="Confirm the custom events">
Once the test events arrive, open your dataset's **Overview** tab in Events Manager. A warning appears: **Confirm custom event(s) that belong to you**. Click **Review events**, click **I acknowledge**, select all events starting with `sw_`, click **Next**, then choose **Confirm custom event** and click **Confirm**. Events can take up to 30 minutes to reach the **Overview** tab, and if no warning appears, the events were already confirmed.

Once confirmed, the warning goes away and the `sw_` events stay listed in the **Overview** events table under the **Conversions API** integration:

<Frame>![A confirmed sw_subscription_start event listed in the dataset's Overview events table under the Conversions API integration](/images/mmp_meta_events_confirmed.jpg)</Frame>
</Step>
<Step title="Allow the superwall.com domain">
In your dataset's **Settings**, under **Traffic permissions - websites**, click **Create allow list** and add `superwall.com`.
</Step>
</Steps>

## Step 4: Create your ad links

Under **Ads links**, Superwall generates the URL you'll use in your Meta ads.

<Steps>
<Step title="Add a link">
Click **+ Add ad link** and pick an App Store language. Create one link per storefront language you advertise in. The link automatically sends people to your app's default App Store product page, so there's nothing else to fill in. Only add a URL under **Custom product page (optional)** if you want the ad to open a custom product page instead.
</Step>
<Step title="Save to activate">
Click **Save changes**. A link only starts working after it's saved.
</Step>
<Step title="Copy the link">
Click the URL in the **Website URL** column to copy it. It already includes the parameters Meta fills in with your campaign, ad set, and ad details, so don't edit them.

<Frame>![The Ads links table with a saved English link showing the copyable Website URL](/images/mmp_meta_ad_links.jpg)</Frame>
</Step>
</Steps>

<Warning>
Deleting or disabling a link immediately breaks any live ads pointing at it.
Keep links in place while campaigns are running.
</Warning>

## Step 5: Create your Meta campaign

Superwall ad links are website links. That means you'll run a **Sales** campaign with a website conversion location, not an App Promotion campaign, even though the goal is installs. When someone taps your ad, the link records the click and sends them straight to the App Store.

<Steps>
<Step title="Create a manual Sales campaign">
In Ads Manager, click **Create** and choose the **Sales** objective. Set the campaign up manually; don't use Meta's AI-assisted setup.

<Frame>![Meta Ads Manager campaign creation with Manual campaign setup and the Sales objective selected](/images/mmp_meta_campaign_objective.jpg)</Frame>
</Step>
<Step title="Point the ad set at your dataset">
Set **Conversion location** to **Website**. Choose your dataset and the conversion event to optimize for. We recommend `sw_transaction_start`, since starting a transaction signals purchase intent.

<Frame>![The ad set level showing Website conversion location, the dataset, and the conversion event](/images/mmp_meta_adset_conversion.jpg)</Frame>
</Step>
<Step title="Restrict placements to iOS">
Under **Placements**, click **Show more settings**, then limit devices to **Mobile** and operating systems to **iOS**, and turn off **Audience Network**.
</Step>
<Step title="Add the link to your ad">
Paste the Superwall link into the ad's **Website URL** field. Leave **URL parameters** under the ad's **Tracking** section empty; the link already carries them.

<Frame>![The ad level with the Superwall link pasted into the Website URL field](/images/mmp_meta_ad_website_url.jpg)</Frame>
</Step>
<Step title="Publish the campaign">
Click **Publish** to put your campaign and ads live.
</Step>
</Steps>

## Verify it's working

- Test events appear in the **Test events** tab of your dataset in Events Manager.
- Once ads run, attributed users appear in Superwall with `acquisition_` user attributes set and an `attribution_match` event in their event stream.
- The **Advertising** charts populate after spend syncs from Meta, which happens daily.

## How attribution works

When someone taps your ad, Superwall records the click along with its IP address, device signals, and the campaign parameters Meta filled into the link, then sends them on to the App Store. When the app launches for the first time, the SDK asks Superwall to match the install against recent clicks. Matching is probabilistic: IP address, how recently the click happened, platform, language, timezone, and screen size all contribute to a score, and the install is attributed only when the score clears a threshold.

- Matching runs once per install, within 7 days of install.
- No ATT prompt or IDFA is required; matching never uses them.
- Unmatched installs stay unattributed and show as `Organic` in charts.

### User attributes

A matched install sets these user attributes. Attributes without a value are omitted.

| Attribute | Value |
|-----------|-------|
| `acquisition_source` | The network that drove the install, like `meta` |
| `acquisition_network` | Same as `acquisition_source` |
| `acquisition_channel` | Always `paid` |
| `acquisition_campaign_name` | The Meta campaign name |
| `acquisition_campaign_id` | The Meta campaign ID |
| `acquisition_ad_set_name` | The ad set name |
| `acquisition_ad_set_id` | The ad set ID |
| `acquisition_ad_name` | The ad name |
| `acquisition_ad_id` | The ad ID |
| `acquisition_placement` | The Meta placement that showed the ad |
| `acquisition_site_source_name` | Where the ad ran, like `ig` or `fb` |
| `acquisition_link_id` | The Superwall ad link ID |
| `acquisition_click_id` | The matched click ID |
| `acquisition_matched_at` | When the match happened |
| `acquisition_app_store_language` | The link's App Store language |
| `acquisition_product_page_id` | The Custom Product Page ID, when the link uses one |
| `acquisition_deeplink_id` | The link's deep link ID, when set |

Use them as breakdowns and filters in [charts](/dashboard/charts), or in [audience filters](/dashboard/dashboard-campaigns/campaigns-audience) to show different paywalls to users acquired from ads.

### The attribution_match event

The SDK tracks `attribution_match` when the match request completes, matched or not.

| Parameter | Value |
|-----------|-------|
| `provider` | `mmp`, or `apple_search_ads` for Apple Search Ads attribution |
| `matched` | Whether the install was attributed |
| `source` | The network, like `meta` |
| `confidence` | `high`, `medium`, or `low` |
| `match_score` | The match score |
| `reason` | Why a match failed: `below_threshold`, `ambiguous`, or `request_failed` |

The event and its parameters are available in charts and audience filters. It can't be used to trigger a paywall directly.

## Charts

With the integration enabled, Superwall pulls campaign spend from Meta daily and adds an **Advertising** chart group:

<Frame>![The Advertising chart group in the Charts sidebar, listing Ad Spend, ROAS, CPM, CPT, CPP, and Blended CPT](/images/mmp_advertising_chart_section.jpg)</Frame>

- **[Ad Spend](/dashboard/charts/ad-spend)**
- **[ROAS](/dashboard/charts/roas)**: proceeds divided by spend
- **[CPM](/dashboard/charts/cpm)**: cost per thousand impressions
- **[CPT](/dashboard/charts/cpt)**: cost per trial
- **[CPP](/dashboard/charts/cpp)**: cost per paid user
- **[Blended CPT](/dashboard/charts/blended-cpt)**: total spend divided by all trials, including organic

Revenue charts can also be broken down by **Acquisition network** and **Acquisition campaign** to split any metric by the campaign that acquired the user. Those breakdowns fill in as installs match; unmatched installs group under `Organic`.

## Troubleshooting

### Installs aren't being attributed

- The app must ship SuperwallKit 4.16.0 or later, and the install must be new. Delete and reinstall the app to test; updating an existing install never attributes.
- Matching only runs within 7 days of install.
- `SuperwallOptions.eventTrackingBehavior` must not be set to `.none`. That setting disables install matching entirely.
- The ad link must be saved and enabled. A deleted or disabled link returns a 404 and records no clicks.

### Events aren't showing in Meta

- Sandbox purchases are never forwarded. Only production events are sent to Meta; use **Send test events to Meta** to validate before going live.
- Confirm the dataset ID and access token still validate by editing and re-saving the configuration.
- Confirm the `sw_` custom events in **Review events** in Events Manager.
- Add `superwall.com` to the dataset's website traffic allow list.

### No transaction or purchase events

- If you sell outside of Superwall paywalls, enable [observer mode](/ios/guides/advanced/observer-mode).
- Check that [revenue tracking](/dashboard/dashboard-settings/overview-settings-revenue-tracking) is configured. Subscription events come from App Store server notifications.
Loading
Loading