Overview: The two Aspire apps
Aspire connects to Shopify through two apps that serve different purposes. Most merchants will install both.
1. Aspire App (core integration)
Connects your store to Aspire and syncs customers, products, collections, and orders.
Powers product catalogs, product-cost calculations, and gifting/fulfillment.
Installed from your Aspire account under Integrations → Shopify.
2. Aspire Affiliate App (sales tracking & creator tools)
Installed from the Shopify App Store: https://apps.shopify.com/aspire-2-0
This app enables Aspire's affiliate features:
SecureCodes - Auto-generated, conflict-free discount codes for creators.
Offer Landing Pages - Shoppable, personalized storefronts for each creator.
Link Tracking - Automatic click & conversion tracking via App Pixels. ⟵ NEW
Before you start: Permissions
Confirm you have the following access in your Shopify admin before connecting:
Store data - Read/write access to Orders, Products, and Customers.
Apps - Ability to install and manage apps and sales channels.
Note: Customer data sync can take up to 24 hours to complete after you first connect. Reporting and tracking become fully reliable once the initial sync finishes.
Step 1 - Connect your store (Aspire App)
From your Aspire account, go to Integrations.
Select Shopify and enter your store URL (e.g. your-store.myshopify.com).
Click Connect my store.
Log in to Shopify when prompted and install the Aspire App.
Wait for the customer/product sync to complete (up to 24 hours).
Once connected, import your products and collections and configure product-cost settings so catalogs and ROI calculations are accurate.
Step 2 - Install the Aspire Affiliate App
Install the Aspire Affiliate App from the Shopify App Store: https://apps.shopify.com/aspire-2-0
Open the listing above and click Install (choose the correct store if you manage several).
Approve the requested permissions.
Open the app dashboard at admin.shopify.com/store/{your-store-id}/apps/aspire-app/app to manage features.
Step 3 - Enable Link Tracking (NEW)
Link Tracking is how Aspire attributes affiliate clicks and conversions on your Shopify store. It runs through Shopify App Pixels installed and managed by the Aspire Affiliate App.
Why it matters
Previously, sales tracking depended on two manual pieces:
• a Custom Pixel in Settings → Customer Events, and
• a tracking script pasted into theme.liquid.
The theme snippet is fragile: a theme update can overwrite theme.liquid and silently strip the tracking script - which has caused conversions to drop to near-zero until someone notices and re-adds it.
The fix: With Link Tracking, Aspire manages tracking through App Pixels instead. The app survives theme updates, so you no longer need to maintain a custom pixel or a theme.liquid snippet for standard (non-headless) Shopify stores.
How to enable it
Open the Aspire Affiliate App dashboard in your Shopify admin.
Look for the Link Tracking section/toggle and enable it.
Don't see Link Tracking after installing? Ask your Aspire contact to enable it for your account (it can be turned on server-side per account).
Place a test order to confirm a conversion is recorded.
Important: Once Link Tracking is confirmed working, you can safely remove the old custom pixel and any Aspire tracking script from your theme files. Keep them in place until you've verified the App Pixel is firing.
Headless storefronts (NEW)
A headless store uses a custom front end (e.g. Next.js / React) for browsing while Shopify still hosts the cart and checkout. Because the affiliate click lands on your custom domain - not on Shopify - the affiliate identifier can't be read inside Shopify's checkout pixel sandbox on its own.
How attribution works on headless
Affiliate links arrive at your storefront with a ?transaction_id=… parameter. A small bridge captures that value and stamps it onto the Shopify cart as a cart attribute (_tune_txn_id). At checkout, the pixel reads that attribute and fires the conversion with the correct transaction ID.
Setup (for your developer)
There are two small changes. First, install the Aspire Affiliate App and enable Link Tracking (above). Then:
Part 1 - Headless front end (Next.js)
Part 1 - Headless front end (Next.js)
Add a helper that captures the transaction ID and writes it to the Shopify cart. Fill in your store domain and your existing public Storefront API token.
// lib/tune-cart-sync.js
// Bridges affiliate attribution from the headless storefront into the
// Shopify checkout. Affiliate links land with ?transaction_id=... in the URL.
// We capture it, persist it, and stamp it onto the Shopify cart as the
// `_tune_txn_id` attribute so the checkout pixel can read it and fire the
// conversion.
const STORE_DOMAIN = 'YOUR_STORE.myshopify.com';
const STOREFRONT_API_TOKEN = 'YOUR_PUBLIC_STOREFRONT_API_TOKEN';
const STOREFRONT_API_VERSION = '2025-01'; // match your existing cart calls
const URL_PARAM = 'transaction_id'; // stays as-is in the affiliate URL
const STORAGE_KEY = 'tune_transaction_id'; // internal localStorage key
const CART_ATTRIBUTE_KEY = '_tune_txn_id'; // MUST match the checkout pixel
const CART_ATTRIBUTES_UPDATE = `
mutation cartAttributesUpdate($cartId: ID!, $attributes: [AttributeInput!]!) {
cartAttributesUpdate(cartId: $cartId, attributes: $attributes) {
cart { id }
userErrors { field message }
}
}
`;
// Capture ?transaction_id=... from the landing URL and persist it.
export function captureTuneTransactionId() {
if (typeof window === 'undefined') return;
const fromUrl = new URLSearchParams(window.location.search).get(URL_PARAM);
if (fromUrl) localStorage.setItem(STORAGE_KEY, fromUrl);
}
// Read the persisted id (falls back to the current URL).
export function getTuneTransactionId() {
if (typeof window === 'undefined') return null;
return (
localStorage.getItem(STORAGE_KEY) ||
new URLSearchParams(window.location.search).get(URL_PARAM)
);
}
// Stamp the transaction id onto the given Shopify cart. Best-effort:
// never throws, so it can't break the add-to-cart flow.
export async function syncTuneTransactionIdToCart(cartId) {
try {
if (!cartId) return;
const transactionId = getTuneTransactionId();
if (!transactionId) return;
const res = await fetch(
`https://${STORE_DOMAIN}/api/${STOREFRONT_API_VERSION}/graphql.json`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Shopify-Storefront-Access-Token': STOREFRONT_API_TOKEN,
},
body: JSON.stringify({
query: CART_ATTRIBUTES_UPDATE,
variables: {
cartId,
attributes: [{ key: CART_ATTRIBUTE_KEY, value: transactionId }],
},
}),
}
);
const data = await res.json();
const errors = data?.data?.cartAttributesUpdate?.userErrors;
if (errors?.length) console.warn('[Tune] Cart attribute errors:', errors);
} catch (err) {
console.error('[Tune] Failed to sync transaction id to cart:', err);
}
}
Wire it in with two calls - capture on every page load, and stamp the cart after it's created:
// 1. Capture on every page load - in pages/_app.js
import { useEffect } from 'react';
import { captureTuneTransactionId } from '../lib/tune-cart-sync';
export default function MyApp({ Component, pageProps }) {
useEffect(() => { captureTuneTransactionId(); }, []);
return <Component {...pageProps} />;
}
// 2. Stamp the cart - right after cartCreate / cartLinesAdd resolves
import { syncTuneTransactionIdToCart } from '../lib/tune-cart-sync';
await syncTuneTransactionIdToCart(cart.id);
Part 2 - Checkout pixel (one line)
Part 2 - Checkout pixel (one line)
In your existing Customer Events pixel, read the cart attribute and pass it into the conversion call:
// read the attribute the storefront stamped onto the cart
const attrs = event.data.checkout.attributes
?? event.data.checkout.customAttributes ?? [];
const transactionId = attrs.find(a => a.key === '_tune_txn_id')?.value;
if (!transactionId) return; // organic order, not affiliate-driven - skip
tdl.convert({
amount: cartSubtotalUSD, // your existing USD value
adv_unique1: event.data.checkout.order.id, // existing
transaction_id: transactionId, // <- the line that fixes attribution
});
Two things to double-check:
The cart attribute key _tune_txn_id must be identical in both places. If the storefront writes one key and the pixel looks for another, conversions silently skip.
The token in Part 1 is the public Storefront API token (the one your cart code already uses) - not the Admin API token.
