# Bien démarrer Lunetric relie vos sources de trafic aux actions et aux paiements. Une seule installation du tracker suffit pour les pages vues et les navigations SPA. ## Le chemin le plus court 1. Créez votre compte et ajoutez votre domaine. 2. Dans **Configuration → Installation**, copiez le prompt et donnez-le à votre assistant dans le dépôt de votre site. 3. Configurez les secrets côté serveur et les services externes indiqués à la fin du prompt. 4. Ouvrez votre site, acceptez la collecte et vérifiez la première visite dans Lunetric. [Installer le tracker](/docs/installation) · [Relier Stripe](/docs/stripe) · [Connecter un assistant](/docs/mcp) ## Comprendre les données Les revenus sont stockés en unités mineures : `4900` représente `49 EUR`. Les paiements sont attribués au premier contact connu dans les 90 jours précédents. Un paiement sans visite correspondante reste non attribué. La carte affiche les actions reçues récemment. Le mode démo est une simulation en lecture seule ; il ne peut pas collecter les visites de votre site. [Comprendre l’attribution des revenus](/docs/attribution) · [Mesurer le trafic IA et la GEO](/docs/geo) ## Pour les assistants La documentation est également disponible en [Markdown complet](/llms-full.txt), avec un [index compact](/llms.txt). Le [MCP](/docs/mcp) permet de lire les mesures d'un site et de contrôler sa réception de données. # Installation ## Installer avec un prompt Dans **Configuration → Installation**, copiez le prompt personnalisé. Il contient votre domaine, la clé publique de collecte et les étapes nécessaires. Donnez-le à un assistant qui peut modifier le dépôt de votre site. L'assistant doit adapter le code au framework existant, tester le consentement et signaler les étapes externes restantes. Il ne peut pas créer des comptes ou deviner vos secrets. La documentation décrit le protocole ; votre prompt contient les valeurs propres à votre site. ## Installation manuelle Placez ce script une seule fois dans le document global, avant la fermeture du `head`. Remplacez l'origine et la clé avec celles affichées dans votre espace. ```html ``` Attendez que le script soit chargé et que le visiteur ait accepté la collecte avant d'appeler : ```js window.lunetric.grantConsent(); ``` Branchez aussi le consentement déjà enregistré par votre gestionnaire. Lors du retrait : ```js window.lunetric.revokeConsent(); ``` Les pages vues et navigations SPA sont suivies automatiquement. N'ajoutez pas un second appel manuel sur chaque changement de route. ## Vérifier * Sans consentement, aucune visite ne doit être collectée. * Après consentement, la requête `/collect` doit être acceptée et la visite apparaître dans Lunetric. * Une navigation SPA produit une nouvelle page vue, sans doublon. * Le domaine doit figurer parmi les domaines autorisés dans Configuration. * Après retrait, la collecte s'arrête. Le tracker utilise localStorage. La clé publique peut être dans le HTML ; une clé d'API serveur ne doit jamais être dans le navigateur. # Événements et visiteurs ## Actions réelles Déclenchez un événement après l'action correspondante, sans dupliquer les appels lors des rendus React. ```js window.lunetric.track('signup', { plan: 'studio' }); ``` Pour mesurer un clic : ```html ``` Les propriétés sont limitées à dix. Ne transmettez pas d'email, de mot de passe ou d'autres données personnelles dans ces propriétés. ## Identifiants Après consentement, transmettez ces identifiants au backend existant si nécessaire. Ils peuvent être `null` avant l'activation. ```js const visitorId = window.lunetric.getVisitorId(); const sessionId = window.lunetric.getSessionId(); ``` L'identification s'effectue côté serveur avec une clé d'écriture : ```http POST /v1/identify Authorization: Bearer VOTRE_CLE_ECRITURE Content-Type: application/json {"visitor_id":"ID_VISITEUR","user_id":"ID_CLIENT","name":"Camille"} ``` ## Funnels Le dashboard propose un funnel de pages, objectifs et paiements. Les étapes sont ordonnées, de deux à huit. Le MCP `get_funnel` accepte des étapes `pageview`, `goal` et `payment` ; une page utilise son chemin ou `*`, un paiement utilise `*`. # Paiements et Stripe ## Relier une session Checkout Récupérez l'identifiant visiteur après consentement et transmettez-le à votre backend. Ajoutez les metadata à la session Stripe Checkout créée côté serveur : ```js metadata: { lunetric_visitor_id: visitorId, lunetric_user_id: userId } ``` N'envoyez pas de valeur `null` dans les metadata. Si l'identifiant manque, continuez le paiement normalement : il restera non attribué. Validez les champs client ; ces identifiants ne remplacent pas l'authentification de votre application. ## Webhook signé Dans Stripe, créez un endpoint avec l'URL affichée dans **Configuration → Intégrations**, sous la forme : ```text https://analytics.votre-domaine.com/webhooks/stripe/VOTRE_SITE_ID ``` Sélectionnez `checkout.session.completed` et `checkout.session.async_payment_succeeded`. Enregistrez le secret de signature `whsec_…` dans Lunetric. Gardez des endpoints et secrets distincts pour la sandbox et la production. Le serveur vérifie la signature et traite uniquement les paiements confirmés. Un clic, une page de succès ou une session non payée ne crée pas de revenu. Les répétitions de webhooks sont dédupliquées. ## Autre prestataire Depuis votre backend après confirmation : ```http POST /v1/payments Authorization: Bearer VOTRE_CLE_ECRITURE Content-Type: application/json {"transaction_id":"order_001","amount_minor":4900,"currency":"EUR","visitor_id":"ID_VISITEUR"} ``` La référence doit être unique pour ce paiement. Le montant est en unités mineures. La devise ne mélange pas automatiquement les taux de change. ## Limites actuelles La connexion Stripe utilise des webhooks Checkout, sans OAuth Stripe. Les renouvellements d'abonnements, remboursements Stripe et imports historiques ne sont pas automatiques. L'API `/v1/refunds` permet un remboursement explicite pour un paiement connu. # Attribution des revenus au premier contact Lunetric utilise une attribution au **premier contact connu**, dans les **90 jours précédant chaque paiement**. Le rapport relie un paiement confirmé à la première page vue enregistrée pour le même visiteur pendant cette fenêtre. Il explique une correspondance observée ; il ne prouve pas qu’un canal a causé l’achat. ## Exemple : d’une campagne au paiement Stripe 1. Un visiteur accepte la collecte et arrive depuis une campagne avec `utm_source=newsletter`. 2. Il revient ensuite par accès direct et ouvre votre checkout. 3. Votre serveur relie son identifiant de visiteur à son identifiant client. 4. Stripe confirme le paiement par webhook, ou votre serveur l’envoie à l’API. Si le premier contact de cet exemple se trouve dans la fenêtre de 90 jours, le revenu est associé à la newsletter. Le retour direct ne remplace pas ce premier contact. Une simple visite de la page de succès ne crée aucun paiement dans Lunetric. [Configurer les paiements Stripe](/docs/stripe) · [Relier les identifiants](/docs/events) ## Pourquoi un revenu peut-il rester non attribué ? Un paiement sans page vue correspondante dans la fenêtre reste dans les revenus, sous **Non attribué**. Les causes à vérifier comprennent l’absence de consentement, un tracker bloqué, un identifiant de visiteur non transmis ou un parcours sur un autre appareil sans correspondance connue. Cette catégorie est une limite de mesure explicite. N’attribuez pas artificiellement ces revenus au trafic direct pour faire disparaître les écarts. Vérifiez d’abord la collecte et la liaison des identifiants sur un parcours de test. ## Revenu brut, remboursements et devise Les montants sont conservés en unités mineures : `4900` représente `49 EUR`. Le revenu net correspond aux paiements moins les remboursements enregistrés. Comparez les rapports dans la même devise et sur la même période ; ne cumulez pas des montants de devises différentes comme s’ils étaient équivalents. Un remboursement envoyé par l’API doit référencer le paiement concerné. Son total ne peut pas dépasser le montant du paiement. [Consulter le protocole API](/docs/api). ## Que signifie la couverture d’attribution ? La couverture rapporte le revenu net attribué au revenu net total du rapport. Elle décrit la part reliée à un premier contact connu. Une couverture élevée ne constitue ni une preuve de causalité, ni une mesure de rentabilité publicitaire : les coûts de campagne ne sont pas déduits du revenu. ## Vérifier votre installation Utilisez un environnement de test pour suivre une visite consentie avec des UTM, une action, une identification et un paiement confirmé. Contrôlez ensuite le parcours, la source du paiement et la devise. Testez aussi un paiement sans visite associée : il doit rester visible et non attribué. [Installer le tracker](/docs/installation) · [Consulter les rapports avec un assistant](/docs/mcp) # Mesurer le trafic IA et la visibilité GEO La GEO concerne la visibilité d’un site dans les réponses des moteurs génératifs. Avec Lunetric, commencez par distinguer **les requêtes des robots**, **les visites humaines depuis un assistant** et **les citations dans les réponses**. Ces observations mesurent des phénomènes différents. ## Ce que Lunetric observe | Signal | Collecte | Ce qu’il permet de dire | | ---------------------------- | --------------------------------------------------- | ------------------------------------------------------------------------- | | Requête de robot | Module serveur ou proxy | Un agent a demandé une URL et reçu un statut HTTP | | Visite humaine | Tracker navigateur après consentement | Une personne a visité le site ; le référent peut identifier une source IA | | Paiement attribué | Webhook ou API serveur avec correspondance visiteur | Un revenu est relié à un premier contact connu | | Citation dans une réponse IA | Observation séparée des réponses | Une page ou une marque a été mentionnée dans une réponse donnée | Le rapport de robots Lunetric ne collecte pas le contenu des réponses des assistants. Il ne fournit pas un taux de citations. Une requête peut correspondre à la recherche, à l’entraînement ou à une visite déclenchée par un utilisateur, selon l’agent déclaré et la vérification disponible. ## Installer la mesure des robots Le tracker navigateur ne voit pas les crawlers qui lisent le HTML sans JavaScript. Installez le module serveur sur l’infrastructure qui sert réellement les pages, avant les routes Express ou sur le proxy compatible Fetch. Une clé d’écriture reste côté serveur. [Installer le module de collecte des robots](/docs/bots) Contrôlez l’URL demandée, le statut HTTP, la catégorie et le niveau de vérification. Un user-agent seul peut être usurpé. La vérification utilise les plages officielles disponibles et nécessite une adresse client obtenue depuis un proxy fiable. ## Mesurer les clics et les revenus Comparez les sources et référents reçus par le tracker, puis les conversions et revenus associés à ces visiteurs. Un référent absent ne permet pas de reconstituer la source avec certitude. La collecte dépend du consentement, du navigateur et des informations transmises par l’assistant. L’attribution au premier contact signifie qu’une visite IA située plus tard dans le parcours peut ne pas recevoir le crédit du paiement. [Comprendre le modèle d’attribution](/docs/attribution). ## Suivre les citations séparément Constituez un petit panel de questions réelles de vos clients. Pour chaque observation, notez la question exacte, le moteur, la date, le contexte, la réponse et les URL citées. Comparez les résultats sur le même panel ; la personnalisation et les changements de modèle peuvent faire varier les réponses. Une citation sans clic n’apparaît pas dans les visites du site. Une visite sans référent identifiable peut rester dans une autre source. Conservez ces limites dans vos rapports au lieu de convertir tous les crawls en « visibilité IA ». ## Améliorer les pages avant de chercher des raccourcis Rendez les réponses importantes disponibles dans le HTML initial, avec des titres descriptifs, des liens explorables et des exemples exacts. Documentez les limites, les méthodes et les changements réels du produit. Vérifiez que les moteurs autorisés reçoivent une page lisible, sans challenge bloquant. Les exports [Markdown](/llms-full.txt) facilitent la consultation documentaire dans les outils qui les prennent en charge. Ils ne garantissent ni indexation, ni classement, ni citation. [Recommandations officielles Google pour les fonctionnalités IA](https://developers.google.com/search/docs/fundamentals/ai-optimization-guide) · [Rôles des robots OpenAI](https://developers.openai.com/api/docs/bots) # IA et robots Le script navigateur ne voit pas les robots qui lisent du HTML sans exécuter JavaScript. Pour les mesurer, ajoutez un middleware au backend ou au proxy qui sert votre site. ## Express Téléchargez [lunetric-bots.mjs](/lunetric-bots.mjs) dans votre dépôt et placez le middleware avant les routes : ```js import { createBotMiddleware } from './lunetric-bots.mjs'; app.use(createBotMiddleware({ origin: 'https://votre-site.com', endpoint: 'https://analytics.votre-domaine.com', key: process.env.LUNETRIC_WRITE_KEY })); ``` ## Fetch et Workers Utilisez le module après obtention de la réponse. `waitUntil` évite de bloquer la réponse et prolonge le travail sur les plateformes compatibles. ```js import { trackCrawlerRequest } from './lunetric-bots.mjs'; const response = await serve(request); await trackCrawlerRequest(request, response, { origin: 'https://votre-site.com', endpoint: 'https://analytics.votre-domaine.com', key: env.LUNETRIC_WRITE_KEY, waitUntil: (task) => ctx.waitUntil(task) }); return response; ``` Gardez la clé d'écriture côté serveur. Un site statique nécessite une fonction serveur ou un proxy pour cette observation. ## Interprétation Les catégories sont réponses IA, indexation et entraînement, d'après l'identité déclarée par le robot. Une requête n'est pas une preuve que votre page a été citée, indexée ou incorporée dans un entraînement. La vérification IP utilise les plages officielles disponibles lorsque l'adresse fiable est fournie. Ne faites confiance aux en-têtes de proxy que si votre infrastructure empêche leur usurpation. L'adresse utilisée pour cette vérification n'est pas conservée. # Connecter un assistant ## Connexion Lunetric expose un MCP **Streamable HTTP** à `/api/mcp`. Dans **Configuration → Général**, créez une clé API de lecture pour le site concerné. Copiez-la une seule fois dans la configuration privée de votre client MCP. ```json { "mcpServers": { "lunetric": { "type": "http", "url": "https://analytics.votre-domaine.com/api/mcp", "headers": { "Authorization": "Bearer VOTRE_CLE_LECTURE" } } } } ``` Ce format fonctionne pour les clients qui acceptent `mcpServers`, `type: http` et les en-têtes. D'autres clients ont un formulaire ou une syntaxe propre : utilisez la même URL, le transport HTTP et l'en-tête Bearer. L'authentification OAuth MCP n'est pas disponible ; un client limité à OAuth doit être configuré autrement. ### Codex Dans votre configuration Codex privée, adaptez : ```toml [mcp_servers.lunetric] url = "https://analytics.votre-domaine.com/api/mcp" bearer_token_env_var = "LUNETRIC_READ_KEY" ``` Définissez `LUNETRIC_READ_KEY` dans l'environnement du client. Ne commitez jamais ce secret. Pour révoquer l'accès, révoquez la clé dans Lunetric ; cela prend effet à la requête suivante. [Référence de configuration Codex](https://developers.openai.com/codex/mcp). ## Outils disponibles | Outil | Fonction | | ------------------------------------ | -------------------------------------------------- | | `get_installation_guide` | Prompt personnalisé sans secret serveur | | `check_installation` | Dernières données reçues et état de Stripe | | `get_analytics` | Trafic, revenus et ventilations filtrées | | `get_live_visitors` | Actions récentes ; simulation marquée dans la démo | | `get_visitor_journey` | Parcours d'un visiteur du site autorisé | | `get_funnel` | Funnel ordonné avec étapes personnalisables | | `get_bot_traffic` | Requêtes de robots et leur vérification | | `list_pages` / `get_page` / `search` | Index, lecture Markdown et recherche Fumadocs | Avec une clé valide, les ressources `lunetric://installation` et `lunetric://docs/…` donnent accès aux guides. Le prompt MCP `install_lunetric` prépare l'installation dans un dépôt. ## Périmètre L’URL `/api/mcp` sert un seul MCP : sans clé, seuls les guides et leurs ressources sont accessibles ; avec une clé valide, les sept outils de lecture du site, le prompt et la ressource d’installation s’ajoutent aux trois outils documentaires. Une clé invalide ou révoquée retourne une erreur, sans repli vers un accès public. L’ancienne URL `/mcp` est un alias de ce même serveur. Les anciens outils `search_docs` et `read_docs` sont remplacés par `search` et `get_page` ; ce dernier prend une URL comme `/docs/stripe`. Chaque clé ne donne accès qu'à son site. Le MCP est en lecture seule, y compris avec une clé d'écriture. Il ne crée ni paiement, ni compte, ni clé API. Les parcours peuvent contenir des noms ou identifiants client : choisissez un assistant auquel vous souhaitez donner cet accès. ## Documentation pour les agents Le MCP `/api/mcp` donne accès aux guides sans clé API. Ajoutez un en-tête Bearer avec votre clé de lecture sur cette même URL pour lire les analytics de votre site. Ajoutez un serveur documentaire à votre client : ```json { "mcpServers": { "lunetric-docs": { "type": "http", "url": "https://analytics.votre-domaine.com/api/mcp" } } } ``` Les outils `list_pages`, `get_page` (avec `url`, par exemple `/docs/stripe`) et `search` (avec `query`) permettent de découvrir, lire et chercher dans les guides. Ce serveur stateless utilise POST avec `Content-Type: application/json` et `Accept: application/json, text/event-stream`. * `/llms.txt` : index des guides. * `/llms-full.txt` : documentation complète. * `/docs.md` : guide de démarrage. * `/docs/stripe.md` : Markdown d’une page ; remplacez `stripe` par son identifiant. * `/docs-markdown/stripe` : ancien format conservé. Sur les URLs `/docs` et `/docs/…`, l’en-tête `Accept: text/markdown` fournit également la représentation Markdown. Les réponses utilisent `Vary: Accept` pour distinguer HTML et Markdown en cache. Les boutons de chaque page copient son contenu Markdown ou ouvrent la page dans ChatGPT, Claude et les assistants proposés par Fumadocs. WebMCP expose `search_docs` et `read_page` aux agents des navigateurs compatibles. Sans URL, `read_page` lit le guide courant. Seules les pages publiques de Lunetric sont acceptées. Les outils sont retirés lorsque vous quittez la documentation. WebMCP est expérimental : sa disponibilité dépend du navigateur et de l’activation de cette API. ## Questions IA dans la documentation Le panneau **Demander à l’IA** apparaît lorsque l’administrateur configure `DOCS_AI_API_KEY` et `DOCS_AI_MODEL` sur le serveur. Il utilise OpenRouter, recherche les guides pertinents et affiche les sources utilisées. Il ne consulte pas les analytics et ne réalise aucune action sur votre compte. Les questions et les derniers échanges sont envoyés au fournisseur du modèle choisi. N’y incluez ni clé API ni information confidentielle. Une réponse IA peut être incorrecte : consultez les guides cités. Le chat nécessite une clé OpenRouter et un identifiant de modèle côté serveur. Les autres fonctionnalités — Markdown, copie, ouverture dans un assistant et MCP public — fonctionnent sans cette configuration. Utilisez `/api/mcp` avec une clé de lecture du site. Sans clé, seuls les outils documentaires sont disponibles. Aucun outil de modification de compte n’est exposé. # API ## Clés Créez les clés depuis **Configuration → Général**. Une clé de lecture permet les rapports ; une clé d'écriture permet aussi l'ingestion. Les clés sont affichées une fois, stockées hachées et révocables. Elles ne sont pas la clé publique du tracker. ## Lire un rapport ```bash curl 'https://analytics.votre-domaine.com/v1/analytics?days=30&granularity=day' \ -H "Authorization: Bearer $LUNETRIC_READ_KEY" ``` Les filtres sont `days` (1, 7, 30, 90), `from`, `to` (dates ISO), `source`, `campaign`, `country`, `path`, `currency` et `granularity` (hour, day, week, month). La date `to` est exclusive. La période maximale est 366 jours ; la vue horaire est limitée à 31 jours. Les revenus sont en unités mineures et dans la devise sélectionnée. Les outils MCP utilisent les mêmes filtres. ## Écrire côté serveur | Route | Utilisation | | ----------------------- | -------------------------------------- | | `POST /v1/identify` | Relier un visiteur à un client | | `POST /v1/payments` | Enregistrer un paiement confirmé | | `POST /v1/refunds` | Enregistrer un remboursement explicite | | `POST /v1/bot-requests` | Enregistrer une exploration | Envoyez `Content-Type: application/json` et `Authorization: Bearer VOTRE_CLE_ECRITURE`. Les requêtes invalides sont rejetées ; les erreurs ne sont pas des confirmations d'intégration. ### Remboursement ```json { "refund_id": "refund_001", "transaction_id": "order_001", "amount_minor": 1200 } ``` `provider` et `provider_account` doivent correspondre au paiement si vous les avez personnalisés. Le total remboursé ne peut pas dépasser le paiement. ### Exploration ```json { "id": "request_unique_001", "url": "https://votre-site.com/pricing", "user_agent": "ChatGPT-User/1.0", "status": 200, "method": "GET" } ``` Le middleware fourni évite de devoir gérer vous-même la classification et les nouvelles tentatives. Les doublons utilisent des références stables. # Déployer Lunetric ## Démarrer localement Depuis le dépôt Lunetric avec une version Node compatible avec les dépendances : ```bash npm ci cp .env.example .env npm run dev ``` Le frontend est accessible sur `http://127.0.0.1:5173`, l'API sur le port 3001. La documentation est sous `/docs`, le MCP sous `/mcp`. Sans `DATABASE_URL`, une base PGlite locale est créée dans `DATA_DIR`. ## Vercel + Railway Le frontend et Fumadocs sont publiés sur Vercel ; l'API, le MCP et le traitement des paiements restent sur Railway avec PostgreSQL. `middleware.ts` transmet les appels serveur en conservant l'origine publique, les cookies et les signatures Stripe. Sur Vercel, configurer `BACKEND_ORIGIN` avec le domaine HTTPS Railway et `PROXY_SECRET`, uniquement côté serveur. Sur Railway, configurer le même `PROXY_SECRET`, `APP_ORIGIN` avec le domaine Vercel, `DATABASE_URL` avec la référence du service PostgreSQL, une `ENCRYPTION_KEY` durable, `HOST=0.0.0.0`, `PORT=3001` et `SERVE_FRONTEND=false`. Le backend refuse les accès directs sans secret, excepté `/health`. `TRUST_GEO_HEADERS=true` permet d'utiliser les données IP approximatives de Vercel, remplacées à l'entrée puis transmises par le proxy authentifié. La collecte et le MCP utilisent le domaine Vercel ; les secrets n'ont pas de préfixe `VITE_`. ```bash npm run build npm run build:server npm run configure:railway npx @railway/cli up --service lunetric-api --environment production --detach vercel --prod ``` Le dépôt inclut `Dockerfile`, `scripts/configure-railway.mjs` et `vercel.json`. Prévoir une base dédiée, des sauvegardes et une seule instance API initialement. Pour un nouveau domaine Vercel, mettre à jour `APP_ORIGIN`, les restrictions Mapbox et l'URL de callback Google. ## Serveur unique ```bash npm ci npm run build npm start ``` Le serveur Express sert le frontend, la documentation, le tracker, le MCP et les API sur la même origine. Conservez `content/docs`, `public`, `server`, `shared` et les dépendances runtime dans le déploiement, ainsi que `dist`. Configurez au minimum : ```text APP_ORIGIN=https://analytics.votre-domaine.com HOST=0.0.0.0 PORT=3001 ENCRYPTION_KEY=UNE_CLE_DURABLE_DE_32_CARACTERES DATABASE_URL=postgresql://... ENABLE_DEMO=false ``` La clé de chiffrement doit être durable : sa perte empêche de déchiffrer les secrets Stripe. Utilisez un gestionnaire de secrets et HTTPS. Avec PGlite, utilisez un disque persistant et un seul processus ; avec plusieurs instances, utilisez PostgreSQL externe. ## Services facultatifs * `GOOGLE_CLIENT_ID` et `GOOGLE_CLIENT_SECRET` activent la connexion Google ; configurez aussi l'URL de callback documentée dans votre environnement. * `MAPBOX_PUBLIC_TOKEN` reçoit une clé publique Mapbox restreinte à vos domaines. * `TRUST_GEO_HEADERS=true` exige un proxy fiable qui contrôle les en-têtes de géolocalisation. Les secrets Google et Stripe restent côté serveur. Le MCP utilise les clés de lecture créées dans l'interface ; aucun secret global supplémentaire n'est nécessaire. ## Contrôles après déploiement Vérifiez `/health`, `/docs`, `/llms.txt`, puis une collecte consentie sur un site réel. Connectez le MCP et appelez `check_installation`. Testez le webhook dans la sandbox avant d'activer un endpoint de production. Prévoyez des sauvegardes de la base et de la clé de chiffrement.