> For the complete documentation index, see [llms.txt](https://docs.adpage.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.adpage.io/optimize-your-setup/profit-on-ad-spend/choose-your-cost-source.md).

# Choose your cost source

Profit on Ad Spend needs a purchase price per product. It can come from Shopify, from your Magento catalogue, from an XML feed, or from a combination.

Everything else on this page depends on one thing: we need to know what a product cost you. There are three ways to tell us, they can be used together, and none is better in general — it depends on your platform.

{% hint style="info" %}
This page quotes the dashboard in English. Using it in Dutch? See the [Dutch glossary](/optimize-your-setup/profit-on-ad-spend/dutch-glossary.md) for every label.
{% endhint %}

|                       | Shopify cost per item                       | Magento catalogue                    | XML purchase-price feed               |
| --------------------- | ------------------------------------------- | ------------------------------------ | ------------------------------------- |
| Works on              | Shopify only                                | Magento only                         | Any platform                          |
| Comes from            | the **Cost per item** field on each variant | the `cost` attribute on each product | a feed you generate yourself          |
| You change a price in | Shopify                                     | Magento                              | the tool that generates the feed      |
| How fresh             | re-read nightly                             | re-read on every sync                | re-read once per hour                 |
| Setup                 | connect Shopify, fill in cost per item      | connect Magento, fill in `cost`      | generate a feed, fill in three fields |

{% hint style="info" %}
**AdPage does not store a price you type in.** The purchase price always comes from one of the sources above, so to change a cost price you change it at the source. AdPage picks it up on the next sync — or straight away with **Sync now** on the Profit on Adspend screen.
{% endhint %}

Use several and they add up: a product id known in both a shop platform and the feed takes the shop figure, because that is your own bookkeeping rather than an export of it. Ids that only exist in the feed — variants, EANs, products from another shop — are added on top.

{% hint style="info" %}
No cost source at all? Then Profit on Ad Spend has nothing to work with. A fallback margin can stand in for products whose cost we do not know, but a margin is an estimate, not a measurement. See The variables for how to tell the two apart.
{% endhint %}

## The Profit on Adspend screen

Everything you set up in AdPage for Profit on Ad Spend is on one screen: open your container at [data.adpage.io](https://data.adpage.io), go to **Settings → Profit on Adspend** and click **Open Profit on Adspend**. Or go straight to `https://data.adpage.io/containers/<your container id>/profit-on-adspend`.

On that screen you find, top to bottom:

| Block                                                 | What it does                                                                                                                                                               |
| ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **On / Off** switch                                   | Turns Profit on Ad Spend on or off for this container                                                                                                                      |
| **Mode**                                              | **Standard** reads the XML feed per order when the purchase webhook comes in. **Advanced** syncs your costs, and adds cost items, the GTM variable and Data Studio reports |
| **Product feed** (Advanced) / **XML feed** (Standard) | Feed URL and the two columns we read, plus the sync status: how many products have a cost price                                                                            |
| **Cost items**                                        | Shipping, payment and other costs per order — see Cost Items. Advanced only                                                                                                |
| **Set up in Google Tag Manager**                      | The lookup token and instructions for the GTM variable. Advanced only                                                                                                      |
| **Check on a real order**                             | Shows the profit calculated on a real order, so you can check the result. Advanced only                                                                                    |

## Shopify cost per item

Shopify already stores a purchase price per variant, so on Shopify there is nothing to generate and nothing to export.

{% stepper %}
{% step %}

#### Fill in Cost per item

In Shopify, open a product and scroll to the variant's **Inventory** section. **Cost per item** is the field we read. A variant without it has no known cost.

Shopify stores this **excluding VAT**, which is the basis Profit on Ad Spend calculates in. Include your import duties and other landed costs here — that is what makes it a purchase price rather than a supplier price.
{% endstep %}

{% step %}

#### Connect Shopify and approve the permissions

Connect the Shopify integration for this container. See [Shopify](https://docs.adpage.io/data-and-insights/marketing-integrations/shopify) for the connection itself.

Reading cost prices needs the **read\_inventory** permission. Stores that installed AdPage before that permission existed do not have it, and Shopify then answers with an access error rather than with zero costs.

If you connected a while ago, open the AdPage app once from your Shopify admin and approve the permissions it asks for. That one-off re-consent is all it takes.
{% endstep %}

{% step %}

#### Turn on Profit on Ad Spend

Open the [Profit on Adspend screen](#the-profit-on-adspend-screen), switch it **On** and choose **Advanced**. (The same switch is also on the **Send Profit on Adspend profit** card under **Webhook Matching**.)

You should end up with a line like "20565 products with a cost price". That number is the check: far below your catalogue size means most variants have an empty **Cost per item**.
{% endstep %}
{% endstepper %}

**Which keys a Shopify cost lands under.** Every priced variant is stored under both its SKU and its variant id, so an order line matches on whichever of the two it carries. A product id is added as well, but only when every variant of that product has the same cost — otherwise an order line carrying nothing but a product id would silently get one variant's price for all of them. Variant-priced products are the normal case, and there the product id is deliberately left out.

## Magento catalogue

{% stepper %}
{% step %}

#### Fill in the cost attribute

In Magento, every product has a `cost` field (Product → Advanced Pricing → Cost). Profit on Ad Spend reads that field, so a product without it has no known cost.

Costs here are **excluding VAT**, which is what Magento stores by default.
{% endstep %}

{% step %}

#### Connect Magento to AdPage

In your AdPage dashboard, connect the Magento integration for this container. No feed, no export, no extra tooling.
{% endstep %}

{% step %}

#### Turn on Profit on Ad Spend

Open the [Profit on Adspend screen](#the-profit-on-adspend-screen), switch it **On** and choose **Advanced**. Switching it on pulls the catalogue straight away. (The same switch is also on the **Send Profit on Adspend profit** card under **Webhook Matching**.)

You should end up with a line like "Active · 4274 products with a cost price from the Magento catalogue". That number is the check: if it is far below your catalogue size, most products have an empty `cost` field.
{% endstep %}
{% endstepper %}

## XML purchase-price feed

Works on any platform, and is the only option outside Shopify and Magento.

{% stepper %}
{% step %}

#### Generate an XML feed

An XML feed is a file containing information about a webshop's products, in a format different systems can read automatically. Change a price in your webshop and every connected system sees the change, without anyone updating it by hand.

You can generate one with Channable, a WooCommerce plugin, or a similar tool. It needs to contain at least a product id and a purchase price per product. The feed must be reachable without logging in.
{% endstep %}

{% step %}

#### Fill in the feed on the Profit on Adspend screen

Open the [Profit on Adspend screen](#the-profit-on-adspend-screen) and fill in the **Product feed** block (called **XML feed** in Standard mode):

* **Feed URL** — where the feed can be downloaded.
* **Product ID column** — the field holding the product id, for example `g:id`. This id must match the `item_id` in your incoming GA4 event requests. If you have not changed the `item_id` parameter in your GA4 event tags, that is the `item_id` from your dataLayer.
* **Cost price column** — the field in the feed holding the purchase price, for example `g:cost_of_goods_sold` or `g:custom_label_2`.

Click **Save feed**. In Advanced this syncs right away, so you immediately see how many products got a cost price.

**Finding the item\_id in the dataLayer.** Open your webshop and go to a product page. Inspect the page, go to the **Console** tab and type `window.dataLayer`. Find the `view_item` event and read the `item_id` of the product you are looking at.

<figure><img src="https://1274044937-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FA65KwL1NwewlJbtCXsXd%2Fuploads%2FLGgKUgd6Xu3YIIwr9g3d%2Fimage.png?alt=media&#x26;token=e134c0de-b898-493d-ada3-ae77fdaa7c7f" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}

#### Tell us whether your feed prices include VAT

Purchase prices in a feed are sometimes listed including VAT and sometimes excluding it, and only you know which. Profit on Ad Spend calculates a pure ex-VAT margin, so if your feed lists prices including VAT, go to **Webhook Matching**, tick **The purchase prices in my feed include VAT** on the **Send Profit on Adspend profit** card, and fill in the **VAT percentage**.

Get this wrong and nothing breaks — your margin is simply off by the VAT rate. If the numbers look consistently too high or too low, check this setting first and re-sync.
{% endstep %}
{% endstepper %}

## Which ids have to match

Whichever source you use, a cost is only found when the product id we receive matches the id we have a cost for. We try every identifier an order line carries — `item_id`, variant id, `sku`, `item_sku` — and use the first one with a known cost, so a mismatch on one key can still resolve on another.

Whether that actually worked on a real order is visible in preview. See Set up the server container.

## What else comes off the margin

A cost source covers the products. Shipping, payment and packaging are set separately, on the same Profit on Adspend screen — see Cost Items.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.adpage.io/optimize-your-setup/profit-on-ad-spend/choose-your-cost-source.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
