Shopify, Server-Side GTM, Stape & Matrixify
Guide to Shopify POAS Tracking for Google Ads: Server-Side GTM, Stape, and Matrixify
As e-commerce advertising becomes more competitive, optimizing campaigns for ROAS (Return on Ad Spend) is no longer enough. High revenue doesn’t always equal high profit, especially if your best-selling items have razor-thin margins. The solution is POAS (Profit on Ad Spend) — feeding real-time profit margins directly into the Google Ads bidding algorithm.
Setting up a reliable, automated POAS pipeline for a large Shopify catalog can be incredibly complex. In this guide, we’ll walk through an enterprise-tier architecture using Shopify, Matrixify, Google Apps Script, Stape.io, and Server-Side GTM (sGTM) to seamlessly pass profit data to Google Ads via both web client tags and server-side webhooks.
The Tech Stack Overview
Here is how the data flows in this architecture:
- Matrixify Shopify app: Exports a daily CSV of your Shopify catalog (costs and prices).
- Google Apps Script: Ingests the CSV, formats the IDs, calculates true profit margins, and outputs the data to a Google Sheet.
- Google Sheets: Publishes a live CSV feed to the web.
- Stape POAS Power-Up: Reads the live Google Sheet and stores the margins in an edge database.
- Server-Side GTM: Formats incoming purchase payloads (web and webhooks), queries Stape for the margin, calculates the exact dollar profit, and sends it to Google Ads.
Let’s build it step-by-step.
Step 1: Automating Catalog Exports with Matrixify
For stores with thousands of SKUs, querying Shopify’s GraphQL API for costs on every purchase is too slow. Instead, we use the Matrixify app to run a scheduled daily export of our catalog.
The “Static URL” Trick
When you schedule a Matrixify export to a custom server or URL, the app automatically appends dynamic parameters to the end of the file link (e.g., ?job=707836997&kind=exported).
To make this predictable for an automated script:
- In Matrixify, under Options, select Custom File Name (e.g.,
stape_poas_feed.csv). - Uncheck Zip CSV files.
- Take the resulting URL and simply delete everything after
.csv. Matrixify’s servers will automatically route any request to that clean, static URL to the most recently generated file.
Step 2: Processing the Data with Google Apps Script
Google Ads requires product IDs to match the format inside Google Merchant Center (usually shopify_US_{product_id}_{variant_id}). Furthermore, we need to calculate our margins and account for fixed overheads.
It’s also a good practice to set up fallback values.
We can use a Google Apps Script for this. Create a Google Sheet, open Extensions > Apps Script, and paste the app script code.
You can quickly use AI to get the code that processes the data, or reach out and I will share my latest and battle-tested snippet.
Crucial Gotcha: If you are passing percentage margins to Stape, they must be formatted as whole numbers (e.g.,
20for 20%), not decimals (0.2). If you pass0.2, Stape will evaluate it as 0.2%, resulting in $0 profit calculations.
Set up a daily time-driven trigger in Apps Script to run this function after your Matrixify export finishes.
Step 3: Publishing to the Web for Stape
Stape needs access to this data. In your Google Sheet:
- Go to File > Share > Publish to web.
- Select your specific tab and change the format from “Web page” to Comma-separated values (.csv).
- Under Published content & settings, ensure “Automatically republish when changes are made” is checked.
- Copy the generated URL.
Step 4: Configuring the Stape POAS Power-Up
- Log into your Stape.io dashboard and open your Server container.
- Go to Power-ups > POAS Data Feed.
- Paste your published Google Sheets CSV URL.
- Under Column Mapping:
- Item ID:
id - Value:
margin - Value Type: Choose whichever type you opted for
- Item ID:
Step 5: Formatting the Data in Server-Side GTM
When a purchase payload hits Server-Side GTM, it comes in two distinct formats:
- Web Purchases (GA4 Client): Uses
item_id,item_variant,price, etc. - Webhook Purchases (Data Manager API): Often uses raw Shopify keys like
product_id,variant_id, andline_items.
The Sandboxed JS Trap
sGTM runs in a sandboxed JavaScript environment. If your web or webhook payload passes price or quantity as a string (e.g., "49.99"), Stape’s margin calculator will attempt to multiply a string by a number, resulting in NaN and outputting $0.00 profit.
To fix this, create a Custom Variable Template in sGTM to universally standardize IDs for both web and webhooks, filter out shipping insurance, and force prices into numeric formats
Create a new Variable in sGTM using this template, and feed your Event Data - items (or line_items) into it. Name it something like {{ss - formatted items array}}.
Step 6: Setting up the Gross Profit Lookup Variable
With your items perfectly formatted, create a new variable using the Stape Store Margin Lookup template from the gallery.
- Items Array Source: Custom items array
- Custom Items Array:
{{ss - formatted items array}} - Item ID Key Name:
item_id - Item Price Key Name:
price - Item Quantity Key Name:
quantity
Testing Warning: During testing, uncheck “Store each Item Margin in cache”. If you make a mistake and the variable calculates a $0 profit, Stape will cache that $0 result for 180 minutes, making it seem like your fixes aren’t working! Once verified, turn the cache back on.
Step 7: Routing Web and Webhook Conversions
Because our Custom JS Template normalizes both GA4 web events and Shopify webhooks into the exact same structure, we can use the exact same Stape Store Margin Lookup variable for both tag triggers.
Create two distinct tags in sGTM:
- Google Ads Conversion Tracking (Web): Triggers on the GA4 purchase event.
- Google Data Manager API Conversion Events (Webhook): Triggers on your Shopify
purchase_webhook.
Set the Conversion Value on both tags to your {{ss - gross profit lookup}} variable. Make sure both tags pass the same transaction_id. Google Ads will receive both events, natively deduplicate them using the transaction ID, and register the exact dollar-amount profit of the order.
Conclusion
By unifying your data structure before it hits the lookup variable, ensuring your prices are strict numeric data types, and scaling your percentage margins to whole numbers, you can build a bulletproof POAS pipeline. Your Google Ads account will now bid based on actual bottom-line profitability, giving you a massive advantage over competitors still optimizing for gross revenue.
Need help setting this up?
We can help you build and maintain a bulletproof Server-Side GTM pipeline to optimize your campaigns for maximum bottom-line profit.
Book a Discovery Call