Angular
Angular a un wrapper dédié : @vskstudio/takt-angular (provider, service, directive, composants badge/embed, web component), bâti sur le cœur @vskstudio/takt-core. APIs standalone pour Angular 17+.
pnpm add @vskstudio/takt-angular @vskstudio/takt-core @vskstudio/takt-core est une dépendance peer : depuis la 0.8.0, le wrapper exige >=0.10.0.
Le package est entièrement typé et sûr au SSR : côté serveur, provideTakt est inerte et TaktService no-ope. Il expose deux points d’entrée :
@vskstudio/takt-angular:provideTakt(), le helperrouteTemplateFromSnapshot(), leTaktServiceinjectable, la directive[taktEvent], les composantsTaktBadgeComponent/TaktEmbedComponentet le tokenTAKT_CONFIG. Il réexporte aussicreateStats,badgeUrl,embedUrl,PublicApiError,optOut,optInetisOptedOutdu cœur.@vskstudio/takt-angular/element: le web component<takt-analytics>autonome, pour du HTML pur.
Setup avec provideTakt()
Enregistre Takt une seule fois au bootstrap avec provideTakt. Il ne boote que dans le navigateur, émet le pageview initial, câble l’autocapture demandée et libère tout quand l’application est détruite.
import { bootstrapApplication } from '@angular/platform-browser'
import { provideTakt } from '@vskstudio/takt-angular'
import { AppComponent } from './app/app.component'
bootstrapApplication(AppComponent, {
providers: [
provideTakt({
// domain par défaut = location.hostname, endpoint = https://taktlytics.com/api/event
outbound: true, // suit les liens sortants
files: true // suit les téléchargements (ou passe ['pdf', 'zip'])
// spa: true, respectDnt: true, excludeLocalhost: true (défauts)
})
]
}) Options de TaktConfig :
| Option | Type | Défaut | Rôle |
|---|---|---|---|
domain | string | location.hostname | Identifiant du site |
endpoint | string | https://taktlytics.com/api/event | URL d’ingestion. Passe /api/event pour un proxy first-party same-origin. |
scriptOrigin | string | aucun | Origine first-party dont dériver l’endpoint ({origin}/api/event) ; endpoint l’emporte |
outbound | boolean | false | Suit les liens sortants |
files | boolean \| string[] | false | Suit les téléchargements (liste d’extensions optionnelle) |
spa | boolean | true | Suit la navigation client (pageviews auto) |
track404 | boolean | false | Signale un événement 404 sur les pages d’erreur (marqueur [data-takt-404] / <meta name="takt:404">, ou statut HTTP 404). |
tagged | boolean | false | Events custom depuis les éléments [data-takt-event] |
respectDnt | boolean | true | Respecte Do Not Track |
excludeLocalhost | boolean | true | Ignore localhost / IP privées |
enabled | boolean | true | Coupe tout envoi quand false (l’emporte sur le reste) |
sampleRate | number | 1 | Échantillonne les events envoyés (0 à 1) |
trackQuery | boolean | false | Conserve la query string telle quelle |
queryParams | string[] | aucun | Allowlist de paramètres de query à garder |
exclude | string[] | aucun | Préfixes de chemin jamais suivis, ex. ['/app', '/account'] (borné au segment) |
scrubUrl | (url) => url | aucun | Nettoyage d’URL sur mesure (page, referrer, url des liens sortants et des téléchargements, path des 404 ; config seulement) |
debug | boolean | false | Trace chaque payload dans la console avant l’envoi |
redactRoutes | string[] | [] | Motifs de routes envoyés à la place du chemin réel, ex. ['/verify/:token'] (voir Masquage de routes) |
redactUndecodablePaths | boolean | true | Non exposée par ce wrapper : se règle sur le SDK core (init() / createTakt()), voir Chemins illisibles |
routeTemplates | boolean | false | Envoie chaque page sous la forme de son gabarit de route ; exige routeTemplate |
routeTemplate | () => string \| null \| undefined | aucun | Renvoie le gabarit de la route courante. S’exécute dans le contexte d’injection, peut donc faire inject(Router) |
La sémantique de ces réglages est détaillée dans Configuration.
Masquage de routes
La query string est retirée par défaut, mais le chemin part en clair : /verify/abc123 transmet le jeton. Liste les routes sensibles dans redactRoutes : un chemin qui correspond part sous la forme de son motif, tous les autres gardent leur valeur réelle.
provideTakt({
redactRoutes: ['/verify/:token', '/invoices/:id']
}) /verify/abc123 part alors comme /verify/:token. Les motifs acceptent la syntaxe Angular (:param, :param?, *, **) ainsi que [param], [[optionnel]], [...reste] et (groupe). La règle couvre l’URL de la page, le referrer du même site, les liens sortants et les téléchargements, et le chemin des 404.
Pour une application entièrement privée, routeTemplates: true envoie chaque page sous la forme de son gabarit (/users/42 devient /users/:id). Donne-lui un résolveur routeTemplate : provideTakt l’exécute via runInInjectionContext, il peut donc faire inject(Router), et routeTemplateFromSnapshot transforme l’instantané du routeur en gabarit.
import { inject } from '@angular/core'
import { provideRouter, Router } from '@angular/router'
import { provideTakt, routeTemplateFromSnapshot } from '@vskstudio/takt-angular'
bootstrapApplication(AppComponent, {
providers: [
provideRouter(routes),
provideTakt({
routeTemplates: true,
routeTemplate: () => routeTemplateFromSnapshot(inject(Router).routerState.snapshot.root)
})
]
}) routeTemplateFromSnapshot suit firstChild depuis la racine, joint les routeConfig.path non vides (les routes de layout en path: '' sont ignorées) et renvoie / quand aucun n’est défini. Dans ce mode, le pageview initial attend que l’application soit stable, pour que la navigation initiale ait trouvé sa route avant la lecture du gabarit. Quand le résolveur ne renvoie rien, redactRoutes s’applique quand même, sinon le chemin réel part. Le package ne dépend pas de @angular/router : le helper ne lit que la forme de l’instantané.
Sur un site public, préfère redactRoutes : routeTemplates fusionne tous les articles en une seule ligne. Détails dans Vie privée.
TaktService
Injecte TaktService n’importe où pour émettre des events impérativement. Aucune méthode ne lève avant l’init ou côté serveur : track() et pageview() sont alors sans effet et émettent un console.warn unique. Les méthodes de consentement optOut(), optIn() et isOptedOut(), elles, fonctionnent toujours (voir Consentement).
import { Component, inject } from '@angular/core'
import { TaktService } from '@vskstudio/takt-angular'
@Component({ /* ... */ })
export class CheckoutComponent {
private readonly takt = inject(TaktService)
buy() {
this.takt.track('Purchase', {
props: { plan: 'pro' },
revenue: { amount: '29.00', currency: 'EUR' }
})
}
// takt.pageview(), takt.optOut(), takt.optIn(), takt.isOptedOut() et takt.instance sont aussi dispo.
} Consentement
Le consentement marche avant que provideTakt() ait démarré, et même sur une page qui ne l’installe pas : TaktService.optOut(), optIn() et isOptedOut() agissent directement sur le choix stocké, tout comme les fonctions optOut, optIn et isOptedOut exportées par le package. Une bannière de consentement peut donc s’afficher en premier, et l’instance créée ensuite respecte le choix.
import { Component, signal } from '@angular/core'
import { isOptedOut, optIn, optOut } from '@vskstudio/takt-angular'
@Component({
selector: 'app-analytics-toggle',
standalone: true,
template: `<button (click)="toggle()">{{ blocked() ? 'Activer la mesure' : 'Désactiver la mesure' }}</button>`
})
export class AnalyticsToggleComponent {
readonly blocked = signal(isOptedOut())
toggle() {
if (this.blocked()) optIn()
else optOut()
this.blocked.set(isOptedOut())
}
} Directive [taktEvent]
Pour du suivi de clic déclaratif, la directive taktEvent résout l’instance active au moment du clic. Importe-la dans un composant standalone :
import { TaktEventDirective } from '@vskstudio/takt-angular'
@Component({
standalone: true,
imports: [TaktEventDirective],
template: `
<button
taktEvent="Signup"
[taktProps]="{ plan: 'pro' }"
[taktRevenue]="{ amount: '29.00', currency: 'EUR' }"
>
S'inscrire
</button>
`
})
export class SignupComponent {} Widgets
Deux composants standalone affichent les widgets publics d’un site : TaktBadgeComponent (<takt-badge>, l’image SVG rendue par le serveur) et TaktEmbedComponent (<takt-embed>, le mini-tableau de bord en iframe). Ils demandent un site public et vérifié.
import { TaktBadgeComponent, TaktEmbedComponent } from '@vskstudio/takt-angular'
@Component({
standalone: true,
imports: [TaktBadgeComponent, TaktEmbedComponent],
template: `
<takt-badge domain="exemple.fr" variant="d"></takt-badge>
<takt-embed domain="exemple.fr" theme="dark"></takt-embed>
`
})
export class StatsPubliquesComponent {} domain est requis. Le badge accepte en plus variant, glyph, lang, host et alt ; l’embed theme, lang, host, width, height et title. host pointe l’adresse de Takt (par défaut https://taktlytics.com). Renseigne-le si tu sers les widgets depuis un domaine personnalisé. Pour lire les mêmes chiffres en TypeScript, le paquet réexporte createStats, badgeUrl, embedUrl et PublicApiError du cœur.
Web component <takt-analytics>
Pour des pages non-Angular (ou un simple <script>), utilise l’élément <takt-analytics> autonome. spa, respect-dnt et exclude-localhost sont actifs par défaut : mets-les à "false" pour les couper. outbound, files, track404 et tagged sont des drapeaux de présence : l’attribut seul suffit à les activer.
import { defineTaktElement } from '@vskstudio/takt-angular/element'
defineTaktElement() // s'exécute aussi automatiquement à l'import <takt-analytics domain="exemple.fr" outbound files></takt-analytics> Attributs reconnus :
| Attribut | Valeur | Rôle |
|---|---|---|
domain | chaîne | Identifiant du site |
endpoint | chaîne | URL d’ingestion |
script-origin | chaîne | Origine first-party dont dériver l’endpoint |
spa | "false" pour couper | Suit la navigation client (pageviews auto) |
respect-dnt | "false" pour couper | Respecte Do Not Track |
exclude-localhost | "false" pour couper | Ignore localhost / IP privées |
enabled | "false" pour couper | Coupe tout envoi |
sample-rate | nombre | Échantillonne les events envoyés (0 à 1) |
track-query | présence | Conserve la query string telle quelle |
query-params | liste séparée par des virgules | Allowlist de paramètres de query à garder |
exclude | liste séparée par des virgules | Préfixes de chemin jamais suivis |
redact-routes | liste séparée par des virgules | Motifs de routes envoyés à la place du chemin réel, ex. redact-routes="/verify/:token, /reset/:code" |
outbound | présence | Suit les liens sortants |
files | présence | Suit les téléchargements (pas de liste d’extensions ici) |
track404 | présence | Signale un événement 404 sur les pages d’erreur |
tagged | présence | Events custom depuis les éléments [data-takt-event] |
debug | présence, "false" pour couper | Trace chaque payload dans la console avant l’envoi |
scrubUrl n’a pas d’équivalent en attribut : passe par provideTakt() pour une réécriture d’URL sur mesure. L’élément n’a pas de routeur, il ne gère donc pas routeTemplates.
Via CDN (embarque le cœur, aucun build) :
<script type="module" src="https://unpkg.com/@vskstudio/takt-angular"></script>
<takt-analytics></takt-analytics> provideTakt renvoie des EnvironmentProviders : installe-le au bootstrap. TAKT_CONFIG est un InjectionToken portant la config résolue, si tu as besoin de la lire ailleurs.