> For the complete documentation index, see [llms.txt](https://doc.commandersact.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://doc.commandersact.com/fr/developpeurs/commanders-tag-gateway.md).

# Commanders Act Gateway

Ce document décrit comment déployer **Commanders Act Gateway**, un **unified first-party gateway** qui utilise **une seule configuration et un seul chemin sur votre domaine** pour alimenter plusieurs cas d'usage de suivi et d'hébergement.

Commanders Act Gateway inclut **Google Tag Gateway**, mais n'est **pas limité à Google**.\
Il est conçu pour servir et collecter des données pour **tous vos partenaires marketing et d'analyse**, en utilisant la même infrastructure first-party.

Une configuration, un chemin first-party, trois usages :

* Google Tag Gateway (GA4, Google Ads)
* Suivi first-party vers toutes les destinations server-side
* Hébergement first-party de bibliothèques de tiers

Si votre objectif est d'implémenter Google Tag Gateway, vous êtes au bon endroit.\
Si votre objectif est de construire une architecture durable de suivi first-party agnostique vis-à-vis des fournisseurs, vous êtes également au bon endroit.

<figure><img src="https://1259070148-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Mk6XpTQ2LaRLcr2tA-d%2Fuploads%2Fgit-blob-5c269a1cb309c24a7504446eef7a53b7aafd97d9%2Fschema_google_ads%20(4).png?alt=media" alt=""><figcaption></figcaption></figure>

***

**Pourquoi utiliser Commanders Gateway ?**

**1. Avantages de l'utilisation d'une passerelle**

Une configuration de passerelle améliore **la qualité et l'exhaustivité de la collecte de données** sur l'ensemble de votre stack marketing.

* Les scripts des fournisseurs sont servis depuis votre propre domaine, ce qui réduit la probabilité d'être bloqué par les bloqueurs de publicité.
* Les restrictions du navigateur (comme l'ITP de Safari) limitent ou bloquent souvent les cookies third-party et certains cookies JavaScript 1st party, mais avec une configuration server-side first-party, la mesure reste plus fiable.
* Cela garantit **un suivi plus précis**, en fournissant aux partenaires des signaux de meilleure qualité pour la mesure, l'attribution et l'optimisation.

**2. Avantages de l'utilisation de Commanders Gateway**

En plus des avantages de toute approche de passerelle, **Commanders Gateway** apporte des avantages uniques :

* Pas limité à Google Tag Gateway — la même configuration durable s'applique à **tous vos partenaires** (Meta, Snapchat, Bing, Awin, etc.).
* Configuration unifiée : un **chemin unique** (`/mypath`) sert et relaie toutes les bibliothèques des fournisseurs.
* Des noms de fichiers JavaScript obfusqués sont fournis automatiquement par Commanders Act, ce qui rend la détection par les listes de blocage beaucoup plus difficile.
* Avec le même chemin simple, vous pouvez également activer d'autres **fonctionnalités d'hébergement et de suivi first-party** telles que : héberger vos conteneurs de tag management, le suivi d'événements server-side, ou des statistiques CMP anonymes. Une seule configuration alimente l'ensemble de votre système d'hébergement et de suivi first-party.
* Une configuration centralisée simplifie le déploiement et la maintenance tout en restant **pérenne** face aux restrictions à venir des navigateurs.

***

**Vue d'ensemble**

**Commanders Gateway** vous permet de déployer des tags marketing et de mesure en utilisant votre **propre infrastructure first-party**, hébergée sur le domaine de votre site web.\
Cette infrastructure se situe entre votre site web et les services de vos partenaires (Google, Meta, Bing, Snapchat, Awin, etc.).

Avec Commanders Gateway :

* Les bibliothèques Google (gtag.js / gtm.js) sont chargées directement depuis votre **domaine first-party**.
* Les autres bibliothèques des fournisseurs sont servies depuis `/mypath/js/` en utilisant **des noms de fichiers obfusqués**.
* Toutes les requêtes de mesure sont relayées via votre domaine avant d'être transmises aux points de terminaison correspondants des partenaires.

***

**Google Tag Gateway (GTG) et consentement**

{% hint style="info" %}
Cette section est rédigée pour la vérification des exigences du Consent Mode avec Google Tag Gateway (GTG). Elle explique ce que GTG change pour le consentement, comment vérifier l'inscription, et quoi faire si un signal de consentement « tardif » est détecté sur un domaine inscrit à GTG.
{% endhint %}

**Ce que Google Tag Gateway change pour le consentement**

**Google Tag Gateway (GTG) pour les annonceurs** permet à un site web de servir des tags Google (`gtag.js`, `gtm.js`) depuis le propre domaine first-party du site au lieu de `googletagmanager.com`, en utilisant un CDN, un load balancer ou un serveur web. Commanders Act Gateway peut être utilisé pour implémenter GTG (voir [Architecture](#architecture) ci-dessous).

GTG ne change pas *ce que* fait le consent mode — il change **d'où est servi le tag Google et, surtout, quand il peut se charger par rapport à votre bannière de consentement**. C'est là que se situe l'impact sur le consentement :

* **Injection CDN automatique / en un clic** (la configuration dans l'interface proposée par Google pour Cloudflare, Akamai, Fastly ou un Google Cloud Load Balancer) fait que Google injecte directement la règle de routage dans la configuration de votre CDN ou de votre load balancer, plaçant généralement le tag Google très tôt dans la page. Comme cette injection se produit **en dehors de votre tag management ou du code source de la page**, vous ne pouvez généralement **plus contrôler l'ordre de chargement des scripts** par rapport à votre bannière de consentement. Si le stub de consentement de votre CMP n'a pas encore été exécuté et n'a pas défini les états de consentement par défaut, le tag Google peut se déclencher en premier.
* **Configuration GTG manuelle / en libre-service**, où vous configurez vous-même le routage et référencez directement le script first-party dans le code source de votre page, garde l'ordre de chargement des scripts sous votre contrôle — vous décidez si le tag Google ou le script de consentement de votre CMP se charge en premier.

Lorsqu'un tag Google se déclenche avant que votre CMP ait défini un état de consentement par défaut, c'est ce que Google appelle un **signal de consentement « tardif »** : le tag s'exécute avec un état de consentement inconnu/non défini au lieu de respecter le défaut que votre CMP était censée définir. Cela peut amener les tags à se comporter comme si aucun cadre de consentement n'était présent, et cela est signalé par les propres outils de diagnostic de Google (voir [Vérification](#verification-checklist) ci-dessous).

{% hint style="warning" %}
Revenir en arrière sur GTG est **pas** la manière recommandée de résoudre un signal de consentement tardif : cela fait perdre les avantages de durabilité de la mesure first-party que GTG est conçu pour offrir. Les remédiations recommandées sont décrites dans [Si un signal de consentement tardif est détecté](#if-a-late-consent-signal-is-detected-and-gtg-enrollment-is-confirmed) ci-dessous.
{% endhint %}

**La documentation de Google sur GTG**

* [Google tag gateway pour les annonceurs – aperçu](https://developers.google.com/tag-platform/tag-manager/gateway)
* [Configurer Google tag gateway pour les annonceurs](https://developers.google.com/tag-platform/tag-manager/gateway/setup-guide)

**Vérifier si un tag est inscrit à GTG**

Avant d'examiner un problème de consentement lié à GTG, confirmez si le domaine est réellement inscrit. L'une des méthodes suivantes peut être utilisée :

* **Dans l'interface Google du produit** — Dans Google Tag Manager, allez à **Admin → Google tag gateway**. Chaque domaine est listé avec un statut : `First-party` (GTG est actif), `Non démarré` (GTG n'a pas été activé), ou `Domaine activé` pour les domaines configurés manuellement ou via un tag différent. Le même statut est disponible dans l'écran équivalent de Google Ads et Google Analytics.
* **Google Tag Assistant** — Connectez Tag Assistant au site web, déclenchez les tags concernés, et vérifiez d'où les requêtes du tag Google sont réellement servies et vers où elles sont envoyées (**Résumé → Sortie → Hits envoyés**). Si les requêtes du tag Google sont acheminées vers votre propre domaine (par exemple `example.com/mypath/` ou `example.com/gtag/js`) au lieu de `www.googletagmanager.com` ou `www.google-analytics.com`, GTG est actif pour cette page.
* **DevTools du navigateur** — Dans l'onglet Network, vérifiez si le script et les requêtes de mesure pour `gtag.js` / `gtm.js` proviennent de votre domaine first-party plutôt que d'un domaine Google.

**Si un signal de consentement « tardif » est détecté et que l'inscription CAGT est confirmée**

Un signal de consentement tardif apparaît généralement dans les [outils de débogage du consentement](https://developers.google.com/tag-platform/security/guides/consent-debugging) (la chronologie du consentement de Tag Assistant, ou un avertissement dans la console) lorsque le tag Google se déclenche avant qu'un état de consentement par défaut n'ait été défini, ou lorsqu'un état de consentement est signalé comme « inconnu » au moment du déclenchement du tag.

**Une fois que vous avez confirmé à la fois (a) un signal de consentement tardif, et (b) que GTG est inscrit sur le domaine**, Google recommande l'une des voies de remédiation suivantes :

1. **Adoptez le Advanced Consent Mode** dans la configuration de votre CMP Commanders Act, et configurez **les Data Transmission Controls** et **les Global Consent Defaults** dans les paramètres de votre tag Google (Google Ads, GA4 ou Campaign Manager 360) selon vos besoins de conformité. C'est le mécanisme que Google recommande spécifiquement pour les tags activés pour GTG — voir [pourquoi ci-dessous](https://claude.ai/chat/4300c170-a117-4d9d-ae3c-86117d316787#why-advanced-consent-mode-u+c-is-recommended-for-gtg).
2. **Migrez tous vos tags Google dans un seul conteneur Google Tag Manager, et déployez ce conteneur lui-même via GTG**, au lieu d'injecter des tags gtag.js individuels. Cela centralise le contrôle de l'ordre de chargement dans GTM, de sorte que les vérifications de consentement intégrées à GTM s'appliquent à chaque tag Google du conteneur, quelle que soit la manière dont le script du conteneur est acheminé.
3. **Configurez GTG manuellement**, afin que vous — et non une injection CDN automatisée — contrôliez l'emplacement de la référence du script first-party GTG dans le code source de votre page, par rapport au script de bannière de consentement de Commanders Act.

{% hint style="info" %}
Ces trois options ne s'excluent pas mutuellement. Par exemple, une configuration GTG manuelle (option 3) peut être combinée avec le Advanced Consent Mode (option 1) pour une résilience supplémentaire si l'ordre de chargement est un jour affecté par un changement futur de page ou de CDN.
{% endhint %}

**Pourquoi le Advanced Consent Mode est recommandé pour GTG**

Le Advanced Consent Mode est le mécanisme que Google recommande pour les tags activés pour GTG car, contrairement au Basic Consent Mode (qui bloque simplement le tag jusqu'à ce qu'un défaut soit défini), il est **compatible avec les configurations GTG manuelles**: il permet au tag Google de se charger et d'envoyer des pings cookieless respectueux de la vie privée, même lorsque le consentement est refusé ou pas encore connu, et passe à une mesure complète dès que le choix du visiteur est reçu — sans dépendre de l'ordre exact dans lequel le script GTG et la bannière de consentement se chargent.

Pour l'activer avec Commanders Act :

* Activez **Advanced Consent Mode** dans la configuration Google Consent Mode de Commanders Act — voir [Google Consent Mode dans Commanders Act TMS](https://doc.commandersact.com/features/consent-management/setup-guides/tag-manager/google-consent-mode-in-commanders-act-tms) et [Google Tag Manager (GTM) – Consent Mode](https://doc.commandersact.com/features/consent-management/setup-guides/tag-manager/google-tag-manager-gtm-consent-mode).
* Activez **les Data Transmission Controls** dans les paramètres de votre tag Google (Google Ads, GA4 ou Campaign Manager 360) afin de restreindre indépendamment les données publicitaires, analytiques et de diagnostic lorsque le consentement est refusé — voir [contrôles de transmission des données](https://support.google.com/google-ads/answer/16054531).
* Définissez **les Global Consent Defaults** pour votre tag Google afin qu'un état de consentement de base (refusé, sauf exigence contraire) s'applique toujours par région, même dans le cas rare où il n'est pas possible de garantir que le stub du CMP s'exécute en premier — voir la [section sur le comportement spécifique à la région du guide Google sur le consent mode](https://developers.google.com/tag-platform/security/guides/consent#region-specific_behavior) et [paramètres de vue d'ensemble du consentement de GTM](https://support.google.com/tagmanager/answer/10718549?hl=en).

{% hint style="success" %}
Choisissez le bon modèle ! Si vous devez activer Google Consent Mode avec IAB TCF, utilisez nos [modèles de bannière IAB TCF](https://doc.commandersact.com/features/consent-management/user-guides/privacy-banners/banner-templates) (Footer ou Popin) et suivez les [spécifications de configuration mentionnées ici](https://doc.commandersact.com/features/consent-management/setup-guides/tag-manager/google-consent-mode-in-commanders-act-tms#additional-settings)
{% endhint %}

***

**Architecture**

Avec **Commanders Gateway**, vous réservez un **chemin unique** sur votre domaine, par exemple :

```
https://example.com/mypath/
```

* **Les scripts Google** (gtag.js / gtm.js) sont chargés directement depuis `/mypath/`.
* **Les autres scripts des fournisseurs** (Meta, Snapchat, Bing, Awin, etc.) sont servis depuis `/mypath/js/` avec un **nom de fichier obfusqué** généré par Commanders Act.

Exemple :

```
https://example.com/mypath/js/f4558899203.js
```

Le mappage entre chaque fournisseur et son nom de fichier de script obfusqué est fourni dans l' **interface First-Party Hosting de Commanders Act**.

**Schéma (conceptuel) :**

```
Site web  →  example.com/mypath/ (Google tags)
         →  example.com/mypath/js/f4558899203.js (Meta, Snap, Bing…)
         →  Commanders Gateway  →  point de terminaison du fournisseur
```

***

**Filtrage et gouvernance des cookies**

Certaines organisations, en particulier celles qui ont des politiques de confidentialité strictes, peuvent craindre d'envoyer **des cookies first-party à des partenaires externes** comme Google. Commanders Gateway prend en charge **la minimisation des données** et fournit des mécanismes permettant de contrôler quels cookies peuvent transiter par la gateway. Deux approches complémentaires peuvent être utilisées :

**Liste noire de cookies en périphérie**

Les clients peuvent filtrer les cookies **directement au niveau du CDN ou de la couche edge** (Cloudflare Worker, Fastly Compute, etc.). Cela peut être fait en **configurant simplement le code Worker fourni dans ce guide** (voir les onglets Cloudflare free ou Faslty ci-dessous) pour supprimer des cookies spécifiques avant que la requête ne soit transmise à Commanders Gateway.

Cela permet de retirer des cookies spécifiques de la requête **avant qu'elle n'atteigne Commanders Gateway**, en garantissant que seuls les cookies approuvés par l'organisation quittent son infrastructure.

**Liste blanche de cookies avant transfert aux partenaires**

Commanders Gateway peut également imposer une **liste blanche de cookies lors du transfert des requêtes aux partenaires**.

Par exemple, lors du transfert des requêtes de mesure à Google, la gateway peut être configurée pour **n'inclure que les cookies liés à Google** (tels que `_ga` ou `_gcl_*`).\
Tous les autres cookies sont automatiquement exclus de la requête envoyée à Google.

**Avant de commencer**

Ce guide suppose que votre site web est déjà configuré avec :

* Un système de gestion des tags (Commanders Act, Google Tag Manager ou équivalent).
* Un CDN ou un load balancer (Cloudflare, Akamai, Fastly, Nginx, etc.) capable de relayer des requêtes vers des points de terminaison externes.

***

**Étape 1 : Choisir le chemin de diffusion du tag**

Vous devez réserver **un chemin** sur le domaine de votre site web.

Exemple :

```
/mypath
```

Attention : cette configuration redirige tout le trafic avec le chemin choisi. Pour éviter d'affecter votre site web, choisissez un chemin qui n'est pas déjà utilisé.

***

**Étape 2 : Acheminer le trafic**

{% tabs %}
{% tab title="Cloudflare Enterprise" %}
Lors de l'utilisation de Cloudflare Enterprise, nous recommandons d'utiliser un **Cloudflare Worker** pour relayer tout le trafic depuis votre chemin choisi, par exemple `/mypath`, vers l'infrastructure Commanders Gateway.

Cette approche est la même que la configuration Cloudflare Free. Elle est plus fiable que d'essayer d'acheminer le chemin avec Cloudflare Origin Rules, car le Worker donne un contrôle total sur l'URL de la requête, les en-têtes, le filtrage des cookies et le transfert de géolocalisation.

**Étape 1 : Créer le Worker**

1. Dans le tableau de bord Cloudflare, allez à **Workers & Pages** → **Create application** → **Worker**.
2. Copiez/collez le code suivant :

```javascript
const prefix = "/mypath"; // Chemin d'exemple, remplacez-le par le chemin choisi à l'étape précédente
const sid = "12345"; // ID d'espace de travail d'exemple (aka ID du site), remplacez-le par votre propre ID

// Liste des noms de cookies qui ne doivent PAS être transmis à Commanders Gateway. Vous pouvez ajouter vos cookies techniques si nécessaire
const blacklistedCookies = [
  "PHPSESSID",
  "JSESSIONID"
];

addEventListener("fetch", event => {
  event.respondWith(handleRequest(event.request));
});

function filterCookieHeader(cookieHeader, blacklist) {
  if (!cookieHeader) return "";

  const blacklistSet = new Set(blacklist);

  const filteredCookies = cookieHeader
    .split(";")
    .map(cookie => cookie.trim())
    .filter(cookie => {
      const cookieName = cookie.split("=")[0];
      return !blacklistSet.has(cookieName);
    });

  return filteredCookies.join("; ");
}

async function handleRequest(request) {
  const url = new URL(request.url);

  if (url.pathname.startsWith(prefix)) {
    // Construire l'URL cible. Elle remplace ${sid} par votre ID d'espace de travail/site ci-dessus.
    const targetUrl = `https://s${sid}.commander4.com${url.pathname}${url.search}`;

    // Cloner les en-têtes de la requête
    const newHeaders = new Headers(request.headers);
    newHeaders.set("X-Forwarded-Host", url.host);
    newHeaders.set("X-Forwarded-For", request.headers.get("CF-Connecting-IP"));
    newHeaders.set("X-Forwarded-Proto", "https");


    const country = request.cf?.country || "";
    const region = request.cf?.regionCode || "";

    if (country) newHeaders.set("X-Forwarded-Country", country);
    if (region) newHeaders.set("X-Forwarded-Region", region);
    if (country && region) {
      newHeaders.set("X-Forwarded-CountryRegion", `${country}-${region}`);
    }

    // Filtrer l'en-tête Cookie avant de relayer la requête.
    const cookieHeader = newHeaders.get("Cookie");
    const filteredCookies = filterCookieHeader(cookieHeader, blacklistedCookies);

    if (filteredCookies) {
      newHeaders.set("Cookie", filteredCookies);
    } else {
      newHeaders.delete("Cookie");
    }

    // Supprimer l'en-tête Host pour éviter les conflits
    newHeaders.delete("host");

    // Relayer la requête vers l'infrastructure Commanders Gateway
    const proxyRequest = new Request(targetUrl, {
      method: request.method,
      headers: newHeaders,
      body: request.body,
      redirect: "manual"
    });

    const response = await fetch(proxyRequest);
    const responseHeaders = new Headers(response.headers);
    responseHeaders.delete("NEL");
    responseHeaders.delete("Report-To");

    return new Response(response.body, {
      status: response.status,
      statusText: response.statusText,
      headers: responseHeaders
    });
  }

  return new Response("Not Found", { status: 404 });
}
```

Ce Worker relaie les requêtes tout en ajoutant des en-têtes supplémentaires :

* `X-Forwarded-Host`
* `X-Forwarded-Country`
* `X-Forwarded-Region`
* `X-Forwarded-CountryRegion`

Il peut également filtrer les cookies sensibles ou techniques avant de transmettre la requête à Commanders Gateway.

**Étape 2 : Lier le Worker au chemin**

1. Dans Cloudflare, ouvrez les paramètres de votre domaine.
2. Accédez à **Workers Routes**.
3. Ajoutez une nouvelle route avec :
   * **URL pattern**: `www.example.com/mypath*`
   * **Worker**: sélectionnez le Worker créé à l'étape 1.

Une fois enregistré, toutes les requêtes vers `/mypath` sera acheminé via proxy vers Commanders Gateway.

**Étape 3 : Vérifier la configuration**

Vous pouvez vérifier la configuration en accédant à :

```
https://example.com/mypath/g/healthy
```

Note : le sous-chemin Google par défaut est /g/, mais il peut être personnalisé. Ce sous-chemin Google se trouve immédiatement après /mypath/.

Il doit renvoyer :

```
ok
```

Pour vérifier le transfert de géolocalisation, vous pouvez aussi tester :

```
https://example.com/mypath/g/?validate_geo=healthy
```

Il doit également renvoyer :

```
ok
```

Le proxy transmet l'IP du visiteur depuis Cloudflare's `CF-Connecting-IP` via `X-Forwarded-For`. Il utilise `request.cf.regionCode` pour le code de région ISO. Les redirections sont renvoyées au navigateur au lieu d'être suivies en périphérie.

**Vérifier le transfert de l'IP et de la localisation du visiteur**

Ouvrez `https://example.com/mypath/debug/`, en utilisant le domaine de votre site web et le préfixe Gateway. Vérifiez les champs sous `calculé`:

* `behindClientProxy` doit être `true`.
* `clientIpSource` doit être `"x-forwarded-for"` (ou `"true-client-ip"` lors de l'utilisation de cet en-tête).
* `countryRegionSource` doit identifier les `x-forwarded-*` en-têtes, normalement `"x-forwarded-countryregion"` lorsque l'en-tête combiné est fourni.

Vérifiez que l'IP et le pays/la région calculés correspondent au visiteur, et non au proxy. Utilisez les codes ISO, par exemple le pays `FR`, région `IDF` et la valeur combinée `FR-IDF`. Un nom complet de région tel que `Île-de-France` est ignoré. Si aucune IP ou localisation de visiteur exploitable n'est transmise, Gateway revient à l'IP ou à la localisation du proxy. Un contrôle de santé réussi à lui seul ne confirme pas le transfert de l'IP et de la localisation du visiteur.
{% endtab %}

{% tab title="Cloudflare Snippet" %}
Les Cloudflare Snippets offrent une alternative plus légère à un Worker complet pour acheminer via proxy le chemin Commanders Gateway. Un Snippet exécute du JavaScript en périphérie et est associé à une **règle Snippet** qui détermine quelles requêtes l'exécutent.

{% hint style="info" %}
Les Cloudflare Snippets sont disponibles sur **Pro, Business et Enterprise** plans. Le nom d'hôte utilisé pour Gateway doit être acheminé via proxy par Cloudflare.
{% endhint %}

**Étape 1 : Créer le Snippet**

1. Dans le Dashboard Cloudflare, ouvrez votre domaine.
2. Accédez à **Règles** → **Snippets**.
3. Créez un nouveau Snippet et donnez-lui un nom descriptif, par exemple `Commanders Gateway`.
4. Collez le code suivant :

```javascript
const CONFIG = {
  prefix: "/mypath", // Remplacez-le par le chemin Gateway choisi pour votre site web
  targetBase: "https://s1234.commander4.com", // Remplacez 1234 par l'ID de votre workspace/site
  blacklistedCookies: [
    "PHPSESSID",
    "JSESSIONID"
  ]
};

function filterCookieHeader(cookieHeader, blacklist) {
  if (!cookieHeader) return "";
  const blacklistSet = new Set(blacklist);
  return cookieHeader
    .split(";")
    .map(c => c.trim())
    .filter(c => {
      const name = c.split("=")[0].trim();
      return !blacklistSet.has(name);
    })
    .join("; ");
}

export default {
  async fetch(request) {
    const url = new URL(request.url);

    if (!url.pathname.startsWith(CONFIG.prefix)) {
      return new Response("Not Found", { status: 404 });
    }

    const remainingPath = url.pathname.slice(CONFIG.prefix.length) || "/";
    const targetUrl = `${CONFIG.targetBase}${CONFIG.prefix}${remainingPath}${url.search}`;

    const newHeaders = new Headers(request.headers);

    newHeaders.set("X-Forwarded-Host", url.host);
    newHeaders.set("X-Forwarded-For", request.headers.get("CF-Connecting-IP"));

    newHeaders.set("X-Forwarded-Proto", "https");

    const country = request.cf?.country || "";
    const region = request.cf?.regionCode || "";
    if (country) newHeaders.set("X-Forwarded-Country", country);
    if (region) newHeaders.set("X-Forwarded-Region", region);
    if (country && region) {
      newHeaders.set("X-Forwarded-CountryRegion", `${country}-${region}`);
    }

    const cookieHeader = newHeaders.get("Cookie");
    const filteredCookies = filterCookieHeader(cookieHeader, CONFIG.blacklistedCookies);
    if (filteredCookies) {
      newHeaders.set("Cookie", filteredCookies);
    } else {
      newHeaders.delete("Cookie");
    }

    newHeaders.delete("host");

    const proxyRequest = new Request(targetUrl, {
      method: request.method,
      headers: newHeaders,
      body: request.body,
      redirect: "manual"
    });

    const response = await fetch(proxyRequest);

    if (response.status >= 300 && response.status < 400) {
      return new Response(response.body, {
        status: response.status,
        headers: response.headers
      });
    }

    return response;
  }
};
```

**Étape 2 : Personnaliser la configuration**

Mettez à jour les valeurs en haut du Snippet :

* `prefix`: remplacez `/mypath` par le chemin réservé à Commanders Gateway sur votre domaine.
* `targetBase`: remplacez `s1234.commander4.com` par le point de terminaison Commanders Gateway associé à l'ID de votre workspace/site.
* `blacklistedCookies`: ajoutez tous les cookies de session, sensibles ou internes qui ne doivent pas être transmis à Commanders Gateway.

Le Snippet transmet aussi le pays et la région du visiteur via `X-Forwarded-Country`, `X-Forwarded-Region`, et `X-Forwarded-CountryRegion`.

Les réponses de redirection provenant de Commanders Gateway sont intentionnellement renvoyées au navigateur au lieu d'être suivies automatiquement en périphérie.

**Étape 3 : Configurer la règle Snippet**

Associez le Snippet à une règle qui ne correspond qu'à votre chemin Commanders Gateway.

Par exemple, dans l'éditeur d'expressions :

```
starts_with(http.request.uri.path, "/mypath")
```

Remplacez `/mypath` par le même chemin configuré dans `CONFIG.prefix`.

{% hint style="warning" %}
Conservez la règle Snippet et `CONFIG.prefix` synchronisés. S'ils utilisent des chemins différents, les requêtes risquent de ne pas être proxyfiées comme prévu.
{% endhint %}

Déployez le Snippet après l'avoir testé avec les outils de prévisualisation de Cloudflare.

**Étape 4 : Vérifier la configuration**

Après le déploiement, vérifiez :

* `https://example.com/mypath/healthy` → doit renvoyer `ok`.
* `https://example.com/mypath/?validate_geo=healthy` → doit renvoyer `ok` lorsque le transfert de géolocalisation est correctement configuré.
* Les cookies listés dans `blacklistedCookies` ne sont plus présents dans les requêtes reçues par Commanders Gateway, tandis que les autres cookies sont conservés.

Le proxy transmet l'IP du visiteur depuis Cloudflare's `CF-Connecting-IP` via `X-Forwarded-For`. Il utilise `request.cf.regionCode` pour le code de région ISO. Les redirections sont renvoyées au navigateur au lieu d'être suivies en périphérie.

**Vérifier le transfert de l'IP et de la localisation du visiteur**

Ouvrez `https://example.com/mypath/debug/`, en utilisant le domaine de votre site web et le préfixe Gateway. Vérifiez les champs sous `calculé`:

* `behindClientProxy` doit être `true`.
* `clientIpSource` doit être `"x-forwarded-for"` (ou `"true-client-ip"` lors de l'utilisation de cet en-tête).
* `countryRegionSource` doit identifier les `x-forwarded-*` en-têtes, normalement `"x-forwarded-countryregion"` lorsque l'en-tête combiné est fourni.

Vérifiez que l'IP et le pays/la région calculés correspondent au visiteur, et non au proxy. Utilisez les codes ISO, par exemple le pays `FR`, région `IDF` et la valeur combinée `FR-IDF`. Un nom complet de région tel que `Île-de-France` est ignoré. Si aucune IP ou localisation de visiteur exploitable n'est transmise, Gateway revient à l'IP ou à la localisation du proxy. Un contrôle de santé réussi à lui seul ne confirme pas le transfert de l'IP et de la localisation du visiteur.
{% endtab %}

{% tab title="Cloudflare Free" %}
Avec Cloudflare Free, la configuration repose sur un **Worker simple** qui achemine via proxy tout le trafic du chemin choisi (par ex. `/mypath`) vers l'infrastructure Commanders Gateway.

**Étape 1 : Créer le Worker**

1. Dans le tableau de bord Cloudflare, allez à **Workers & Pages** → **Create application** → **Worker**.
2. Copiez/collez le code suivant :

```javascript
const prefix = "/mypath"; // Chemin d'exemple, remplacez-le par le chemin choisi à l'étape précédente
const sid = "12345"; // ID d'espace de travail d'exemple (aka ID du site), remplacez-le par votre propre ID

// Liste des noms de cookies qui ne doivent PAS être transmis à Commanders Gateway. Vous pouvez ajouter vos cookies techniques si nécessaire
const blacklistedCookies = [
  "PHPSESSID",
  "JSESSIONID"
];

addEventListener("fetch", event => {
  event.respondWith(handleRequest(event.request));
});

function filterCookieHeader(cookieHeader, blacklist) {
  if (!cookieHeader) return "";

  const blacklistSet = new Set(blacklist);

  const filteredCookies = cookieHeader
    .split(";")
    .map(cookie => cookie.trim())
    .filter(cookie => {
      const cookieName = cookie.split("=")[0];
      return !blacklistSet.has(cookieName);
    });

  return filteredCookies.join("; ");
}

async function handleRequest(request) {
  const url = new URL(request.url);
  if (url.pathname.startsWith(prefix)) {
    // Construire l'URL cible (elle remplace ${sid} par l'ID de votre workspace/site ci-dessus)
    const targetUrl = `https://s${sid}.commander4.com${url.pathname}${url.search}`;

    // Cloner les en-têtes de la requête
    const newHeaders = new Headers(request.headers);
    newHeaders.set("X-Forwarded-Host", url.host);
    newHeaders.set("X-Forwarded-For", request.headers.get("CF-Connecting-IP"));
    newHeaders.set("X-Forwarded-Proto", "https");


    const country = request.cf?.country || "";
    const region = request.cf?.regionCode || "";
    if (country) newHeaders.set("X-Forwarded-Country", country);
    if (region) newHeaders.set("X-Forwarded-Region", region);
    if (country && region) {
      newHeaders.set("X-Forwarded-CountryRegion", `${country}-${region}`);
    }

    // Filtrer l'en-tête Cookie avant de relayer la requête.
    const cookieHeader = newHeaders.get("Cookie");
    const filteredCookies = filterCookieHeader(cookieHeader, blacklistedCookies);

    if (filteredCookies) {
      newHeaders.set("Cookie", filteredCookies);
    } else {
      newHeaders.delete("Cookie");
    }

    // Supprimer l'en-tête Host pour éviter les conflits
    newHeaders.delete("host");

    // Relayer la requête vers l'infrastructure Commanders Gateway
    const proxyRequest = new Request(targetUrl, {
      method: request.method,
      headers: newHeaders,
      body: request.body,
      redirect: "manual"
    });
    const response = await fetch(proxyRequest);
    const responseHeaders = new Headers(response.headers);
    responseHeaders.delete("NEL");
    responseHeaders.delete("Report-To");

    return new Response(response.body, {
      status: response.status,
      statusText: response.statusText,
      headers: responseHeaders
    });
  }
  return new Response("Not Found", { status: 404 }); // Renvoie 404 si le chemin de la requête ne correspond pas au préfixe
}
```

Ce Worker achemine les requêtes via proxy tout en ajoutant des en-têtes supplémentaires (`X-Forwarded-Host`, `X-Forwarded-Country`, `X-Forwarded-Region`).

**Étape 2 : Lier le Worker au chemin**

1. Dans Cloudflare, ouvrez les paramètres de votre domaine.
2. Accédez à **Workers Routes**.
3. Ajoutez une nouvelle route avec :
   * **URL pattern**: `www.example.com/mypath*`
   * **Worker**: sélectionnez le Worker créé à l'étape 1.

Une fois enregistré, toutes les requêtes vers `/mypath` sera acheminé via proxy vers Commanders Gateway.

Le proxy transmet l'IP du visiteur depuis Cloudflare's `CF-Connecting-IP` via `X-Forwarded-For`. Il utilise `request.cf.regionCode` pour le code de région ISO. Les redirections sont renvoyées au navigateur au lieu d'être suivies en périphérie.

**Vérifier le transfert de l'IP et de la localisation du visiteur**

Ouvrez `https://example.com/mypath/debug/`, en utilisant le domaine de votre site web et le préfixe Gateway. Vérifiez les champs sous `calculé`:

* `behindClientProxy` doit être `true`.
* `clientIpSource` doit être `"x-forwarded-for"` (ou `"true-client-ip"` lors de l'utilisation de cet en-tête).
* `countryRegionSource` doit identifier les `x-forwarded-*` en-têtes, normalement `"x-forwarded-countryregion"` lorsque l'en-tête combiné est fourni.

Vérifiez que l'IP et le pays/la région calculés correspondent au visiteur, et non au proxy. Utilisez les codes ISO, par exemple le pays `FR`, région `IDF` et la valeur combinée `FR-IDF`. Un nom complet de région tel que `Île-de-France` est ignoré. Si aucune IP ou localisation de visiteur exploitable n'est transmise, Gateway revient à l'IP ou à la localisation du proxy. Un contrôle de santé réussi à lui seul ne confirme pas le transfert de l'IP et de la localisation du visiteur.
{% endtab %}

{% tab title="CloudFront" %}
Utilisez votre distribution CloudFront existante pour acheminer le chemin first-party réservé vers Commanders Act Gateway. Dans les exemples ci-dessous, remplacez `mypath` par votre préfixe Gateway et `1234` par l'ID de votre workspace/site Commanders Act.

**Étape 1 : Créer l'origine Gateway**

1. Ouvrez votre distribution et accédez à **Origins** → **Créer l'origine**.
2. Définissez **Domaine d'origine** à `s1234.commander4.com`, sans protocole ni chemin.
3. Laissez **Chemin d'origine** vide. Le chemin complet de la requête, y compris `/mypath`, doit parvenir à Gateway sans modification.
4. Utilisez **HTTPS uniquement** pour la connexion à l'origine, sur le port **443**.
5. Enregistrez l'origine.

**Étape 2 : Créer le comportement Gateway**

Accédez à **Behaviors** → **Créer le comportement** et configurez :

| Paramètre                          | Valeur requise                                       |
| ---------------------------------- | ---------------------------------------------------- |
| Modèle de chemin                   | `/mypath/*`, ou `/<prefix>/*` pour le préfixe choisi |
| Origine                            | L'origine Gateway créée ci-dessus                    |
| Politique de protocole du visiteur | Rediriger HTTP vers HTTPS                            |
| Méthodes HTTP autorisées           | **GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE**     |
| Politique de cache                 | **Managed-CachingDisabled**                          |
| Politique de requête d'origine     | **Managed-AllViewerExceptHostHeader**                |

Placez ce comportement avant tout modèle plus large susceptible de correspondre aux requêtes Gateway.

{% hint style="warning" %}
Le `/*` final dans le modèle de chemin est obligatoire. `/mypath` À lui seul, il ne correspond qu'à cette URL exacte : des requêtes telles que `/mypath/js/...`, `/mypath/cdp/...` et `/mypath/g/...` seraient routées vers votre site web au lieu d'être envoyées vers Gateway.

Sélectionnez la liste complète des méthodes HTTP autorisées. Les événements utilisent **POST** et les requêtes préliminaires CORS du navigateur utilisent **OPTIONS**. N'autoriser que GET et HEAD les bloque.
{% endhint %}

**Managed-AllViewerExceptHostHeader** transmet tous les en-têtes du visiteur sauf `Host`, toutes les chaînes de requête, tous les cookies, ainsi que les en-têtes de protocole, d'appareil et de localisation CloudFront, y compris `CloudFront-Viewer-Country` et `CloudFront-Viewer-Country-Region`. CloudFront définit l'en-tête Host de la requête d'origine `Host` à `s1234.commander4.com`.

{% hint style="warning" %}
N'utilisez pas **Managed-AllViewer** ou une politique de requête d'origine personnalisée sur le comportement Gateway. L'ancienne politique personnalisée `metrics-proxy-headers` n'est plus nécessaire.

Une politique personnalisée utilisant **Tous les en-têtes du visiteur et les en-têtes CloudFront suivants** transmet le Host du site web, ce qui empêche l'origine Gateway de fonctionner correctement. Une politique personnalisée utilisant **Tous les en-têtes du visiteur sauf** ne vous permet pas d'ajouter les en-têtes de localisation CloudFront, ce qui fait perdre le transfert de géolocalisation.
{% endhint %}

**Étape 3 : Créer et associer la CloudFront Function requise**

La fonction préserve le nom d'hôte du site web dans `x-forwarded-host` avant que CloudFront ne remplace `Host` par le nom d'hôte de l'origine Gateway. Elle copie également les en-têtes CloudFront de pays et de région disponibles vers les en-têtes de transfert Gateway.

1. Dans **CloudFront** → **Functions**, créez une fonction utilisant le runtime JavaScript **2.0**.
2. Collez le code suivant :

```javascript
function handler(event) {
  var request = event.request;
  var headers = request.headers;

  // Conserver le nom d'hôte du site web sans modifier l'en-tête Host en lecture seule.
  headers['x-forwarded-host'] = { value: headers.host.value };

  // Remplacer tous les en-têtes de transfert fournis par le viewer par les données de localisation CloudFront.
  delete headers['x-forwarded-country'];
  delete headers['x-forwarded-region'];
  delete headers['x-forwarded-countryregion'];

  var country = headers['cloudfront-viewer-country'];
  var region = headers['cloudfront-viewer-country-region'];

  if (country && country.value) {
    headers['x-forwarded-country'] = { value: country.value };
  }
  if (region && region.value) {
    headers['x-forwarded-region'] = { value: region.value };
  }
  if (country && country.value && region && region.value) {
    headers['x-forwarded-countryregion'] = {
      value: country.value + '-' + region.value
    };
  }

  // Conserver l'URI complète et la chaîne de requête inchangées.
  return request;
}
```

3. Enregistrez, testez et **publiez** la fonction.
4. Modifiez le `/mypath/*` comportement. Sous **Associations de fonction**, associez la fonction publiée à **requête du visiteur**.
5. Enregistrez le comportement et attendez la fin du déploiement de la distribution.

{% hint style="warning" %}
La fonction de requête du visiteur est obligatoire. N'ajoutez pas `x-forwarded-proto` à celle-ci : AWS interdit cet en-tête dans les fonctions en périphérie et renvoie **502 Bad Gateway** si la fonction le définit. Gateway utilise HTTPS par défaut. Ne modifiez pas l' `Host` en-tête en lecture seule dans la fonction.
{% endhint %}

CloudFront ajoute automatiquement l'IP du visiteur à `X-Forwarded-For`. Avec la politique de requête d'origine et la fonction de requête du visiteur ci-dessus, Gateway utilise l'IP du visiteur transmise ainsi que les codes pays/région disponibles pour les requêtes de collecte Google et Commanders Act. Aucun traitement de l'IP n'a besoin d'être ajouté à la fonction.

**Étape 4 : Vérifier la configuration complète**

1. Ouvrez `https://example.com/mypath/debug/`, en remplaçant le domaine et le préfixe par vos propres valeurs.
2. Dans les en-têtes renvoyés, vérifiez :
   * `headers.host` est `s1234.commander4.com` (votre ID de workspace/site).
   * `x-forwarded-host` est `example.com` (le nom d'hôte de votre site web).
   * Lorsque les données de localisation CloudFront sont disponibles, `x-forwarded-country`, `x-forwarded-region` et `x-forwarded-countryregion` contiennent les valeurs correspondantes.
3. Vérifiez `https://example.com/mypath/healthy`: il doit renvoyer `ok`.
4. Déclenchez un événement de test via votre intégration de suivi configurée. Dans les DevTools du navigateur, confirmez que la **POST** requête utilise votre domaine first-party et votre préfixe, atteint Gateway et apparaît dans l'inspecteur d'événements ou la destination attendue.
5. Testez un **OPTIONS** préflight sur le même point de terminaison d'événement, avec l'Origin réel du site web et les en-têtes utilisés par le POST. Confirmez qu'il atteint Gateway et que la réponse CORS autorise la requête.

Ne vous arrêtez pas au contrôle de santé : POST et OPTIONS doivent aussi fonctionner avant l'activation.

**Dépannage**

* Les requêtes en dessous du préfixe atteignent votre site web : vérifiez `/<prefix>/*` et la priorité du comportement.
* POST ou OPTIONS est rejeté : vérifiez la liste complète des méthodes HTTP autorisées.
* La réponse de débogage montre votre site web dans `headers.host`: sélectionnez **Managed-AllViewerExceptHostHeader**.
* `x-forwarded-host` manquant : publiez et associez la fonction sur **requête du visiteur** pour le comportement Gateway.
* CloudFront renvoie 502 après association de la fonction : vérifiez qu'elle ne définit pas `x-forwarded-proto` ou ne modifie pas `Host`.

Références AWS : [Politiques de requête d'origine gérées](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-managed-origin-request-policies.html) et [Restrictions sur les fonctions en périphérie](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/edge-function-restrictions-all.html).

**Vérifier le transfert de l'IP et de la localisation du visiteur**

Ouvrez `https://example.com/mypath/debug/`, en utilisant le domaine de votre site web et le préfixe Gateway. Vérifiez les champs sous `calculé`:

* `behindClientProxy` doit être `true`.
* `clientIpSource` doit être `"x-forwarded-for"` (ou `"true-client-ip"` lors de l'utilisation de cet en-tête).
* `countryRegionSource` doit identifier les `x-forwarded-*` en-têtes, normalement `"x-forwarded-countryregion"` lorsque l'en-tête combiné est fourni.

Vérifiez que l'IP et le pays/la région calculés correspondent au visiteur, et non au proxy. Utilisez les codes ISO, par exemple le pays `FR`, région `IDF` et la valeur combinée `FR-IDF`. Un nom complet de région tel que `Île-de-France` est ignoré. Si aucune IP ou localisation de visiteur exploitable n'est transmise, Gateway revient à l'IP ou à la localisation du proxy. Un contrôle de santé réussi à lui seul ne confirme pas le transfert de l'IP et de la localisation du visiteur.
{% endtab %}

{% tab title="Akamai" %}
{% hint style="warning" %}
Commanders Gateway avec Akamai est en **beta**. Si vous avez une question ou un problème avec votre configuration, contactez le support
{% endhint %}

**Créer la règle de redirection**

1. Créez une nouvelle version de votre configuration de livraison dans **Property Manager**.
2. Sous la **Paramètres de configuration de propriété** section, ajoutez une nouvelle Rule :
   * Nommez-la : *Acheminement des mesures*
3. Ajoutez un nouveau **Correspondance**:
   * Type de correspondance : `Chemin`
   * Condition : *est l'un des*
   * Valeur : `/mypath/*`
4. Ajoutez un nouveau **Comportement**:
   * Sélectionnez *Comportement standard de la propriété* et choisissez **Serveur d'origine** comportement.
   * Définissez **Nom d'hôte du serveur d'origine** à `s1234.commander4.com.`
   * Définissez **Transmettre l'en-tête Host** à *Nom d'hôte d'origine*.
5. Enregistrez la nouvelle règle et déployez vos modifications.
   * ⚠️ Testez la règle de redirection dans votre **environnement de préproduction** avant le déploiement en production.
   * Assurez-vous qu'aucune autre règle ne modifie/supprime les en-têtes de réponse sortants (par ex., *Content-Type*) car cela peut casser les scripts.

***

**Transmettez l’IP du visiteur, le nom d’hôte du site web et le protocole**

Dans la règle Gateway, configurez la requête sortante vers l’origine pour inclure :

| En-tête             | Valeur                                                             |
| ------------------- | ------------------------------------------------------------------ |
| `X-Forwarded-Host`  | Le nom d’hôte d’origine du site web issu de la requête du visiteur |
| `X-Forwarded-Proto` | `https` pour le site web HTTPS                                     |
| `X-Forwarded-For`   | L’IP du visiteur, ajoutée par Akamai à la chaîne sortante          |

Si vous utilisez `True-Client-IP` à la place, configurez Akamai pour la renseigner avec l’IP du visiteur. Utilisez l’IP déterminée par Akamai, plutôt qu’une valeur fournie par le navigateur. Laissez **Transmettre l'en-tête Host** défini sur **Nom d'hôte d'origine**.

**Inclure les informations de géolocalisation**

1. Accédez à la **Variables de propriété** section et ajoutez les variables suivantes :

| Nom de la variable | Paramètres de sécurité |
| ------------------ | ---------------------- |
| USER\_REGION       | Hidden                 |
| USER\_COUNTRY      | Hidden                 |

2. Choisissez votre **règle de redirection** (créée ci-dessus) dans les paramètres de configuration de la propriété.
3. Ajoutez deux nouveaux **Définir la variable** comportements (un par variable) :

| Variable              | Créer la valeur à partir de | Récupérer les données depuis | Champ Edgescape | Opération |
| --------------------- | --------------------------- | ---------------------------- | --------------- | --------- |
| PMUSER\_USER\_REGION  | Extraire                    | Données Edgescape            | Code de région  | Aucun     |
| PMUSER\_USER\_COUNTRY | Extraire                    | Données Edgescape            | Code pays       | Aucun     |

4. Ajoutez deux nouveaux **Modifier l’en-tête de la requête sortante** comportements :

| Action  | Sélectionner le nom de l’en-tête | Nom d’en-tête personnalisé | Valeur de l’en-tête            |
| ------- | -------------------------------- | -------------------------- | ------------------------------ |
| Ajouter | Autre...                         | X-Forwarded-Region         | {{user.PMUSER\_USER\_REGION}}  |
| Ajouter | Autre...                         | X-Forwarded-Country        | {{user.PMUSER\_USER\_COUNTRY}} |

Utilisez Edgescape **Code de région** (code de subdivision ISO), et non le nom de la région. Transmettez le pays et la région séparément comme indiqué ci-dessus, ou fournissez leur valeur combinée via `X-Forwarded-CountryRegion` (par exemple `FR-IDF`).

5. Enregistrez la nouvelle règle et déployez vos modifications.

***

**Filtrer les cookies avant de les transmettre à Commanders Gateway**

Vous pouvez empêcher certains cookies d’être transmis à Commanders Gateway. Cela peut être utile pour les cookies de session, les cookies contenant des informations sensibles, ou les cookies techniques internes qui ne doivent pas quitter votre infrastructure.

La liste des cookies à exclure dépend des exigences de votre organisation.

**Option 1 : utiliser les capacités de gestion des cookies d’Akamai**

Si des comportements de gestion des cookies sont disponibles dans votre configuration Akamai, configurez Akamai pour supprimer les cookies concernés de la requête avant qu’elle ne soit transmise à Commanders Gateway.

Par exemple, vous pouvez vouloir exclure des cookies tels que :

```
PHPSESSID
JSESSIONID
```

Configurez le comportement afin que ces cookies soient supprimés de la **requête client envoyée à l’origine**, où l’origine est votre point de terminaison Commanders Gateway.

{% hint style="info" %}
Le nom exact et la disponibilité des comportements de gestion des cookies Akamai peuvent varier selon les produits Akamai activés sur votre compte.
{% endhint %}

**Option 2 : modifier l’en-tête Cookie sortant**

Si les capacités de gestion des cookies ne sont pas disponibles, vous pouvez utiliser un **Modifier l’en-tête de la requête sortante** comportement sur l’ `Cookie` en-tête et supprimer les cookies sélectionnés à l’aide d’une expression régulière.

Exemple pour `PHPSESSID` et `JSESSIONID`:

```regex
(?:^|;\s*)(PHPSESSID|JSESSIONID)=[^;]*
```

Configurez :

* **En-tête :** `Cookie`
* **Action :** Remplacement par regex
* **Expression régulière :** l’expression ci-dessus, adaptée à votre liste de cookies
* **Remplacement :** vide

{% hint style="warning" %}
Testez cette configuration avec soin avant de la déployer en production. Une expression régulière incorrecte peut entraîner un `Cookie` en-tête mal formé ou supprimer involontairement des cookies qui devraient être transmis.
{% endhint %}

Si vous utilisez plusieurs configurations CDN ou edge pour la même implémentation, gardez cohérente la liste d’exclusion des cookies entre elles.

***

**Vérifiez la configuration**

Après le déploiement de la configuration Akamai :

* Accédez à `https://example.com/mypath/healthy` → devrait afficher `ok`.
* Tester les en-têtes de géolocalisation : `https://example.com/mypath/?validate_geo=healthy` → devrait également afficher `ok`.
* Vérifiez que les requêtes transmises à Commanders Gateway ne contiennent plus les noms de cookies exclus, tandis que les autres cookies sont toujours transmis normalement.

**Vérifier le transfert de l'IP et de la localisation du visiteur**

Ouvrez `https://example.com/mypath/debug/`, en utilisant le domaine de votre site web et le préfixe Gateway. Vérifiez les champs sous `calculé`:

* `behindClientProxy` doit être `true`.
* `clientIpSource` doit être `"x-forwarded-for"` (ou `"true-client-ip"` lors de l'utilisation de cet en-tête).
* `countryRegionSource` doit identifier les `x-forwarded-*` en-têtes, normalement `"x-forwarded-countryregion"` lorsque l'en-tête combiné est fourni.

Vérifiez que l'IP et le pays/la région calculés correspondent au visiteur, et non au proxy. Utilisez les codes ISO, par exemple le pays `FR`, région `IDF` et la valeur combinée `FR-IDF`. Un nom complet de région tel que `Île-de-France` est ignoré. Si aucune IP ou localisation de visiteur exploitable n'est transmise, Gateway revient à l'IP ou à la localisation du proxy. Un contrôle de santé réussi à lui seul ne confirme pas le transfert de l'IP et de la localisation du visiteur.
{% endtab %}

{% tab title="Fastly" %}
{% hint style="warning" %}
La prise en charge de Commanders Gateway par Fastly est actuellement en **beta**. Les étapes ci-dessous sont destinées aux utilisateurs techniques familiarisés avec Fastly Compute (Compute Services). Selon la configuration de votre compte Fastly (domaines, TLS, produits activés), certaines étapes de liaison en production peuvent varier.
{% endhint %}

Lorsque vous utilisez Fastly, la configuration est différente de Cloudflare. Vous déployez un **service Compute** (Wasm) et le configurez principalement via la **API Fastly et la CLI** depuis un terminal.

**Prérequis**

1. Créez un jeton API dans l’interface Fastly (les portées doivent autoriser Compute, les services, les backends et les déploiements).
2. Exportez le jeton dans l’environnement de votre terminal :

```
export FASTLY_API_TOKEN=XXXXXXXXXXXX
```

3. Installez les prérequis :

* Node.js
* Fastly CLI

**Étape 1 : créez le service Compute**

Créez un nouveau service Compute :

```
fastly service create --name "CA Gateway" --type wasm
```

Fastly renvoie un **ID de service**, par exemple :

```
dyBxiT8wpc2c8ZQg2KRrMN
```

Enregistrez-le, vous en aurez besoin pour la création du backend et les déploiements.

**Étape 2 : créez un projet Compute local (starter kit)**

Générez un projet local à partir du starter kit JavaScript par défaut :

```
npm create @fastly/compute@latest -- --language=javascript --default-starter-kit
```

Cela crée une structure de projet similaire à :

```
.
├── README.md
├── fastly.toml
├── package.json
└── src
    ├── index.js
    └── welcome-to-compute.html
```

**Étape 3 : configurez l’ID de service dans fastly.toml**

Modifiez `fastly.toml` et définissez l’ID de service :

```
# fastly.toml
service_id = "YOUR_SERVICE_ID"
```

**Étape 4 : créez le backend (origine Commanders Gateway)**

Créez un backend pointant vers l’infrastructure Commanders Gateway (remplacez `1234` par votre ID de workspace/site) :

```
fastly backend create \
  --service-id YOUR_SERVICE_ID \
  --version 1 \
  --name commander_gateway \
  --address s1234.commander4.com \
  --use-ssl \
  --port 443 \
  --ssl-sni-hostname s1234.commander4.com
```

Notes :

* `--version 1` est un point de départ typique. Si votre service possède déjà des versions, utilisez celle que vous comptez déployer.
* L’adresse du backend doit être `s1234.commander4.com` (votre propre ID de workspace/site).

**Étape 5 : implémentez la logique de routage dans src/index.js**

Remplacez le contenu de `src/index.js` par le code worker suivant.

Vous devez modifier :

* `prefix` (votre chemin client, exemple : `/mypath`)
* `sid` (votre ID de workspace/site Commanders, exemple : `s1234`)

```javascript
/// <reference types="@fastly/js-compute" />

import { env } from "fastly:env";
import { includeBytes } from "fastly:experimental";

const prefix = "/PATHACHANGER";              // TODO : remplacez par le chemin Gateway que vous avez choisi (par ex. "/mypath")
const sid = "s123456";                       // TODO : remplacez par votre ID de workspace/site (par ex. "s1234")
const BACKEND = "commander_gateway";         // Nom du backend Fastly pointant vers sid.commander4.com

// Liste des noms de cookies qui ne doivent PAS être transmis à Commanders Gateway. Ajoutez vos cookies techniques si nécessaire
const blacklistedCookies = [
  "PHPSESSID",
  "JSESSIONID"
];

addEventListener("fetch", (event) => event.respondWith(handleRequest(event.request, event.client)));

function filterCookieHeader(cookieHeader, blacklist) {
  if (!cookieHeader) return "";

  const blacklistSet = new Set(blacklist);

  const filteredCookies = cookieHeader
    .split(";")
    .map(cookie => cookie.trim())
    .filter(cookie => {
      const cookieName = cookie.split("=")[0];
      return !blacklistSet.has(cookieName);
    });

  return filteredCookies.join("; ");
}

async function handleRequest(request, client) {

  const url = new URL(request.url);

  // Ne proxyfiez que les requêtes correspondant au préfixe configuré
  if (!url.pathname.startsWith(prefix)) {
    return new Response("Not Found", { status: 404 });
  }

  // Conservez le chemin client complet, y compris son préfixe configuré.
  const target = `https://${sid}.commander4.com${url.pathname}${url.search}`;

  // Clonez les en-têtes et ajoutez les informations de transfert
  const headers = new Headers(request.headers);
  headers.set("X-Forwarded-Host", url.host);
  headers.set("X-Forwarded-Proto", "https");

  // Ajoutez l’IP du visiteur à la chaîne de transfert existante.
  if (client.address) {
    const forwardedFor = headers.get("X-Forwarded-For");
    headers.set("X-Forwarded-For", forwardedFor
      ? `${forwardedFor}, ${client.address}`
      : client.address);
  }

  // Transmettez les informations géographiques lorsqu’elles sont disponibles (facultatif mais recommandé)
  const geo = client.geo;
  const country = geo && geo.country_code ? geo.country_code.toUpperCase() : "";
  const region = geo && geo.region ? geo.region : "";
  if (country) headers.set("X-Forwarded-Country", country);
  if (region)  headers.set("X-Forwarded-Region", region);
  if (country && region) headers.set("X-Forwarded-CountryRegion", `${country}-${region}`);

  // Filtrer l'en-tête Cookie avant de relayer la requête.
  const cookieHeader = headers.get("Cookie");
  const filteredCookies = filterCookieHeader(cookieHeader, blacklistedCookies);

  if (filteredCookies) {
    headers.set("Cookie", filteredCookies);
  } else {
    headers.delete("Cookie"); // Supprimez l’en-tête Cookie en entier si tous les cookies ont été filtrés
  }

  // Évitez les conflits d’en-tête Host à l’origine
  headers.delete("host");

  // Reconstruisez la requête pour l’origine
  const originReq = new Request(target, {
    method: request.method,
    headers,
    body: request.body
  });

  // Contournez le cache pour garantir que les hits de mesure ne sont jamais mis en cache
  const co = new CacheOverride("pass");

  // Envoyez la requête au backend Fastly configuré
  return fetch(originReq, { backend: BACKEND, cacheOverride: co });

}
```

Important :

* Remplacez `s1234.commander4.com` avec le véritable point de terminaison de votre ID de workspace/site.
* Conservez le même `prefix` que le chemin que vous réservez sur le domaine client (exemple : `/mypath`).
* N’ajoutez PAS de slash final à la fin du chemin dans les URL côté client.

**Étape 6 : déployer**

Déployez le service Compute :

```
npm run deploy
```

**Étape 7 : testez**

Après le déploiement, Fastly fournit un domaine temporaire pour les tests, par exemple :

```
https://plainly-rested-bison.edgecompute.app/mypath/healthy
```

Il doit renvoyer :

```
ok
```

**Liaison de production (domaine client)**

À ce stade, le service Compute s’exécute sur un domaine de test fourni par Fastly. Pour passer en production sur le domaine client (exemple : `https://example.com/mypath/`), vous devez encore lier le service au domaine de production et vous assurer que le TLS est en place.

Cela implique généralement, selon la configuration du client :

* Ajouter le domaine client au service Fastly et configurer TLS pour celui-ci (TLS géré ou certificat client).
* Créer l’enregistrement DNS requis (souvent un CNAME) afin que `example.com` pointe vers Fastly.
* S’assurer que le service Compute est celui qui reçoit les requêtes pour le chemin choisi (exemple : `/mypath*`) sur ce domaine.

Comme les étapes exactes dépendent des produits Fastly activés sur le compte et de la manière dont le client gère TLS et DNS, considérez ceci comme une étape bêta et contactez le support si vous avez besoin des commandes exactes pour votre configuration spécifique.

**Vérifier le transfert de l'IP et de la localisation du visiteur**

Ouvrez `https://example.com/mypath/debug/`, en utilisant le domaine de votre site web et le préfixe Gateway. Vérifiez les champs sous `calculé`:

* `behindClientProxy` doit être `true`.
* `clientIpSource` doit être `"x-forwarded-for"` (ou `"true-client-ip"` lors de l'utilisation de cet en-tête).
* `countryRegionSource` doit identifier les `x-forwarded-*` en-têtes, normalement `"x-forwarded-countryregion"` lorsque l'en-tête combiné est fourni.

Vérifiez que l'IP et le pays/la région calculés correspondent au visiteur, et non au proxy. Utilisez les codes ISO, par exemple le pays `FR`, région `IDF` et la valeur combinée `FR-IDF`. Un nom complet de région tel que `Île-de-France` est ignoré. Si aucune IP ou localisation de visiteur exploitable n'est transmise, Gateway revient à l'IP ou à la localisation du proxy. Un contrôle de santé réussi à lui seul ne confirme pas le transfert de l'IP et de la localisation du visiteur.
{% endtab %}
{% endtabs %}

***

**Étape 3 : mettez à jour les scripts dans votre système de tag management ou sur votre site web**

Remplacez les URL des scripts fournisseur par les nouveaux **chemins First-party**.

Exemples :

**Google**

```html
<!-- Au lieu de -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-12345"></script>

<!-- Utilisez -->
<script async src="/mypath/"></script>
```

**Meta (Facebook Pixel)**

```html
<!-- Au lieu de -->
<script src="https://connect.facebook.net/en_US/fbevents.js"></script>

<!-- Utilisez (chemin obfusqué fourni dans l’interface Commanders Act) -->
<script src="/mypath/js/f4558899203.js"></script>
```

**Snapchat**

```html
<script src="/mypath/js/a82b99df732.js"></script>
```

**Bing (UET)**

```html
<script src="/mypath/js/c77ac91be11.js"></script>
```

Chaque nom de fichier obfusqué est généré automatiquement et disponible dans le **interface First-Party Hosting de Commanders Act**.

**OneTag**

Vous pouvez modifier manuellement le domaine de votre configuration cact() avec le `collectionDomain` propriété Exemple :

```javascript
cact(..., {collectionDomain: "www.youdomain.com/mypath"});
```

Attention : n’ajoutez PAS un `/` à la fin du chemin

***

**Étape 4 : vérifiez la configuration**

* Pour le chemin global, vérifiez le point de terminaison de santé :
  * `https://example.com/mypath/healthy` → doit renvoyer `ok`
* Utilisez les DevTools du navigateur pour vérifier que :
  * les scripts Google sont chargés depuis `/mypath/`
  * les autres scripts fournisseur sont chargés depuis `/mypath/js/{obfuscated}.js`
  * Les requêtes sont effectuées vers votre **domaine first-party**.
* Assurez-vous que les événements apparaissent dans les dashboards partenaires respectifs (Google Analytics, Facebook Events Manager, etc.).

***

**Avantages**

* **Durabilité**: le tracking continue de fonctionner même avec ITP de Safari et les restrictions de cookies Third-party.
* **Résilience**: servir les scripts depuis votre domaine avec des noms de fichiers obfusqués rend plus difficile l’interférence des règles de blocage.
* **Configuration centralisée**: un seul chemin (`/mypath`) gère tous les fournisseurs.
* **Pérenne**: s’adapte à privacy sandbox et aux futures restrictions des navigateurs.
*

**Configurez la collecte de données First-party pour les fonctionnalités Commanders Act (via Gateway)**

Ce chapitre explique comment acheminer la collecte de données Commanders Act via votre **chemin gateway First-party** (par exemple `/mypath`) pour les principales fonctionnalités Commanders Act.

Notes importantes :

* Le chemin gateway affiché dans les exemples (`/mypath`) n’est qu’un exemple. Les clients choisissent leur propre chemin lors de la configuration du gateway dans leur outil CDN ou edge (Cloudflare, Akamai, etc.).
* Tous les exemples ci-dessous supposent que votre gateway est opérationnel : `https://example.com/mypath/healthy` renvoie `ok`.

***

**1. Destinations server-side via le gateway (exemple : Meta Facebook CAPI)**

Le tracking server-side Commanders Act repose sur **oneTag** tags. En général, vous aurez un oneTag par événement que vous souhaitez collecter, par exemple :

* `page_view`
* `add_to_cart`
* `purchase`

Pour acheminer ces événements oneTag via le gateway, vous devez mettre à jour la **configuration du tag oneTag** afin que la `cact()` configuration utilise votre domaine et votre chemin de collecte First-party.

Dans votre tag oneTag (ou dans le snippet partagé utilisé par vos tags oneTag), définissez `collectionDomain`:

```javascript
cact(..., { collectionDomain: "www.yourdomain.com/mypath" });
```

Notes :

* Remplacez `www.yourdomain.com/mypath` avec votre propre domaine et le chemin que vous avez configuré dans votre gateway.
* N’ajoutez PAS de slash `/` à la fin du chemin.
* Une fois cela défini, tous les événements oneTag (page\_view, add\_to\_cart, purchase, etc.) seront collectés via votre chemin gateway First-party.

***

**2. Collecte CDP, Campaign Analytics et CMP via le gateway**

*(Data Activation, Campaign Analytics, statistiques CMP et preuve de consentement)*

Ces trois fonctionnalités reposent sur le même mécanisme de routage. Pour envoyer leurs données via le gateway, vous devez définir la variable **`tC.clientCollectDns`** soit :

* directement dans chaque tag concerné, **ou**
* dans un **tag de configuration global** qui s’exécute avant tous les tags Commanders Act (recommandé).

Exemple :

```javascript
tC.clientCollectDns = "www.yourdomain.com/mypath";
```

Comportement :

* Dès que `tC.clientCollectDns` est défini, la collecte pour **Data Activation, Campaign Analytics et le suivi lié à CMP** sera effectuée via le gateway.
* `mypath` n’est qu’un exemple. Les clients peuvent utiliser n’importe quel chemin qu’ils ont configuré dans leur configuration de gateway.

Options d’implémentation :

* **Option A (simple) :** ajoutez la ligne directement dans le tag Data Activation / Campaign Analytics / CMP.
* **Option B (recommandée) :** ajoutez-la dans un tag de configuration global qui s’exécute avant tous les Commanders Act tags.

***

**Liste de vérification de validation**

Après avoir appliqué les modifications ci-dessus, vérifiez :

* Le point de terminaison de santé du gateway : `https://example.com/mypath/healthy` renvoie `ok`.
* Dans les outils de développement du navigateur (onglet Réseau), les requêtes de collecte Commanders Act vont vers votre domaine first party et le chemin (par exemple `https://example.com/mypath/...`).
* Les événements et les données apparaissent comme prévu dans :
  * Les dashboards de destination server-side (exemple : Meta Events Manager pour CAPI)
  * Flux Data Activation
  * Statistiques CMP et rapports de preuve de consentement (le cas échéant)
  * Rapports Campaign Analytics


---

# 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://doc.commandersact.com/fr/developpeurs/commanders-tag-gateway.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
