Symfony
Le bridge Symfony vskstudio/takt-symfony expose le cœur PHP sous forme de bundle : une fonction Twig pour le snippet et un service Takt autowiré pour le S2S. Compatible Symfony 6.4 / 7.x, PHP 8.1+.
composer require vskstudio/takt-symfony Le paquet n’expose pas de recette Flex : enregistre le bundle à la main.
// config/bundles.php
return [
// …
Vskstudio\Takt\Symfony\TaktBundle::class => ['all' => true],
]; Le TaktBundle enregistre ensuite ses services depuis la config sémantique : le SnippetRenderer derrière la fonction Twig, et le client S2S Takt. Ce dernier est RequestStack-aware : il forwarde l’IP et l’User-Agent de la requête courante pour l’attribution.
Cette page est la référence des options. Pour l’intégration de bout en bout et ses pièges — placement du snippet sous Turbo, arbitrage contrôleur de retour / webhook pour les conversions — voir le guide analytics sans cookie dans une application Symfony.
Configuration
config/packages/takt.yaml :
takt:
domain: 'exemple.fr'
endpoint: 'https://taktlytics.com/api/event' # voir « La clé endpoint » ci-dessous
api_key: '%env(TAKT_API_KEY)%' # S2S uniquement — omets la clé sinon
mode: inline
outbound: true
files: true
tagged: true
not_found: true
file_extensions: ['pdf', 'zip'] Un %env(...)% doit correspondre à une variable déclarée : sans elle, le conteneur lève EnvNotFoundException sur toutes les pages qui rendent le snippet.
# .env
TAKT_API_KEY=tk_… Référence des clés
| Clé | Défaut | Rôle |
|---|---|---|
domain | '' | Domaine du site (attribut data-domain, et domaine porté par chaque event S2S) |
endpoint | https://taktlytics.com | Cible d’ingestion — deux contrats distincts, voir ci-dessous |
script_origin | null | Origine first-party qui sert le runtime et dont l’endpoint est dérivé (contourne les ad-blockers) ; endpoint prime |
api_key | null | Clé d’API scope=ingest — utilisée uniquement par le client S2S |
mode | inline | Source du runtime : inline, cdn, asset ou sdk |
outbound | false | Suit les liens sortants (token outbound) |
files | false | Suit les téléchargements (token downloads) |
tagged | false | Suit les éléments marqués data-takt-event (token tagged) |
not_found | false | Suit les pages 404 (token 404) |
file_extensions | [] | Restreint les téléchargements comptés ; vide = liste par défaut du tracker |
exclude_localhost | true | Ignore les hits émis depuis localhost — la raison la plus fréquente d’un « rien ne remonte » en dev |
nonce | null | Nonce CSP posé sur la balise <script> (indispensable en mode: inline sous CSP stricte) |
sample_rate | null | N’envoie qu’une fraction (0–1) des hits |
track_query | null | Conserve la query string + le hash (défaut : strippés) |
query_params | [] | Allowlist de paramètres conservés quand track_query est off |
exclude | [] | Préfixes de chemins jamais suivis — requiert mode: sdk |
respect_dnt | null | false cesse de respecter Do-Not-Track |
enabled | null | false = coupe-circuit, snippet no-op |
scrub_url | null | Fonction JS brute de réécriture d’URL — requiert mode: sdk |
Les cinq dernières options avancées valent null par défaut (« non définie » : le défaut du tracker s’applique) ; ne les pose que pour une valeur non-défaut, sample_rate: 0.5 jette la moitié du trafic et enabled: false coupe toute la mesure.
Les modes :
inline— embarque le bundletakt.auto.jsvendoré dans la balise (zéro requête en plus).cdn— loader<script defer src="https://cdn.jsdelivr.net/npm/@vskstudio/[email protected]/dist/takt.auto.js">.asset— loader vers/takt/takt.auto.js, une copie que tu héberges toi-même (voir le callout en fin de page).sdk—<script type="module">qui boote le SDK complet.
mode n’est pas validé : une valeur inconnue retombe silencieusement sur inline.
La clé endpoint
La même clé alimente deux consommateurs qui n’attendent pas la même forme :
- snippet Twig — la valeur est rendue telle quelle en
data-endpoint, et le tracker y POSTe : il lui faut une URL d’ingestion complète ; - service
Takt(S2S) — la valeur est une origine de base, à laquelle/api/eventest ajouté à chaque envoi.
Valeur d’endpoint | Le snippet POSTe sur | Le service S2S POSTe sur |
|---|---|---|
https://taktlytics.com (défaut) | https://taktlytics.com | https://taktlytics.com/api/event |
https://taktlytics.com/api/event | https://taktlytics.com/api/event | https://taktlytics.com/api/event/api/event |
/api/event (proxy same-origin) | /api/event sur ton domaine | chemin relatif : aucun envoi n’aboutit |
Aucune valeur ne satisfait les deux usages à la fois. Règle-la selon ce que tu utilises :
- snippet seul —
endpoint: 'https://taktlytics.com/api/event'pour la collecte hébergée, ou'/api/event'si tu proxifies l’ingestion en first-party depuis ton propre domaine ; - S2S seul — garde le défaut
https://taktlytics.com; - les deux dans la même application — règle
endpointpour le snippet et redéclare le client S2S avec l’origine nue :
# config/services.yaml
services:
Vskstudio\Takt\Takt:
factory: ['Vskstudio\Takt\Symfony\TaktFactory', 'create']
arguments:
- 'https://taktlytics.com'
- 'exemple.fr'
- '%env(TAKT_API_KEY)%'
- '@request_stack' script_origin ne sert à dériver l’endpoint du snippet que si endpoint vaut exactement https://taktlytics.com/api/event : le tracker POSTe alors sur {script_origin}/api/event. Avec toute autre valeur, l’endpoint est émis en data-endpoint et prime.
mode: sdk
mode: sdk charge le SDK en module ES. C’est le seul mode capable d’exprimer scrub_url, une fonction JS brute de réécriture d’URL injectée verbatim dans la page, et exclude, les préfixes de chemins jamais suivis. Le snippet minimal n’embarque ni l’un ni l’autre : les poser dans un autre mode lève une exception au rendu plutôt que de les laisser filer silencieusement. Réserve scrub_url au dev : ne la construis jamais à partir d’entrées utilisateur.
takt:
mode: sdk
exclude: ['/app', '/compte']
scrub_url: "(u) => u.split('#')[0]" Fonction Twig takt()
Rends le snippet dans le <head> de ton template de base :
<head>
<meta charset="utf-8">
{{ takt() }}
</head> takt() ne prend aucun argument : l’autocapture (outbound, files, tagged, not_found) et toutes les autres options se règlent uniquement dans config/packages/takt.yaml. Un argument passé depuis un template est ignoré sans erreur — il n’y a pas de surcharge par template.
Service Takt autowiré (serveur-à-serveur)
Type-hinte simplement Vskstudio\Takt\Takt — l’autowiring fait le reste :
namespace App\Controller;
use Symfony\Component\HttpFoundation\Response;
use Vskstudio\Takt\Revenue;
use Vskstudio\Takt\Takt;
final class CheckoutController
{
public function __construct(private readonly Takt $takt) {}
public function success(): Response
{
$this->takt->event('Purchase', ['plan' => 'pro'], new Revenue(amount: '29', currency: 'EUR'));
return new Response('Merci');
}
} L’envoi est fire-and-forget : un 202 vaut succès, et les erreurs de transport sont avalées pour ne jamais casser la requête. $this->takt->strict() renvoie une instance qui lève sur tout statut différent de 202 (utile en test). pageview() et withVisitor() sont détaillés sur la page cœur PHP.
Request::getClientIp(), qui n'honore X-Forwarded-For que si framework.trusted_proxies est configuré. Derrière un CDN ou un reverse proxy non déclaré, tous les events S2S sont attribués à l'IP du proxy.mode: asset, le loader pointe vers /takt/takt.auto.js, mais le bundle ne publie aucun asset : copie toi-même vendor/vskstudio/takt-core-php/resources/takt.auto.js dans public/takt/takt.auto.js. En mode: sdk avec script_origin, le module est chargé depuis /takt/takt.esm.js sur cette origine — ce fichier n'est pas vendoré non plus, c'est à toi de le servir.