Profit tracking: bid on profit, not revenue
Google Ads and Meta optimise for the conversion value you send them. For most shops that is revenue, so bidding treats a €100 order with a 10% margin the same as a €100 order with a 60% margin. Profit tracking sends the profit of every order instead, so your campaigns chase the orders that actually earn money. That is bidding on POAS (profit on ad spend) rather than ROAS.
How it works
Every purchase passes your tagging server before it reaches your server container. When profit tracking is on, the tagging server looks up the cost price of each item in the order, calculates the profit and adds it to the event as mb_profit. In your server container that is plain event data: use {{ed - mb_profit}} as the conversion value in your Google Ads and Meta tags.
- Your cost prices stay private. They live on your tagging server. They never reach the browser, your Tag Manager container or the ad platforms. Google and Meta only see the profit number of each order.
- No extra template or API call. Nothing new to import into GTM and no password in a variable. The profit is on the event before the container sees it.
- Server-side purchases too. Purchases sent by the Shopify app, the WordPress plugin or the Shopware plugin pass the same tagging server and get the same profit.
The calculation
Per purchase, from the items in the event:
- Revenue excl. VAT. The item prices as your event sends them, after discounts, without VAT when your prices include it. Shipping the customer pays counts too if you choose so.
- Minus cost prices. Each item's cost price times its quantity. Items without one use your fallback margin.
- Minus order costs. A fixed cost per order (picking, packing), your shipping cost per order, and the payment fee as a percentage plus a fixed amount.
- Minus expected returns. An optional return rate lowers the profit of every order by that share.
An order that makes a loss sends mb_profit as 0, because Google Ads and Meta do not accept a negative conversion value. The dashboard still shows the real number.
Where the cost prices come from
- A feed. A Google Merchant Center feed with
cost_of_goods_sold, a Channable feed, or any public CSV, JSON or XML file. Measurebase reads it every day. - A file. Upload a CSV, TSV, JSON or XML file of up to 20 MB, and upload a new one when your cost prices change.
- Shopify. The cost per item of every variant, which you already keep in Shopify. Choose Use Shopify cost prices in the Measurebase app. It asks once for permission to read cost prices, and syncs them every night.
- WooCommerce. The WordPress plugin sends the cost price of every product and variation once a day. It reads WooCommerce's own cost of goods, the common cost-of-goods plugins, or a custom field you name. Switch it on under Settings, Measurebase, WooCommerce.
- Shopware. The Shopware plugin sends the net purchase price of every product and variant once a day. Switch it on in the plugin configuration under Profit tracking (POAS).
Measurebase matches on every identifier a product has: product ID, variant ID, SKU and GTIN. Whichever one your events use as item_id, it finds the cost price. When your events send the product ID and the variants of that product have different cost prices, the product counts with their average.
Fallback margins
Not every product has a cost price: gift cards, new arrivals, bundles. Set a fallback margin, globally or per item_category, and those items count with that margin instead of disappearing from the profit. Without a fallback, an item without a cost price adds no profit.
Setting it up
- Add your cost prices. In the dashboard, open your domain, then Advanced tracking, Profit tracking. Choose a feed, a file or your shop.
- Set your order costs. VAT, shipping cost, payment fee, fixed cost per order and fallback margins. Try a sample order to check the result.
- Switch it on. From then on every purchase carries
mb_profit. - Use it in your tags. Tick Bid on profit (POAS) in the GTM template builder, and the Google Ads, Meta, TikTok and Snapchat purchase tags use
{{ed - mb_profit}}as their value. In an existing container, create an Event Data variable formb_profitand use it as the conversion value of those tags.
Before you switch your bidding
Profit is lower than revenue, so the values your campaigns learn from drop. A target ROAS set for revenue is too high for profit: lower it in line with your margin, or start with a separate conversion action and move your bidding over once it has collected data. Give Smart Bidding a few weeks to adjust.
Checking that it works
- Coverage. The share of your purchase revenue that matched a real cost price, with the item IDs that never matched and how often they were bought.
- Recent purchases. The last orders with their revenue, profit and match rate, to hold against your own order data.
- The tracking audit. The tracking audit warns when coverage drops, when your feed stops updating, and when your Google Ads conversion tags still send revenue while profit tracking is on.
Profit in GA4
mb_profit also reaches GA4 with the purchase. Register it as a custom metric and GA4 reports profit next to revenue. If you'd rather keep your margins out of GA4, exclude the parameter in your GA4 tag in the server container.
Frequently asked questions
Can Google or Meta see my cost prices?
No. Only the profit of each order leaves your tagging server, as the conversion value.
Which plans include profit tracking?
Every plan, including Starter.
What about orders that are returned later?
Set an expected return rate and every order counts with that share already taken off. Adjusting individual orders after a return is not part of profit tracking yet.
My shop runs in more than one currency. Does that work?
Cost prices are kept in one currency. Purchases in another currency are not converted: they count as unmatched in the coverage, so you can see how much revenue that concerns.