Get ROAS for your ads

See real revenue next to your ad spend on Meta, TikTok, and Google. No affiliate program required.

Where each number comes from

The ads dashboards mix three data sources. Two arrive on their own; one needs a five-minute setup.

Metric
Where it comes from
What it needs
Spend, impressions, clicksThe ad network's API, synced nightlyJust connecting your ad account
Reported conversionsThe network's own claimed results (it grades its own homework)Whatever conversion setup the network has
Verified Revenue, ROAS, LTVReal sales Affiliateo tracked on your site, matched to the exact ad click that caused themThe two wires below

If your Revenue column shows a dash, money is going out but your site isn't wired in yet. Nothing is broken; Affiliateo just has no way to see your sales.

The two wires

Verified ROAS needs exactly two things, set up once per website.

1

The tracking snippet on your site. One script tag, installed once. It notices when a visitor arrives from an ad (Google, Meta, and TikTok click IDs are caught automatically) and remembers them.

2

Your payment provider connected (Stripe, Shopify, WooCommerce, Polar, Paddle, or Whop). This is what reports each sale. No code involved; you just log in.

When a tracked visitor buys, the sale is matched to the exact campaign that brought them. That match is your verified ROAS, and it works for any number of campaigns pointing at any number of sites.

Set it up

From any ads app (Meta, TikTok, or Google):

1

Open the ads app settings (the gear icon) and find "Track your sales".

2

Enter your website URL, pick your payment provider, and connect it.

3

Install the snippet on your site (shown right there after connecting).

4

Done. From the next ad click on, sales are matched to campaigns and the Revenue and ROAS columns fill in.

Running ads for more than one website? Add each one (up to 10). Every campaign is matched to whichever site its clicks actually land on, automatically.

No affiliate program required

Tracked sites added this way are not affiliate apps: they cannot be joined, never appear on Discover, and pay no commissions to anyone. If you already run affiliate apps on Affiliateo, their sites are counted automatically and you don't need to add anything.

Affiliates running ads

Advertise your affiliate link with your own ad account and see what your ads earn.

1

Create your own business in Affiliateo and connect your Meta, TikTok, Snapchat or Google ad account in its ads app.

2

Use your affiliate link as the ad's link. Campaigns you launch in Affiliateo tag it by themselves. For a campaign built in the network's own ads manager, add the URL parameters from that ads app's settings, so each click carries the campaign id.

3

When someone buys through that ad, the campaign's revenue in your Ads dashboard is the commission you earned, so ROAS is commission divided by spend. The row is marked as an affiliate campaign for that business, with what the buyers paid beside it. Nothing else of the business's sales is shown.

Sending those sales to the affiliate's own ad account

Each Affiliate app has the switch Let affiliates send the sales they bring to their own ad accounts, in its create and edit settings under the commission. It is off by default. When it is on, a sale an affiliate's own ad brought through that app is also sent to that affiliate's pixel or Google conversion action, so their campaigns can learn who buys.

Only sales whose click came from the affiliate's own ad and whose credit is that affiliate. The value is the affiliate's commission and the event id is the affiliate's own, so nothing counts twice for the business. Only the ad's click id and the browser's user agent go with it, never the buyer's email. An app sale goes as a website purchase tied to the ad click, because the click went through the affiliate's web link. A sale from a phone that said no to ad tracking, or made while the switch was off, is not sent.

Affiliates see how these sends went in their ads app's settings, under Sales from your affiliate links. Developers and AI assistants set the switch as share_ad_sales_with_affiliates on the app and read the sends with GET /ads/affiliate-sales.

Google may reject an ad whose link jumps to another domain, so on Google link to the business's own page with ?ref= followed by your affiliate code. Meta, TikTok and Snapchat take an affiliate link on a website campaign. App install campaigns link to the store listing, so they can't carry an affiliate link.

Choose your tracking setup

What to add to your website or app for each kind of ad, and who sends the purchases.

What you advertise
Visits, steps and installs
Purchases
A website, on Meta, TikTok or SnapchatThe network's own pixel, for page views, add to cart and checkoutOne sender per network: Affiliateo (recommended) or the pixel
A website, on GoogleThe Google tag, for visitsAffiliateo sends them, with one primary purchase goal
A phone app, with app install ads on Meta, TikTok or SnapchatThe network's own SDK in your app, or a measurement partner. You need one: Affiliateo doesn't count installsOne way only: the network's SDK, or Affiliateo's Send app sales
A phone app, with Google app campaignsAndroid: link Google Play to Google Ads, no code. iPhone: Google's Firebase SDK, linked to Google AdsGoogle Play or Firebase reports them. Affiliateo can't send app sales to Google

Website purchases: we recommend Affiliateo, because the server also catches sales that ad blockers hide. Turn off the pixel's own Purchase event and turn on Sales with no click id. To let the pixel send purchases instead, keep its Purchase event and turn off Pixel in that ads app's settings. On Google, keep the Google tag for visits and let Affiliateo send purchases, with only one purchase goal as primary.

App purchases: pick one way per network. The simplest is to let the network's SDK log them and leave Send app sales off for that network. Or turn on Affiliateo's Send app sales: a payment is sent only after the store confirms it, and a free trial that turns paid while the app is closed still counts. Then turn off the SDK's own purchase logging (the steps are further down this page).

Sales or trial starts: if your app has a free trial and only a few sales a week, set Send app sales to Trial starts for that network, so the campaign learns from trial starts. Otherwise keep Sales, so it learns who pays. Trial starts go as the network's trial event, never as a purchase, and renewals and refunds are never sent.

TikTok only takes app sales from a server after your TikTok rep switches this on for your ad account. Until then, let TikTok's SDK log the purchases.

Google app campaigns: on Android, link Google Play to Google Ads, with no code. On iPhone, add Google's Firebase SDK (Google Analytics for Firebase) and link it to Google Ads. Affiliateo can't send app sales to Google.

Affiliateo's link that sends iPhones to the App Store and Android phones to Google Play is for creators and affiliates to share. Don't use it as an ad's link: Google rejects ads whose link jumps to another domain, and Meta and TikTok app ads link to the store listing directly.

Never send the same purchase to one network two ways. It counts twice.

None of this needs the "Allow tracking?" prompt on iPhone.

The pixel is optional (and separate)

The pixel in each ads app's settings does not affect your Affiliateo numbers. It reports the sales Affiliateo already tracked back to the ad network, so the network's own dashboard shows purchases and its bidding can optimize. Turn it on or off any time; your verified ROAS is unaffected.

If your website also has the network's own pixel (Meta Pixel, TikTok Pixel, Snap Pixel or Google's tag), keep it for page views, add to cart and checkout. Purchases need one sender per network, never two: the network only matches two reports of a sale when they carry the same ID, so with both on it counts every sale twice.

We recommend letting Affiliateo send purchases, because the server also reports sales that ad blockers and browsers hide. Turn off the pixel's own Purchase event, then turn on Sales with no click id on that network's Conversion reporting card, under Measurement. That sends each sale with the buyer's email, hashed, so the network also hears about buyers who saw an ad without clicking or who switched devices. Without it, Affiliateo only sends sales from buyers who came straight from that network's ad.

To let your pixel send purchases instead, keep its Purchase event and turn off Pixel in this ads app's settings. Do the same if your store already reports purchases through its own app or plugin, such as Shopify's Facebook & Instagram app or a WooCommerce plugin. On Google, count only one purchase goal, the one Affiliateo set up or your tag's, never both.

Mobile apps

In any ad network's settings, open Track your sales and pick Track a mobile app. Choose how your app takes payments (RevenueCat, Apple In-App Purchase, Google Play, Adapty or Stripe) and add the Affiliateo SDK to the app. Your app's sales then count as revenue here, with no affiliate program. Apple Search Ads gets the full picture: the SDK ties installs and sales to the campaign, so you see real ROAS. For Google, Meta, TikTok and Snapchat ads, the app store doesn't tell Affiliateo which ad led to an install, so those sales add to your total revenue but can't be tied to one campaign here. Those networks measure their own app campaigns through their own SDK or a measurement partner, as the next section explains.

Trials and payments from each campaign

For a campaign that sends people to one of your apps, the Campaigns table also shows what happened inside the app in the dates you picked: Downloads (phones that opened the app for the first time after the ad, counted by Affiliateo, so it can differ from the network's own Installs), Trials, Cost per trial, Trial rate, Paying (people who paid you for the first time, after a free trial or straight away), Cost per paying customer and Paid rate. A row of cards above the table adds them up.

The ROAS day column takes the people who downloaded in those dates and divides what they paid within 1, 2, 4, 7 or 30 days of downloading by what the ads cost. Pick the day in the ROAS day box beside the date range: it changes both the ROAS day card above the table and the column. The column is on the Campaign tab, and on Apple Ads on the Ad group and Keyword tabs too, because Apple names the ad group and keyword of each install. The number can still go up while some of those people have not had that many days yet. Payback is how many days after downloading they had paid back the spend, or how much has come back until then. Trial rate and Paid rate follow the same people: of those downloads, the share that started a free trial within 7 days of first opening the app, and the share that paid for the first time within 30 days.

Renewal off is the share of those trials whose person turned off renewal before the first charge. Every row also shows Click to install (Tap to install on Apple Ads, Click to conversion on the networks whose conversion column is not installs): the network's installs or conversions divided by its clicks, both as the network counts them.

A campaign belongs to the apps its downloads and sales went to (an Apple Ads campaign also to the app it promotes). With more than one app, the App buttons above the table show one app's campaigns and numbers at a time. The same numbers are on the API (GET …/ads, with ?app=) and the MCP's get_ad_stats.

Apple Ads keywords by country

On the Apple Ads page, the Keyword tab has one table: each keyword with its on and off switch and bid, Apple's spend, installs and cost per install, and what the people it brought did in your app in the same dates. Trials are free trials started within 7 days of the install, and Paying is the people who paid for the first time within 30 days. CAC, LTV and LTV:CAC are on the same row. The Country box shows one country's figures on their own. A Search Match row per ad group holds the installs Apple gives no keyword, so the rows add up to the ad group. Est. CAC is spend divided by paying customers.

Est. LTV is what a paying customer is expected to bring in over 12 months: what they paid so far, plus their price times the renewals still to come at their plan's renewal rate (how often first payments of that plan renewed, mixed with a typical rate while there is little data). A one-time purchase is worth what was paid. Amounts are what the buyer paid, before the store's cut, like the Revenue page. LTV:CAC is green from 3x, amber from 1x and red below 1x.

The trend compares the dates you picked with the same number of days just before (yesterday with the day before, the last 7 days with the 7 before), with the earlier installs counted at the same age. All time has nothing before it, so it shows a dash. Installs younger than 30 days are still counting.

On the Search terms tab, the + beside a term adds it as a keyword: pick the ad group, the match type and a bid. It starts paused unless you turn it on. The same numbers are on the API (GET .../ads/keywords-economics) and the MCP tool get_apple_keyword_economics.

Send app sales to Meta, TikTok and Snapchat

App campaigns get better when the ad network knows who pays, not only who installs. In the Meta, TikTok or Snapchat settings here, open Send app sales and paste the network's ID for your app: the Meta dataset ID, the TikTok App ID or the Snap App ID. Each first payment in that app then goes to the network: a subscription's first charge, or a one-time purchase. If your app's payments come through RevenueCat, Apple, Google Play or Adapty connected here, you're done: they're sent on their own. You can also add one line to your paywall, right after a purchase succeeds. It sends the phone's network address too, which helps the network match. Either way, each payment is sent once.

With RevenueCat

Paywall.swift
// RevenueCat
let result = try await Purchases.shared.purchase(package: package)
if !result.userCancelled, let transaction = result.transaction {
    Affiliateo.purchase(
        transactionId: transaction.transactionIdentifier,
        productId: transaction.productIdentifier,
        price: package.storeProduct.price,
        currency: package.storeProduct.currencyCode ?? "USD"
    )
}

With StoreKit 2

Paywall.swift
// StoreKit 2
if case .success(.verified(let transaction)) = try await product.purchase() {
    Affiliateo.purchase(transaction)
    await transaction.finish()
}

Affiliateo sends payments, not installs. App campaigns count installs through the network's own SDK in your app or a measurement partner (AppsFlyer, Adjust, Branch, Singular or Kochava). So an app that runs ads on Meta, TikTok or Snapchat adds that network's SDK, or a partner, for installs, and keeps Send app sales on for payments.

Send each network your app's purchases one way only, or it counts every sale twice. Keep the network's SDK for installs, but turn its purchase reporting off. Meta: in your app on Meta for Developers, under Settings > Basic, set the switch that logs in-app purchases automatically to No on the iOS and Android cards. Leave the SDK's automatic logging itself on, because turning that off stops installs too. TikTok: on iPhone, call disablePaymentTracking() on its config; on Android, don't call enableAutoIapTrack() or trackGooglePlayPurchase(). Snapchat: don't send purchases from its SDK. A measurement partner that forwards purchases to the network counts too: stop forwarding them, or leave Send app sales off for that network.

In Send app sales, choose what each app sends to each network: Sales, Trial starts or Both. Sales sends each customer's first payment as a purchase, and a free trial's first real charge counts as one. Trial starts sends only the start of each free trial, as the network's trial event: StartTrial on Meta and TikTok, START_TRIAL on Snapchat. It's never sent as a purchase. Both sends the two as separate events.

Pick Sales for most apps, so the campaign learns who pays. Pick Trial starts if your app has a free trial and only a few sales a week: trial starts come days sooner and more often, so the campaign learns faster. With Both, pick one of the two as the campaign's goal in the network's ads manager.

A trial start is sent only after the store confirms it, so it needs your payment provider connected here: RevenueCat, Apple, Google Play or Adapty. It's sent with a value of 0, because nobody has paid yet. On Meta and Snapchat, the plan's price goes with it as its predicted value. Renewals and refunds are never sent.

Why let Affiliateo send the payments rather than each network's SDK: a payment is sent only after the store confirms it was really paid, each sale goes out once, a first payment still counts when it happens while the app is closed (a free trial turning paid days later, for example), one setup here covers Meta, TikTok and Snapchat, and you switch a network on or off without an app update. A network's SDK mostly sees what happens while the app is open.

A payment your payment provider reports by itself carries no details about the phone. Affiliateo matches it to the phone that bought, using the network address the phone last used in your app. That address is kept for up to 35 days, and only while Send app sales is on for the app. The paywall line above still matches best.

On iPhone, your app doesn't need the "Allow tracking?" prompt. A payment from someone who didn't tap Allow is still sent, marked as not allowed to track and without Apple's device IDs, and the network uses it only in its limited, privacy-safe way. Someone who did tap Allow is sent with the advertising ID, which matches best. When Meta's SDK is in your app, Affiliateo's SDK also sends Meta's anonymous ID with each payment (Swift, Kotlin and React Native), so Meta ties the payment to the install its SDK saw, including for people who didn't tap Allow.

TikTok only accepts app sales from a server after it switches the feature on for your ad account, so ask your TikTok rep. Google gets app sales from Google Play or Firebase instead, so it isn't listed. Renewals and refunds aren't sent, and your revenue here still subtracts refunds.