> For the complete documentation index, see [llms.txt](https://docs.adpage.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.adpage.io/integrations-marketingtools/meta-ads.md).

# Meta Ads

How to set up server-side tagging for Meta Ads

This guide shows you how to configure the Meta (Facebook) Conversions API in your Google Tag Manager server container, step by step.

{% hint style="warning" %}
**This article covers a server-side only setup.** All Meta events are sent from your server container to the Conversions API, there is no Meta Pixel firing in the browser. You can also run Meta Ads **client-side and server-side at the same time**, with event deduplication based on the `event_id` parameter. That setup requires a few different settings, which we describe in [Setting up Meta Ads client-side tagging with event deduplication](/integrations-marketingtools/meta-ads/setting-up-client-side-meta-ads-tracking-with-deduplication.md). One setting in particular (**Use HttpOnly cookies**) depends on which of the two setups you choose.&#x20;
{% endhint %}

### Before you start

Make sure you have:

* [ ] A working GTM server container that receives events (usually via your Google Tag / GA4 client).
* [ ] Your **Pixel ID** and **API Access Token** from Meta Events Manager. See [Where to find the Meta Pixel ID and the Meta API Token](/integrations-marketingtools/meta-ads/where-to-find-the-meta-pixel-id-and-the-meta-api-token.md).

### Step 1: Add the tag template

1. Open your GTM server container and go to **Templates**.
2. Under **Tag Templates**, click **Search Gallery**.
3. Search for the **Facebook Conversion API** tag template and add it to your workspace.

<figure><img src="https://1274044937-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FA65KwL1NwewlJbtCXsXd%2Fuploads%2FKxgO3z08RHOjmdbqUVsT%2Fimage.png?alt=media&amp;token=285e035b-a564-4b23-bed9-35abe786b085" alt=""><figcaption></figcaption></figure>

### Step 2: Create the tag

1. Go to **Tags** and create a new tag.
2. Choose the **Facebook Conversion API** template as your tag configuration.
3. Choose **Inherit from client** as the event name setup method. Only change this if you want to send different event names to the Facebook Conversion API than the event names received from the incoming GA4 events.
4. Choose **Website** as the action source.
5. Under **Facebook Pixel ID**, enter your Pixel ID from Meta Events Manager. Under **API Access Token**, enter your API token from Meta Events Manager.

<figure><img src="https://1274044937-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FA65KwL1NwewlJbtCXsXd%2Fuploads%2FgSs6rfNbNJkREadhGeKW%2Fimage.png?alt=media&amp;token=b209b048-e761-471c-bf91-9c5ec38508f5" alt=""><figcaption></figcaption></figure>

### Step 3: Set the cookie and event options

<figure><img src="https://1274044937-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FA65KwL1NwewlJbtCXsXd%2Fuploads%2F0sTLveszr6vX28nrXYpC%2Fimage.png?alt=media&amp;token=b74dcef1-e9f6-4746-ba24-f5e62c44ccb5" alt=""><figcaption></figcaption></figure>

Set the four checkboxes as follows for a server-side only setup:

| Option                                 | Server-side only | Client-side + server-side (deduplication) |
| -------------------------------------- | ---------------- | ----------------------------------------- |
| Generate `_fbp` cookie if it not exist | Disabled         | Disabled                                  |
| Use HttpOnly cookies                   | **Enabled**      | **Disabled**                              |
| Enable Event Enhancement               | Enabled          | Enabled                                   |
| Use Optimistic Scenario                | Disabled         | Disabled                                  |

**Generate \_fbp cookie if it not exist**

The `_fbp` cookie holds the browser ID: Meta's identifier for the browser. With this option enabled, your server container generates the `_fbp` value itself when it is missing **Recommendation: disable this.** The \_fbp value should not be generated by your server container because then it won't be an identifier Meta issues or recognises. Meta cannot tie it to a person on its own. All it can do is group events that came from the same browser, and that only works if the cookie is reliably written to your tracking domain and returned on every following request.

**Use HttpOnly cookies**

An HttpOnly cookie cannot be read by JavaScript in the browser. It is only sent along with requests to your server. Enabling or disabling this option depends on your setup:

* **Server-side only:** enable it. Nothing in the browser needs to read the cookie, and an HttpOnly cookie cannot be read out by scripts or browser extensions running on your site. It is also less exposed to cookie-clearing behaviour by browsers, because the cookie is set by your server rather than by JavaScript.
* **Client-side and server-side with deduplication:** disable it. The Meta Pixel in the browser will read the \_fbp with JavaScript. If the cookie is HttpOnly, the Pixel cannot see it, generates its own browser ID, and you end up with two different identifiers for the same user. That breaks the match between your browser events and your server events.

**Enable Event Enhancement**

This option lets the tag store user data in a separate HttpOnly cookie (`gtmeec`) on your own domain. **Recommendation: enable this.** It raises your event match quality, which improves attribution and Meta's ability to optimise your campaigns. The data stays in a first-party, HttpOnly cookie that JavaScript cannot access.

{% hint style="info" %}
Do consider your privacy documentation: the tag stores personal data (hashed) in a cookie on your domain, so make sure this is covered in your cookie policy and that the tag only fires with marketing consent.
{% endhint %}

**Use Optimistic Scenario**

Normally the tag waits for Meta's API to confirm that the event was received before reporting back to GTM. With this option enabled, the tag reports success immediately, without waiting for a response. **Recommendation: leave this disabled.** You lose your only view of whether events actually arrive, which makes tracking problems very hard to spot.&#x20;

### Step 4: Add a trigger

1. Give the tag a new trigger. Click **Triggers** under the tag, then click the blue plus icon in the top right.
2. Choose the grey **Custom** option as the trigger configuration.
3. Add your condition. Common options are:

* **Based on specific event names**
  * `{{Event Name}}` matches RegEx `eventname|eventname`
    * Always include `page_view` as the first event name.&#x20;
* **Without a condition**, if you want to send every GA4 event to the Conversions API
  * `{{Client Name}}` equals `GA4`

4. Save the trigger and the tag.

<figure><img src="https://1274044937-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FA65KwL1NwewlJbtCXsXd%2Fuploads%2FTuFNaTS8n5ugIia78FmV%2Fimage.png?alt=media&amp;token=1973d922-d95f-488c-8c44-299169467cd0" alt=""><figcaption></figcaption></figure>

### Step 5: Test

Use the server container preview mode to check that the Facebook Conversion API tag fires on incoming events.

For a more thorough check, add a **Test ID** to the tag and open the Test Events tab in Meta Events Manager. Your events should appear with **Server** listed as the source. Remove the Test ID again once you are done testing.

### Optional: Add or override event parameters

By default, the tag builds its payload from the incoming event on its own. It reads the parameters your web container sends to the server container and maps the ones it recognises to their Meta equivalents. For most setups that is enough.

You can override that mapping, or add parameters the tag does not pick up by itself. Open your Facebook Conversion API tag and expand the sections below the main settings:

* **Server Event Data Override** — for event-level fields, such as the event name or the event ID.
* **User Data** — for identifying parameters, including the browser ID and click ID.
* **Custom Data** — for the commercial details of the event, such as value, currency and product data.

Each section works the same way: you add a property, choose which field you want to fill, and give it a value. That value is normally a variable pointing at a parameter in the incoming event.

There are two reasons to do this:

* **The parameter arrives, but the tag does not map it.** Your web container may send a value under a name the tag does not recognise, or in a structure it cannot read. Pointing the field at the right parameter yourself gets it into the payload.
* **The parameter is wrong or missing.** If the automatic mapping produces a value you do not want to send, an override replaces it.

Which parameters are available to you depends entirely on what your GA4 event tags send from the web container. There is no universal list. Open the server container preview mode, look at an incoming request, and work from the parameters you actually see there.

Two things to keep in mind. The tag hashes user data automatically, so pass values in plain text and do not hash them yourself first. And only map parameters you have a legal basis to send: anything you add here goes to Meta, so it needs to be covered by your consent setup and your privacy statement.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.adpage.io/integrations-marketingtools/meta-ads.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
