# SDK serveur PHP et Laravel

URL: https://traqio.app/fr/docs/sdks/php
Last updated: 2026-10-16

Signalez inscriptions et achats depuis un backend PHP ou Laravel avec traqio/traqio-php, rattachés à leur clic publicitaire. Auto-découvert dans Laravel.

`traqio/traqio-php` est le SDK Traqio pour les backends PHP et Laravel — la moitié serveur du SDK web de Traqio. La conversion qui compte sur un site — une inscription, un abonnement, un achat — a lieu sur votre backend, là où l’id utilisateur est connu. Ce paquet la signale avec le **trackID**, le click id de la publicité que [@traqio/web](https://traqio.app/fr/docs/sdks/web) a gardé en stockage first-party depuis la page d’arrivée, et Traqio crédite la campagne qui a amené l’utilisateur — [de façon déterministe](https://traqio.app/fr/docs/concepts/web-attribution), par l’id de ce clic. Aucune dépendance au-delà d’`ext-curl` ; auto-découvert dans Laravel.

## Prérequis

- PHP 8.1 ou plus, avec `ext-curl` et `ext-json`. Laravel 12 ou 13 pour l’intégration auto-découverte ; sinon PHP seul, Symfony ou tout framework PSR-7.
- Une **clé serveur** pour le produit (`tq_sk_…`). Ni la clé SDK de l’app ni une clé web ne fonctionnent ici.
- [@traqio/web](https://traqio.app/fr/docs/sdks/web) sur le site, et des publicités qui pointent vers des [liens de tracking](https://traqio.app/fr/docs/concepts/tracking-links) avec une destination site web — c’est ainsi que le trackID arrive jusqu’à votre formulaire d’inscription.

## Mise en place

### Créer une clé serveur

Dans la console, ouvrez **Intégrations → SDK** et créez une **clé serveur**. Elle n’est affichée qu’une fois : placez-la dans `.env`, jamais dans le code ni dans une page. Traqio n’en garde qu’une empreinte ; une clé perdue est remplacée par une nouvelle, et l’ancienne révoquée.

.env:
```bash
TRAQIO_SECRET_KEY=tq_sk_...
```

### Installer le paquet

```bash
composer require traqio/traqio-php
```

Tant que le paquet n’est pas sur Packagist, ajoutez le dossier que nous vous envoyons comme dépôt de type path :

```bash
# the folder you received, committed inside the backend's repository
composer config repositories.traqio path ./vendor-src/traqio-php
composer require traqio/traqio-php:@dev
```

### Configurer le client

**Laravel** : rien à écrire — le service provider et la façade `Traqio` sont découverts, et lisent `TRAQIO_SECRET_KEY`. Pour changer l’endpoint, le timeout ou les nouvelles tentatives, publiez le fichier de configuration :

```bash
php artisan vendor:publish --tag=traqio-config
```

**PHP seul** : un client, construit une fois.

```php
use Traqio\Traqio;

$traqio = new Traqio(getenv('TRAQIO_SECRET_KEY'));
```

### Signaler l’inscription avec son trackID

Appelez `signup()` une fois, là où le compte est créé. @traqio/web écrit le trackID dans le cookie `traq_click` sur votre propre domaine : le navigateur l’envoie donc avec la requête d’inscription, et `TrackId::fromRequest()` le lit.

Laravel:
```php
use Illuminate\Http\Request;
use Traqio\Laravel\Facades\Traqio;
use Traqio\TraqioException;
use Traqio\TrackId;

public function store(Request $request)
{
    $user = User::create($request->validated());

    try {
        // Reads the raw Cookie header: Laravel's cookie decryption would drop traq_click.
        Traqio::signup((string) $user->id, TrackId::fromRequest($request));
    } catch (TraqioException $e) {
        report($e); // never fail the sign-up itself
    }

    return redirect('/welcome');
}
```

PHP:
```php
use Traqio\TrackId;

$user = $users->create($_POST);
$result = $traqio->signup((string) $user->id, TrackId::fromRequest()); // the current request
```

Dans Laravel, pour sortir l’appel de la requête, exécutez-le une fois la réponse envoyée :

```php
dispatch(fn () => Traqio::signup((string) $user->id, $trackId))->afterResponse();
```

Si le backend est sur un autre domaine que le site, le cookie ne lui parvient pas : envoyez plutôt `Traqio.getTrackId()` depuis le navigateur avec le formulaire. L’inscription est le moment où l’utilisateur est **acquis** ; le dernier clic qui la précède, dans votre [fenêtre d’attribution](https://traqio.app/fr/docs/concepts/attribution-windows), reçoit le crédit.

### Suivre les conversions

```php
Traqio::track((string) $user->id, 'purchase', [
    'value' => 49,
    'currency' => 'EUR',
    'transactionId' => $paymentIntent->id, // one payment, one row — whoever reports it
    'store' => 'stripe',
]);
```

Les conversions suivent l’utilisateur : elles sont créditées à la campagne qui l’a acquis.

## Ce que dit la réponse

```php
$result = Traqio::signup((string) $user->id, $trackId);

$result->trackId;                 // "matched" | "unknown" | "expired" | "claimed" | "refused" | null
$result->acquired;                // true: the sign-up is recorded
$result->attribution->network;    // "meta", "tiktok"… or "organic"
$result->attribution->campaignId; // the campaign that brought the user
```

| trackId | Signification |
| --- | --- |
| matched | Le clic appartient désormais à cet utilisateur. Une nouvelle tentative répond de nouveau matched. |
| unknown | Aucun clic de ce produit n’a cet id — une faute de frappe, le lien d’un autre produit, ou une valeur que @traqio/web n’a pas écrite. |
| expired | Le clic est plus ancien que la fenêtre d’attribution du produit. |
| claimed | Un autre utilisateur, ou une installation d’app, possède déjà ce clic. Un clic crédite une seule identité. |
| refused | Le clic a échoué à une règle anti-fraude (il est passé par un réseau d’anonymisation). Il est compté, jamais crédité. |

## Ce qu’il fait aujourd’hui, et ce qu’il ne fait pas

|  | Aujourd’hui |
| --- | --- |
| Rattacher une inscription à son clic, et dire qui a été crédité | Oui — dans la réponse |
| Enregistrer les achats avec valeur, devise et id de paiement, dédoublonnés | Oui |
| Laisser intacts les installations, revenus et ROAS de vos apps | Oui — jamais rattachés à une installation d’app |
| Afficher les conversions web dans les rapports de la console | Oui — par campagne, à côté des installations |
| Envoyer les conversions web à Meta ou TikTok | Pas encore |

Les conversions envoyées ici apparaissent dans **Événements en direct**, marquées comme non rapprochées d’une installation — c’est normal pour un site web. Une inscription créditée à une campagne est comptée dans le rapport ROAS comme une conversion web de cette campagne, à côté de ses installations, et la réponse de chaque appel vous donne l’attribution tout de suite.

## Erreurs et nouvelles tentatives

Une erreur réseau, un timeout, un `429` ou un `5xx` est retenté — deux fois par défaut, avec le même corps, donc rien n’est compté deux fois. Un `4xx` (clé erronée ou révoquée, payload invalide) n’est pas retenté. Les deux se terminent par une `Traqio\TraqioException` :

```php
use Traqio\TraqioException;

try {
    Traqio::signup((string) $user->id, $trackId);
} catch (TraqioException $e) {
    // $e->status: 401 = wrong or revoked key, 400 = invalid payload, null = network
    Log::warning($e->getMessage(), ['status' => $e->status, 'body' => $e->body]);
}
```

> **Signalez après votre propre écriture** Appelez Traqio une fois le compte ou le paiement enregistré, et ne laissez jamais une erreur Traqio le faire échouer.

## Référence de l’API

config/traqio.php:
```php
// config/traqio.php
return [
    'secret_key'  => env('TRAQIO_SECRET_KEY'),                       // required
    'endpoint'    => env('TRAQIO_ENDPOINT', 'https://api.traqio.app'),
    'timeout'     => (float) env('TRAQIO_TIMEOUT', 10),               // seconds per attempt
    'max_retries' => (int) env('TRAQIO_MAX_RETRIES', 2),              // network error, 429, 5xx
];
```

| Méthode | Ce qu’elle fait |
| --- | --- |
| signup($userId, $trackId = null, $events = []) | Signale l’inscription — l’acquisition — avec son trackID. La première est conservée. |
| track($userId, $name, $properties = []) | Enregistre une conversion : value, currency, transactionId, store, eventId, trackId. |
| send($input) | L’appel brut derrière les deux, pour plusieurs événements à la fois. |
| TrackId::fromRequest($request = null) | Le trackID tiré d’une requête Laravel, Symfony ou PSR-7 — ou de la requête PHP courante — ou null. |

En PHP seul, les mêmes options sont le second argument du constructeur : `endpoint`, `timeout`, `max_retries`, et `transport` pour faire passer les requêtes par votre propre client HTTP.

> **Niveau de preuve** Testé avec PHPUnit — l’intégration Laravel sur Laravel 12 et 13, le client sur PHP 8.1 et 8.5 — et exécuté de bout en bout contre une API Traqio en fonctionnement : une inscription portant un trackID est revenue matched avec sa campagne, un second utilisateur revendiquant le même clic a reçu claimed, une clé erronée a été refusée. Pas encore exécuté dans le backend de production d’un client.

## Questions fréquentes

**Pourquoi $request->cookie('traq_click') renvoie-t-il null dans Laravel ?**
Laravel chiffre ses cookies et les déchiffre à chaque requête ; un cookie écrit en JavaScript — celui que pose @traqio/web — échoue à ce déchiffrement, et Laravel renvoie donc null. TrackId::fromRequest lit à la place l’en-tête Cookie brut, auquel le déchiffrement ne touche jamais. Inutile d’ajouter traq_click aux exceptions d’EncryptCookies.

**Quelles versions de Laravel sont prises en charge ?**
Laravel 12 et 13, par l’auto-découverte des paquets : le service provider, le fichier de configuration et la façade Traqio s’enregistrent seuls. Le client lui-même est du PHP 8.1+ pur et fonctionne dans Symfony, Slim ou toute application PSR-7.

**Et si le visiteur ne vient pas d’une publicité ?**
TrackId::fromRequest renvoie null et l’inscription est quand même enregistrée, comme organique : aucune campagne n’est créditée.

**Une nouvelle tentative compte-t-elle un achat deux fois ?**
Non. Chaque appel génère ses ids d’événement une seule fois et renvoie exactement le même corps, et un achat est aussi identifié par son transactionId : le même paiement signalé deux fois est stocké une fois.
