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

# Intégration côté serveur (Recommandé)

> Suivre les conversions depuis votre backend pour une fiabilité maximale

import { Steps, Step } from "fumadocs-ui/components/steps";

Le suivi côté serveur est la **méthode recommandée** pour le suivi des conversions car il :

* ✅ **Ne peut pas être bloqué** par les bloqueurs de publicités
* ✅ **Garantit la livraison** des événements de tracking
* ✅ **Confirme les actions** avant le tracking (ex: paiement vérifié)
* ✅ **Fonctionne avec les webhooks** des fournisseurs de paiement

## Comment ça marche

<Frame>
  <img src="https://mintcdn.com/taapit/XwQ3OGJ9I1yOhz_n/images/visual_manual.png?fit=max&auto=format&n=XwQ3OGJ9I1yOhz_n&q=85&s=a9262bd7a7b9b243a3b25163dd6a086b" alt="Taapit Visual manual integration" width="1664" height="822" data-path="images/visual_manual.png" />
</Frame>

## Prérequis

<Warning>
  **Important** : Pour que le suivi des conversions fonctionne, les utilisateurs
  doivent arriver sur votre site via un **deeplink Taapit**. C'est ainsi que
  l'ID de suivi (`ta_tid`) est généré et transmis à votre site.
</Warning>

Avant de commencer :

1. **Créez un deeplink Taapit** pointant vers votre site ou landing page
2. **Activez le suivi des conversions** sur votre lien :
   * Allez dans les paramètres de votre lien dans le dashboard Taapit
   * Activez **Suivi des conversions**
3. **Obtenez votre Secret Key** depuis [Paramètres → Conversion](https://taap.it/dashboard/settings/conversion) dans votre dashboard Taapit

<Warning>
  N'exposez jamais votre **clé secrète** dans le code côté client. Utilisez-la
  uniquement sur votre serveur.
</Warning>

## Installation

<Warning>
  Même pour le suivi côté serveur, vous **devez** installer le SDK sur votre
  frontend pour capturer le cookie `ta_tid`.
</Warning>

<Tabs>
  <Tab title="Package NPM (React/Next.js)">
    ### Étape 1 : Frontend - Installer le SDK

    ```bash theme={null}
    npm install taapit-sdk
    ```

    Ajoutez le composant Analytics pour capturer le `ta_tid` :

    ```tsx app/layout.tsx theme={null}
    import { Analytics } from "taapit-sdk/react";

    export default function RootLayout({ children }) {
      return (
        <html>
          <body>
            {children}
            <Analytics />
          </body>
        </html>
      );
    }
    ```

    ### Étape 2 : Backend - Configurer votre clé API

    ```bash .env theme={null}
    TAAPIT_API_KEY=taapit_sk_xxx
    ```

    <Warning>
      N'exposez jamais votre clé API secrète dans le code côté client.
    </Warning>

    ### Étape 3 : Backend - Suivre les conversions

    ```typescript app/api/signup/route.ts theme={null}
    import { Taapit } from "taapit-sdk";
    import { cookies } from "next/headers";

    const taapit = new Taapit({
      apiKey: process.env.TAAPIT_API_KEY,
    });

    export async function POST(request: Request) {
      const body = await request.json();

      // Obtenir l'ID de suivi depuis le cookie
      const cookieStore = cookies();
      const trackingId = cookieStore.get("ta_tid")?.value;

      // Créer l'utilisateur dans votre base de données
      const user = await db.users.create({
        email: body.email,
        name: body.name,
      });

      // Suivre le lead
      if (trackingId) {
        await taapit.track.lead({
          trackingId,
          customer: {
            externalId: user.id,
            email: user.email,
          },
        });
      }

      return Response.json({ user });
    }
    ```
  </Tab>

  <Tab title="Balise Script + API REST">
    ### Étape 1 : Frontend - Ajouter le script

    ```html theme={null}
    <script src="https://taap.it/api/sdk"></script>
    ```

    ### Étape 2 : Frontend - Envoyer l'ID de suivi au backend

    ```html theme={null}
    <script>
      document
        .getElementById("signup-form")
        .addEventListener("submit", async (e) => {
          e.preventDefault();
          const formData = new FormData(e.target);

          // Inclure l'ID de suivi dans la requête
          await fetch("/api/signup", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({
              email: formData.get("email"),
              name: formData.get("name"),
              trackingId: taapit.getTrackingId(), // Inclure ceci !
            }),
          });
        });
    </script>
    ```

    ### Étape 3 : Backend - Appeler l'API REST

    ```bash theme={null}
    curl -X POST https://track.taap.it/api/events/lead \
      -H "Authorization: Bearer taapit_sk_xxx" \
      -H "Content-Type: application/json" \
      -d '{
        "trackingId": "rLnWe1uz9t282v7g",
        "customer": {
          "externalId": "user_123",
          "email": "john@example.com"
        }
      }'
    ```
  </Tab>
</Tabs>

## Suivre un Lead

<Tabs>
  <Tab title="SDK Node.js">
    ```typescript theme={null}
    import { Taapit } from 'taapit-sdk';
    import { cookies } from 'next/headers';

    const taapit = new Taapit({ apiKey: process.env.TAAPIT_API_KEY });

    export async function POST(request: Request) {
      const body = await request.json();
      const cookieStore = cookies();
      const trackingId = cookieStore.get('ta_tid')?.value || body.trackingId;
      
      // Créer l'utilisateur
      const user = await createUser(body);
      
      // Suivre le lead
      if (trackingId) {
        const result = await taapit.track.lead({
          trackingId,
          customer: {
            externalId: user.id,
            email: user.email,
            firstname: body.firstName,
            lastname: body.lastName,
          },
          metadata: {
            source: 'signup-api',
            plan: body.plan,
          },
        });
        
        if (!result.success) {
          console.error('Échec du suivi du lead:', result.error);
        }
      }
      
      return Response.json({ user });
    }
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import requests

    def track_lead(tracking_id: str, user: dict):
    response = requests.post(
    'https://track.taap.it/api/events/lead',
    headers={
    'Authorization': f'Bearer {TAAPIT_API_KEY}',
    'Content-Type': 'application/json',
    },
    json={
    'trackingId': tracking_id,
    'customer': {
    'externalId': user['id'],
    'email': user['email'],
    },
    },
    )
    return response.json()

    ```
  </Tab>

  <Tab title="PHP">
    ```php theme={null}
    <?php
    function trackLead($trackingId, $user) {
        $ch = curl_init('https://track.taap.it/api/events/lead');

        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_HTTPHEADER => [
                'Authorization: Bearer ' . TAAPIT_API_KEY,
                'Content-Type: application/json',
            ],
            CURLOPT_POSTFIELDS => json_encode([
                'trackingId' => $trackingId,
                'customer' => [
                    'externalId' => $user['id'],
                    'email' => $user['email'],
                ],
            ]),
        ]);

        $response = curl_exec($ch);
        return json_decode($response, true);
    }
    ```
  </Tab>

  <Tab title="Ruby">
    ```ruby theme={null}
    require 'net/http'
    require 'json'

    def track_lead(tracking_id, user)
    uri = URI('https://track.taap.it/api/events/lead')
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true

    request = Net::HTTP::Post.new(uri.path)
    request['Authorization'] = "Bearer #{TAAPIT_API_KEY}"
    request['Content-Type'] = 'application/json'
    request.body = {
    trackingId: tracking_id,
    customer: {
    externalId: user[:id],
    email: user[:email]
    }
    }.to_json

    response = http.request(request)
    JSON.parse(response.body)
    end

    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    func trackLead(trackingID string, user User) error {
        payload := map[string]interface{}{
            "trackingId": trackingID,
            "customer": map[string]string{
                "externalId": user.ID,
                "email":      user.Email,
            },
        }

        body, _ := json.Marshal(payload)
        req, _ := http.NewRequest("POST",
            "https://track.taap.it/api/events/lead",
            bytes.NewBuffer(body))

        req.Header.Set("Authorization", "Bearer "+apiKey)
        req.Header.Set("Content-Type", "application/json")

        client := &http.Client{}
        resp, err := client.Do(req)
        if err != nil {
            return err
        }
        defer resp.Body.Close()

        return nil
    }
    ```
  </Tab>
</Tabs>

## Suivre une Vente

<Info>
  **`trackingId` pour les ventes** : Si le customer a déjà été tracké via un
  **événement lead**, le `trackingId` est optionnel pour les événements de
  vente. Vous n'avez besoin que du `customerExternalId` pour lier la vente au
  customer existant. Si c'est un **nouveau customer** (pas de lead préalable),
  `trackingId` est requis.
</Info>

<Tabs>
  <Tab title="SDK Node.js">
    ```typescript theme={null}
    export async function POST(request: Request) {
      const body = await request.json();
      const cookieStore = cookies();
      const trackingId = cookieStore.get('ta_tid')?.value || body.trackingId;
      
      // Vérifier le paiement
      const order = await verifyPayment(body);
      
      // Suivre la vente
      // trackingId est optionnel si le customer a déjà été tracké via un événement lead
      await taapit.track.sale({
        trackingId, // Optionnel si le customer existe déjà
        customer: {
          externalId: order.userId, // Requis - lie au customer existant ou en crée un nouveau
          email: order.customerEmail,
        },
        amount: order.total,      // ex: 149.99 (PAS en centimes)
        currency: order.currency, // ex: 'eur'
        metadata: {
          orderId: order.id,
          productIds: order.items.map(i => i.productId),
        },
      });
      
      return Response.json({ success: true });
    }
    ```
  </Tab>

  <Tab title="API REST">
    ```bash theme={null}
    # Avec trackingId (nouveau customer ou premier tracking)
    curl -X POST https://track.taap.it/api/events/sale \
      -H "Authorization: Bearer taapit_sk_xxx" \
      -H "Content-Type: application/json" \
      -d '{
        "trackingId": "rLnWe1uz9t282v7g",
        "customer": {
          "externalId": "user_123",
          "email": "john@example.com"
        },
        "amount": 99.99,
        "currency": "eur",
        "metadata": {
          "orderId": "order_456"
        }
      }'

    # Sans trackingId (customer déjà tracké via un événement lead)

    curl -X POST https://track.taap.it/api/events/sale \
     -H "Authorization: Bearer taapit_sk_xxx" \
     -H "Content-Type: application/json" \
     -d '{
    "customer": {
    "externalId": "user_123"
    },
    "amount": 99.99,
    "currency": "eur"
    }'

    ```
  </Tab>
</Tabs>

<Warning>
  Le `amount` doit être en **unités de devise**, pas en centimes.

  * ✅ `amount: 29.99` pour 29,99€
  * ❌ `amount: 2999` (cela serait interprété comme 2999€)
</Warning>

## Référence API

### Endpoints

| Événement | Endpoint                                     |
| --------- | -------------------------------------------- |
| Lead      | `POST https://track.taap.it/api/events/lead` |
| Vente     | `POST https://track.taap.it/api/events/sale` |

### Authentification

```

Authorization: Bearer taapit_sk_xxx

```

### Corps de la requête

```json theme={null}
{
  "trackingId": "rLnWe1uz9t282v7g",
  "customer": {
    "externalId": "user_123",
    "email": "john@example.com",
    "firstname": "John",
    "lastname": "Doe",
    "phoneNumber": "+33612345678",
    "avatarUrl": "https://example.com/avatar.jpg"
  },
  "amount": 99.99,       // Vente seulement
  "currency": "eur",     // Vente seulement
  "metadata": {}
}
```

| Champ                 | Type   | Requis          | Description                  |
| --------------------- | ------ | --------------- | ---------------------------- |
| `trackingId`          | string | Voir ci-dessous | Le `ta_tid` du cookie/URL    |
| `customer.externalId` | string | Oui             | Votre ID utilisateur interne |
| `customer.email`      | string | Non             | Email de l'utilisateur       |
| `amount`              | number | Vente           | Montant en unités de devise  |
| `currency`            | string | Vente           | Code ISO 4217 (eur, usd...)  |
| `metadata`            | object | Non             | Données personnalisées       |

<Info>
  **Quand `trackingId` est-il requis ?** - **Événements lead** : `trackingId`
  est **toujours requis** - **Événements vente** : - Si le `customerExternalId`
  a déjà été tracké (via un événement lead précédent), `trackingId` est
  **optionnel** - Si c'est un nouveau customer (pas d'événement lead préalable),
  `trackingId` est **requis** pour créer l'enregistrement client
</Info>

### Réponse

```json theme={null}
{ "ok": true }
```

## Bonnes pratiques

### 1. Récupérer l'ID de suivi de plusieurs sources

```typescript theme={null}
const cookieStore = cookies();
const trackingId =
  cookieStore.get("ta_tid")?.value || // Cookie (préféré)
  body.trackingId || // Corps de la requête
  new URL(request.url).searchParams.get("ta_tid"); // Paramètre URL
```

### 2. Toujours suivre après confirmation

```typescript theme={null}
// ✅ Bien - Suivre après confirmation du paiement
const paymentResult = await processPayment();
if (paymentResult.success) {
  await taapit.track.sale({...});
}

// ❌ Mal - Suivre avant confirmation
await taapit.track.sale({...});
const paymentResult = await processPayment(); // Pourrait échouer !
```

### 3. Stocker l'ID de suivi pour une utilisation ultérieure

```typescript theme={null}
// Lors de la création d'une session checkout
const session = await stripe.checkout.sessions.create({
  metadata: { ta_tid: trackingId }, // Stocker pour le webhook
});

// Plus tard dans le webhook, le récupérer
const trackingId = session.metadata.ta_tid;
```

### 4. Logger les échecs de tracking

```typescript theme={null}
const result = await taapit.track.sale({...});
if (!result.success) {
  console.error('Échec du tracking Taapit:', result.error);
  // Ne pas faire échouer l'opération principale - le tracking est secondaire
}
```

## Prochaines étapes

<CardGroup cols={2}>
  <Card title="Intégration Stripe" icon="stripe" href="/fr/conversions/automatic/stripe">
    Suivi automatique pour Stripe (encore plus simple).
  </Card>

  <Card title="API Track Lead" icon="code" href="/fr/api-reference/events/lead">
    Documentation complète de l'API pour les leads.
  </Card>

  <Card title="API Track Sale" icon="code" href="/fr/api-reference/events/sale">
    Documentation complète de l'API pour les ventes.
  </Card>
</CardGroup>
