Skip to content
Integration: Shopify

Conversions API for Shopify, from the shop’s orders

Someone on r/FacebookAds described the native Shopify integration with Meta as counting purchases “like 3x”. A duplicate comes from several paths for the same purchase. Basketly reads the purchase from the order through the shop’s API and sends it to Meta server-side, and the purchase balance shows how many Meta actually accepted.

The demo has sample data; the login comes to your e-mail.

Where a duplicate purchase comes from

The Pixel in the browser and a send from the server are two paths for the same purchase. Meta counts it once only when both events carry the same id. When several tools in the shop send a purchase, a duplicate is easy to get and hard to find. So Basketly always sends the purchase with one fixed id, and the Purchase balance shows shop orders next to purchases Meta accepted.

What Basketly does on Shopify

You give the shop address (*.myshopify.com), the access token of a custom app made in the shop and that app’s API secret key. The app does the rest.

  • Saving checks access by reading the shop, one order and one product. A refusal is named: wrong token, frozen shop, or a missing read_orders, read_products or read_customers permission.
  • With the app’s API secret key the app subscribes to orders and products (order created and updated, product created, updated and deleted) and accepts a notification only with a valid signature and the shop’s own domain. Without the key orders come with the 15-minute read.
  • A paid, not cancelled order becomes a purchase: value, currency, products from the lines, e-mail, phone (hashed before sending), the buyer’s IP from the order. A cancelled, fully refunded or voided order is not sent.
  • Every purchase is saved first and then sent with retries. When Meta has an outage, the purchase waits instead of getting lost.
  • Shopify products (title, description, shop link, image, price and compare-at price, SKU, barcode, vendor as brand, stock) land on the Products screen with a diagnosis for Google Merchant Center and the Meta catalogue, and from there in a fixed feed.
  • Shopify’s limits are respected: after a throttling refusal the job waits and returns.

Connect Shopify in 4 steps

It takes a few minutes. You need no developer, but you will add a custom app in the shop.

  1. Create a custom app in Shopify

    In the shop create a custom app with read access to orders, products and customers. Note the Admin API access token (shpat_…) and the app’s API secret key.

  2. Add the shop in the app

    In Basketly open Integrations → Data sources → Add source, choose Shopify and enter a name and the shop address. From the source’s menu open the API connection, enter the *.myshopify.com address, the token and the app’s API secret key, tick the bought statuses and confirm the legal basis for passing the data.

  3. Connect Meta and add the guide’s attribute

    Sign in with your Meta account, choose the dataset (Pixel) and keep the purchase flow from the shop to Meta. The connection guide shows the shop script and the cart attribute with the id.

  4. Check the first purchase

    Click “Fetch now”, send a Test event with the code from Events Manager and, after the first orders, open the purchase balance.

Cash on delivery and statuses

An order with the financial status PAID is bought at once. With cash on delivery Shopify usually holds PENDING, so when connecting you can tick PENDING, AUTHORIZED or PARTIALLY_PAID as bought. Cancelled, fully refunded (REFUNDED) and voided (VOIDED) orders never become a purchase. Keep Meta’s limit in mind: a purchase older than 7 days is not accepted.

Tying the purchase to the visit, and history

The connection guide adds a cart attribute with the Basketly script’s id. The purchase then carries what the script saw during the visit, but only after the buyer’s consent, because the script runs only then. The 24-month order history is read once; without the read_all_orders permission Shopify gives only the last 60 days. Up to 25 lines are read from one order, and the order total is always whole.

How to check that it works

  • Test event: one click sends the newest shop purchase with the test code from Events Manager, and you see it under Test Events.
  • Purchase balance: shop orders next to purchases Meta accepted, day by day, with the most common error reasons.
  • Self-check: compares the dataset’s statistics in Meta with what was actually sent, and says what to fix.
  • Orders: each order shows whether its purchase was accepted, failed or is waiting.

What it does not do

  • It does not switch off the native Shopify integration or other apps. If one also sends the purchase server-side, you have two server paths for the same purchase: keep one, or make sure both use the same event id, and check the result in Events Manager.
  • It does not replace the Pixel in the browser: events such as product views or add to cart stay on the shop side. It is a second, independent path for purchases.
  • Without the Basketly script in the shop and the buyer’s consent Meta gets no ad click id, so matching the purchase to an ad can be weaker.
  • It does not make Meta’s numbers equal the shop’s: Meta counts purchases by its attribution windows. Both numbers are shown side by side.
  • It does not send a purchase older than 7 days and does not work without the shop’s confirmed legal basis.
Integration: Shopify

Frequently asked questions

Your question is not here? Write to us

No. Whatever that integration does stays on the shop side, and Basketly adds the purchase from the order as a second path. If both send the same purchase, Meta counts it once only when they carry the same event id. The server sends shopify-order-<order id>, so after connecting check in Events Manager that purchases are not doubled.

With it the app subscribes to Shopify webhooks and checks their signature, so orders arrive at once. Without it the 15-minute read still works.

Yes, when you tick the financial status that counts as bought. The purchase goes after such a change, as long as the order is not older than 7 days.

The first read goes 7 days back, because Meta does not accept older purchases. The order history is read once into Orders and Clients but never sent to Meta.

The free plan covers up to 100 orders a month, with no card and no time limit. The limit counts orders, not sends to platforms. Other plans are on the pricing page.

Get started in under 5 minutes

Connect your shop and Meta and see how many purchases really arrive.

  • Free up to 100 orders a month
  • No developer needed
  • Purchase balance and self-check