> ## Documentation Index
> Fetch the complete documentation index at: https://docs.runrally.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Ad conversion tracking

> Install the Meta Pixel or TikTok Pixel on your site so the ads Rally runs can optimise on real signups and purchases, and verify from Rally that events arrive.

Rally can run and optimise paid ads on a connected Meta or TikTok ad account. Conversion ads need the platform's own pixel on your site: it is what tells Meta or TikTok which clicks turned into signups and purchases, and what their optimisation learns from. This is separate from the [Rally snippet](/developers/tracking): the snippet credits creators; the pixel trains the ad platform. Both run side by side.

Set it up per ad account under **Settings → Integrations → Ad accounts → Set up conversion tracking**. The dialog gives you the fields below and a coding-agent prompt tailored to your stack.

## 1. Create the pixel and copy its id

<Tabs>
  <Tab title="Meta">
    In **Events Manager → Connect data → Web**, name the dataset, create it, choose **Set up Meta Pixel → Add code yourself**. The number in `fbq('init', '…')` of the base code Meta shows is the **Dataset ID** (Meta's name for the Pixel ID since pixels became datasets). You can also find it under Datasets → the dataset → Settings. Paste it into Rally and pick the **Purchase event** Rally's purchase-optimised ads should target (`Purchase` by default).
  </Tab>

  <Tab title="TikTok">
    In **Ads Manager → Assets → Events Manager → Connect data source → Web → Manual setup**, enter your site (or skip), choose **TikTok Pixel + Events API**, name it, create. The **Pixel ID** is the 20-character code in `ttq.load('…')` on the Install base code step, and at the top of the pixel's page afterwards. Paste it into Rally. Skip TikTok's Event Builder: the events are fired from code.
  </Tab>
</Tabs>

## 2. Install the base code

The base code goes on every page, in `<head>`. In Next.js or React, load it once in the root layout and fire the page event on every client-side route change.

<Tabs>
  <Tab title="Meta">
    ```html theme={null}
    <!-- Meta Pixel Code -->
    <script>
    !function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,document,'script','https://connect.facebook.net/en_US/fbevents.js');
    fbq('init', 'YOUR_DATASET_ID');
    fbq('track', 'PageView');
    </script>
    <noscript><img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=YOUR_DATASET_ID&ev=PageView&noscript=1"/></noscript>
    <!-- End Meta Pixel Code -->
    ```

    An `<img>` is not valid inside `<head>`; if your build tooling rejects the `<noscript>` block there (Vite does), put it at the top of `<body>`.
  </Tab>

  <Tab title="TikTok">
    Use the base code TikTok's Events Manager hands out on the **Install base code** step, with your pixel id in `ttq.load('…')` and `ttq.page()` after it. Rally's prompt carries the full snippet.
  </Tab>
</Tabs>

## 3. Fire the two standard events

Fire each exactly once, when the thing happens. Never on page load of a generic page, on refresh, or for returning logged-in users: the ads optimise on these, so noise costs money.

<Tabs>
  <Tab title="Meta">
    Event names are case-sensitive standard events.

    ```js theme={null}
    // When a signup completes (account created, email verified, whatever "lead" means for you):
    fbq('track', 'Lead', {}, { eventID: 'lead_' + user.id });

    // When a purchase or subscription succeeds. Must be the event picked as the Purchase event in Rally.
    fbq('track', 'Purchase', { value: 49.0, currency: 'USD' }, { eventID: paymentReference });
    ```

    Fire the purchase event from the success page only if that page knows the amount and a payment reference to use as `eventID`; otherwise send it server-side only (next step), which is enough for Meta to optimise on.
  </Tab>

  <Tab title="TikTok">
    `ttq.track` takes the event name, a properties object and an options object; `event_id` goes in the third argument or TikTok will not deduplicate it against the server event.

    ```js theme={null}
    // Before either event, when the user is known. The SDK hashes these; they match the conversion to the TikTok user.
    ttq.identify({ email: user.email, external_id: user.id });

    // When a signup completes:
    ttq.track('CompleteRegistration', {}, { event_id: 'reg_' + user.id });

    // When a purchase or subscription succeeds (Events Manager labels this one "Purchase"):
    ttq.track('CompletePayment', { value: 49.0, currency: 'USD', content_type: 'product' }, { event_id: orderId });
    ```
  </Tab>
</Tabs>

## 4. Mirror events from your server (recommended)

Browser blockers drop a share of pixel events. Sending the same events from your backend with the same `event_id` recovers them; the platform deduplicates by id. Generate the token in the platform, store it as a server secret, and paste it into Rally's dialog (**Add to prompt**) so the coding-agent prompt carries it.

<Tabs>
  <Tab title="Meta Conversions API">
    Token: **Events Manager → Datasets → the dataset → Settings → Conversions API → Generate access token**. Store it as `META_CAPI_TOKEN`.

    `POST https://graph.facebook.com/v19.0/<DATASET_ID>/events` with the token in the `Authorization` header (never in a URL), sending the same `event_name` (`Lead`, `Purchase`), `event_time`, the same `event_id` as the browser event, `action_source: "website"`, and hashed `user_data` (`em`, `ph`, `client_ip_address`, `client_user_agent`, the `fbp` and `fbc` cookies).
  </Tab>

  <Tab title="TikTok Events API">
    Token: **Ads Manager → Assets → Events Manager → the pixel → Settings → Generate access token** (step 7 of TikTok's Pixel + Events API guide; shown once). Store it as `TIKTOK_EVENTS_TOKEN`.

    `POST https://business-api.tiktok.com/open_api/v1.3/event/track/` with header `Access-Token`. `event_source_id` is the pixel id; use the same event name and `event_id` as the browser side; `email`, `phone` and `external_id` are SHA-256 hex, `ip` and `user_agent` plain; `page.url` is required; `CompleteRegistration` carries no value or currency. Hashed email plus `ttclid` is what gives the ad match rate.
  </Tab>
</Tabs>

## 5. Verify from Rally

Open your site once (a page view), complete a test signup and, if you can, a test purchase. Then in Rally, **Settings → Integrations → Ad accounts → the account → Conversion tracking → Verify**. Rally reads back from the platform what arrived:

| Check | Meaning |
| - | - |
| Pixel on the ad account | The id you pasted belongs to this ad account. |
| Website tag firing | Page views are arriving from the browser. |
| Signup events | `Lead` (Meta) or `CompleteRegistration` (TikTok) arrived. |
| Purchase events | Your purchase event arrived. Until it does, purchase-optimised ads have nothing to learn from. |
| Server events | Events are arriving through the Conversions API or Events API. |

The Meta Pixel Helper extension, and each platform's Events Manager → Test events, show the same live.

<Note>
  Rally's own click, signup and sale numbers do not depend on the pixel; they come from the tracking snippet and your lead and sale calls. The pixel only affects how well the platform can optimise the ads.
</Note>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.