Skip to content
DocsAnalytics & reports
ANALYTICS & REPORTS

Revenue tracking

Connect website visits to the sales and the ads that brought them. Install one script, connect Stripe or Shopify, and compare results with Meta.

19 min read8 sectionsUpdated September 14, 2026
Open Revenue setup
01

How it works

A small script on every page measures visits, sources and campaigns. Your payment provider, Stripe or Shopify, reports each sale, and Revenue credits it back to the visit — and the ad — that produced it.

Visits start arriving as soon as the script is installed and consent is granted. Sales start arriving once Stripe or Shopify is connected; your website never reports them itself.

02

Register your website

  1. Open Revenue in your dashboard and enter your website or store address.
  2. Click Continue to setup. This creates the site and its public site key.
  3. Check the currency and timezone. If you will compare with Meta, match your Meta ad account.
The site key is public

It identifies your website and is safe in HTML.

03

Choose how to install

Pick one method. Installing the script twice — say in your code and in Tag Manager — counts every visit twice.

In Setup, Copy installation prompt gives your coding assistant ready-made instructions with your site key and script URL. It contains no secret. The assistant still needs access to your website's code.

Choose how to install
MethodBest forOrders
HTMLAny site where you can edit the shared page template.Stripe connection
ShopifyShopify stores. Nothing to paste: connecting the store installs the script.Same Shopify connection
Google Tag ManagerSites that already manage tags through GTM.Stripe connection
Next.jsNext.js App Router applications.Stripe connection
04

Install the tracker

The tracker is one short line of code, called a snippet, that has to load on every page of your website. You never write it yourself: Revenue → Setup writes it for you. Pick your method from the tabs at the top of Install the script, and use the copy button on the code box. The snippet Setup gives you already contains your own site key. The examples on this page use the placeholder YOUR_PUBLIC_SITE_KEY, so always copy from Setup, not from here.

Decide on cookieless tracking before you copy. Ticking Use cookieless tracking in Setup changes the snippet (see Connect analytics consent below), so tick it first if you want it, then copy.

If someone else looks after your website, such as a developer, an agency or a freelancer, send them the snippet together with a link to the section for your method below. Setup's Copy installation prompt produces the same instructions ready to paste into a coding assistant. It contains no secret.

HTML

Use this method if you or your developer can edit your website's files.

You paste one line of code into the header that all your pages share. The header is the hidden part of a page between <head> and </head>. Do it once and every page is covered.

This step tracks visits only: which pages people open and which ad or site brought them. Sales are not tracked yet. If you sell on your site, there is one more step at the end.

  1. In AdRiseLab, open Revenue → Setup, select the HTML tab and copy the snippet.
  2. Open the file that holds your shared header. It is often called index.html, header.html, header.php, base.html or layout.html.
  3. Paste the snippet on a new line just before </head>. If each page has its own header, do this on every page.
  4. Save and publish your site the way you normally do.
  5. Reload your website. It will look the same; that is expected. To confirm it works, see Verify the installation below.
  6. Selling on your site? Continue with Connect your sales, further down. Without it, Revenue shows visits but no sales.
Your page template · inside <head>
<head>
  <!-- your existing tags stay as they are -->
  <title>My store</title>

  <script defer data-site="YOUR_PUBLIC_SITE_KEY"
    data-consent="required"
    src="https://adriselab.com/s.js?v=5"></script>
</head>
Using a website builder?

Many builders have a setting for adding code to the header of every page, often called custom code, header code or code injection. Pasting the snippet there works the same way. Setup has no dedicated option for these builders, so check your builder's help pages for where that setting lives. Use it once, site-wide, not on a single page.

Shopify

Shopify stores do not paste a snippet. You connect the store once, through a Shopify app you create yourself, and AdRiseLab installs the tracker on your storefront and starts receiving your paid orders. It takes about ten minutes and does not change how your store looks.

Why an app: Shopify's checkout runs no third-party script, so a sale can never be seen from the browser. It has to be reported by Shopify itself, and Shopify only reports orders to an app the store has installed. The app is yours: it lives in your own Shopify organization, it has two permissions, and you can uninstall it at any time.

What you need: the store owner account, or a staff account that can create and install apps. The app and the store must belong to the same Shopify organization, which is the case when you create the app from the account that owns the store. Your storefront must be a Shopify Online Store theme; see the note below for headless storefronts.

  1. Open the Shopify Dev Dashboard at dev.shopify.com/dashboard and sign in with the account that owns your store.
  2. Click Create app and give it a name you will recognise later, for example AdRiseLab Revenue. The name is only shown to you.
  3. Open the app's configuration and find Access scopes. Add exactly two: read_orders and write_script_tags. Do not add anything else; AdRiseLab reads no customers and no products.
  4. Release the app version. If Shopify shows a dialog asking for a version name or message, you can leave those fields empty.
  5. Back on the app's Home page, click Install app, choose your store, and approve the installation in Shopify admin. The approval screen lists the same two permissions.
  6. Open the app's Settings and find Credentials. Copy the Client ID and the Client secret. Treat the secret like a password.
  7. In AdRiseLab, open Revenue, open the website picker and choose Add Shopify store (on your first visit, click Add your Shopify store instead under the website form). Enter your store's myshopify.com address (for example your-store.myshopify.com, not your custom domain), paste the Client ID and the Client secret, and click Connect store.
  8. Your store is now its own website in the picker: its storefront address is the website's domain, and its currency and timezone come from Shopify. Revenue → Settings → Shopify shows Connected to your-store.myshopify.com. If one of your websites was already on that domain, the store is connected to it instead.
  9. Open your store in a new browser tab, accept analytics cookies if your store shows a banner, and browse a couple of pages. Revenue → Setup turns green when the first event arrives.
Shopify
Connecting does this on your storeWhy
Adds the tracking script as a script tagSo every storefront page is measured without editing your theme. It survives theme changes.
Registers a webhook for paid ordersSo each sale reaches Revenue from Shopify, signed.
Registers a webhook for refundsSo refunds are subtracted from the sale they belong to.
Registers a webhook for app uninstallSo Revenue shows the store as disconnected if you remove the app.
Adds your storefront domain to this websiteSo events from your store are accepted. This happens in AdRiseLab, not in Shopify.
Consent and headless stores

The script follows your store's own cookie banner: it measures a visitor only when Shopify reports analytics consent for them, so there is nothing to wire up. Headless storefronts (Hydrogen or a custom front end) do not run script tags: install the script there with the HTML or Next.js method for visits, and still connect the store for orders.

Google Tag Manager

Use this method if your website already has Google Tag Manager (GTM) installed, which is common when a marketing team manages tracking tags. You can then add the tracker without touching your website's code. What you need: Publish access to your site's GTM container at tagmanager.google.com.

If GTM is not on your site yet, installing it only for AdRiseLab adds a step. Use the HTML method instead.

  1. In AdRiseLab, open Revenue → Setup, select the Tag Manager tab and copy the snippet.
  2. Open tagmanager.google.com and select the container for your website.
  3. Go to Tags and click New. Name the tag something recognisable, for example AdRiseLab Revenue.
  4. Click Tag Configuration and choose Custom HTML. Paste the snippet into the HTML box.
  5. Click Triggering and choose All Pages, so the tracker loads on every page.
  6. Click Save.
  7. Optional: click Preview, enter your website address and confirm the new tag is listed under Tags Fired.
  8. Click Submit, then Publish. The tag reaches your live site only after you publish.
Custom HTML tag
<script defer data-site="YOUR_PUBLIC_SITE_KEY"
  data-consent="required"
  src="https://adriselab.com/s.js?v=5"></script>
Install in one place only

If the snippet is also in your website's code, or in a second GTM tag, remove the extra one. Two installs count every visit twice. If your cookie banner is managed through GTM, you still need the consent calls described under Connect analytics consent: the snippet waits for them before it measures anything.

Next.js

This method is for websites built with Next.js using the App Router, which means the project has an app folder with a layout.tsx (or layout.js) file in it. This is a developer task. If you do not work on the code yourself, forward this section and the snippet to whoever does.

The snippet goes into the root layout, the file that wraps every page. It uses Next.js's own Script component, which loads the tracker after the page becomes interactive, so it does not slow the first paint.

  1. In AdRiseLab, open Revenue → Setup, select the Next.js tab and copy the snippet.
  2. Open app/layout.tsx (or app/layout.js), the root layout at the top of the app folder, not one inside a subfolder.
  3. Add import Script from "next/script"; with the other imports at the top of the file, if it is not already there.
  4. Paste the <Script … /> element inside <body>, for example right after {children}.
  5. Run the site locally or deploy it as usual. The tracker loads on every route, including pages reached through client-side navigation.
app/layout.tsx
import Script from "next/script";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        <Script
          src="https://adriselab.com/s.js?v=5"
          data-site="YOUR_PUBLIC_SITE_KEY"
          data-consent="required"
          strategy="afterInteractive"
        />
      </body>
    </html>
  );
}
Route changes are measured for you

Moving between pages without a full reload is counted without extra code. Do not also load the script through Tag Manager, and if your site sets a Content Security Policy, allow the AdRiseLab script origin in script-src and connect-src.

06

Connect your sales

The tracker measures visits on its own, but it cannot see a sale, and it has no way to report one: nothing a page sends is counted as money. A sale appears in Revenue only when your payment provider reports it. Until Stripe or Shopify is connected, a store shows visits and zero revenue.

A site without sales can skip this step. If you take payments through anything other than Stripe Checkout or Shopify, Revenue measures your visits but cannot show your revenue.

Stripe

Use this if your website sends buyers to Stripe Checkout and your own server creates the Checkout Session. Stripe's checkout page is on Stripe's domain, so the tracker cannot see the payment. Two steps close the gap, and you need both: Stripe tells Revenue about each payment, and your server tells Stripe which visitor is paying.

The second step is a developer task and nothing can do it for you. Without it every payment is still counted, but it is credited to no visit and no ad.

About the key you hand over: it has one permission, so it can manage webhooks and nothing else. It cannot read payments or customers, and it cannot charge, refund or move money. AdRiseLab uses it for a single request, asking Stripe to create the webhook, and then discards it. What AdRiseLab keeps is the signing secret Stripe returns for that webhook, which can only confirm that an incoming payment event really came from Stripe. You can delete the key in Stripe as soon as the card shows Connected, and the webhook stays visible and removable in your Stripe account under Developers → Webhooks.

  1. In AdRiseLab, open Revenue → Settings → Stripe and click the restricted API key link. It opens Stripe with the one permission, Webhook Endpoints: Write, already selected. Create the key without changing any permissions and copy it.
  2. Back in the Stripe card, paste the key and click Connect Stripe. The key is used once to register a webhook on your Stripe account and is not stored.
  3. In your server code, find where the Checkout Session is created. Read the adriselab_vid cookie from the buyer's request and add it to the session's metadata under the same name, as in the code below.
  4. For subscriptions, add the same value to subscription_data.metadata as well, so renewals are credited too.
  5. Deploy, make a purchase through your own checkout and check that it appears once in Revenue → Transactions with the source of the visit.
Where your server creates the Checkout Session
const visitor = (await cookies()).get("adriselab_vid")?.value ?? "";

const session = await stripe.checkout.sessions.create({
  mode: "payment",
  line_items: [/* your items */],
  metadata: { adriselab_vid: visitor },
  // Subscriptions only, so renewals are credited too:
  // subscription_data: { metadata: { adriselab_vid: visitor } },
});
When a payment shows no source

The payment arrived but the visitor ID did not. Check that the metadata key is exactly adriselab_vid, and that the cookie reaches your server: if your checkout request goes to a different subdomain than your pages, add data-domain to the snippet so the cookie is shared. Buyers who declined analytics consent, sites using cookieless tracking, and buyers who pay on a different device cannot be matched. Payments made before you connected are not imported, and Payment Links, pricing tables and Buy buttons are not supported.

Shopify

There is no separate step for orders. The connection described under Install the tracker → Shopify already registered the webhooks, so paid orders and refunds start arriving as soon as the card shows Connected.

How a sale is credited to an ad: a buyer clicks an ad and lands on your store, where the script records the visit and the ad it came from. When they add to cart, the script writes its visitor ID into the cart as a hidden attribute. Shopify copies cart attributes onto the order, and when the order is paid Shopify sends it to Revenue with that ID attached. Revenue then looks up that visitor's visits in the 30 days before the payment and credits the sale to the visit, the campaign and the ad behind it.

Some orders never have a cart: Buy it now and the express buttons go straight from the product page to checkout. Those orders are credited from the campaign tags on the page the visit landed on, which Shopify records on the order. That credits the campaign and the ad, though not the individual visit.

The script also sends two events you can use in goals and funnels without adding code: add_to_cart and initiate_checkout. Express buttons such as Shop Pay render inside Shopify's own frames, so they are not seen as initiate_checkout; the order is still recorded.

About the secret you hand over: Shopify signs every order it sends with your app's Client secret, so AdRiseLab has to keep it to check that an order is genuine. Unlike a Stripe key, it cannot be discarded after connecting. It is stored encrypted, never shown again and never sent to a browser. The app has two permissions, reading orders and managing script tags: it cannot read customers or products, and it cannot change, cancel or refund an order. From each order Revenue keeps the amount, currency, time, order number, sales channel, discount codes and item names. It does not keep the buyer's name, email, phone or address.

  1. Place a test order on your store from a normal browser window, after accepting analytics cookies. A real payment that you refund afterwards works; Shopify's test orders are ignored on purpose, because they are not money.
  2. Open Revenue → Transactions. The order appears within a minute, under the same order number you see in Shopify, for example #1001.
  3. Check that the order shows the source of the visit. If it shows Unattributed, see the table below.
  4. Refund the test order in Shopify and confirm the refund is subtracted from that sale.
Shopify
If an order shows no sourceWhat to do
The buyer declined analytics cookies, or their browser sends Do Not Track or Global Privacy Control.Nothing. No visitor ID is created for them, by design. The order still counts as revenue.
The order came from POS, a draft order or a subscription app.Nothing. It never passed through your storefront, so there is no visit to credit.
The buyer clicked the ad on one device and paid on another.Nothing. The two browsers cannot be linked.
The buyer's last visit with a source was more than 30 days before paying.Nothing. This is outside the attribution window.
The ad was created by hand in Meta Ads Manager.Add the URL parameters shown under Meta in the Revenue guide, so the ad's link carries the ad ID.
Limits and disconnecting

Orders placed before you connected are not imported, and a refund of one of those is ignored because its sale is not in Revenue. Unpaid, cancelled and test orders are not recorded. A store can be connected to one website only. To disconnect, click Disconnect on the Shopify card: AdRiseLab removes its script tag and webhooks from your store, and you can then uninstall the app in Shopify. Uninstalling the app first also works; the card then shows Not connected. Orders already recorded stay in Revenue. To reconnect, paste the Client ID and secret again; nothing is duplicated.

07

Verify the installation

Setup shows a live status for the selected website. It turns green once the first event arrives.

  1. Open your website in a normal browser window and grant analytics consent.
  2. Navigate to a second page.
  3. Return to Revenue → Setup and confirm the status shows a recent event.
  4. Check Visitors. If an automated or headless test is missing, turn on Show crawler traffic.
  5. For a store, connect Stripe or Shopify, place a test order and confirm it appears once in Transactions.
  6. Check that the order shows the source of the visit. If it does not, the visitor ID did not reach your payment provider.
08

Diagnose missing or different numbers

If visits are missing, check the selected site, actual installed site key, consent, script loading, date range, and crawler filter first.

If visits arrive but sales do not, check Revenue → Settings: the script alone never reports a sale, so Stripe or Shopify has to show as connected there.

If sales arrive but are credited to no source, the payment reached Revenue without a visitor ID. On Stripe, check the adriselab_vid metadata on the Checkout Session; on Shopify, check that the store still shows as connected in Settings and that the buyer accepted analytics cookies.

If Meta and Revenue disagree, compare their date ranges and measurement methods. Meta’s attributed conversions and the website ledger are distinct sources; neither should be silently substituted for the other.