SDK JavaScript Application Insights (Web) pour TypeScript
Surveillance utilisateur réel (RUM) pour les apps navigateur avec @microsoft/applicationinsights-web. Collecte automatiquement les pages visitées, les dépendances AJAX/fetch, les exceptions non gérées et (avec le plugin Click Analytics) les clics. Supporte les événements personnalisés, les métriques et les traces d'agent GenAI qui suivent les conventions sémantiques GenAI d'OpenTelemetry et se corrèlent aux spans backend via W3C Trace Context.
Distinct de
azure-monitor-opentelemetry-ts, qui est pour les apps serveur Node.js. Cette skill concerne le code navigateur/web (et React Native).
Avant l'implémentation
Cherchez microsoft-docs MCP pour les patterns API actuels :
- Requête : "Application Insights JavaScript SDK setup"
- Requête : "Application Insights JavaScript SDK configuration"
- Requête : "Application Insights JavaScript framework extensions React Angular"
- Vérifiez la version du package :
npm view @microsoft/applicationinsights-web version
Packages
| Package | Finalité |
|---|---|
@microsoft/applicationinsights-web |
SDK RUM principal (pages, AJAX, exceptions). |
@microsoft/applicationinsights-clickanalytics-js |
Collecte auto de la télémétrie des clics. |
@microsoft/applicationinsights-react-js |
Plugin React (instrumentation du routeur, hooks, HOC, ErrorBoundary). |
@microsoft/applicationinsights-react-native |
Plugin React Native (crashs natifs, sessions). |
@microsoft/applicationinsights-angularplugin-js |
Plugin Angular (événements du routeur, ErrorHandler). |
@microsoft/applicationinsights-debugplugin-js |
Inspecteur de télémétrie dev-only. |
@microsoft/applicationinsights-perfmarkmeasure-js |
Intégration User Timing (performance.mark/measure). |
Installation
npm i --save @microsoft/applicationinsights-web
# Plugins optionnels (installez uniquement ceux que vous utilisez) :
npm i --save @microsoft/applicationinsights-clickanalytics-js
npm i --save @microsoft/applicationinsights-react-js @microsoft/applicationinsights-react-native @microsoft/applicationinsights-angularplugin-js
Les typages sont inclus avec le package — aucune installation séparée @types/... n'est nécessaire.
Chaîne de connexion
Le SDK navigateur nécessite une chaîne de connexion au moment de l'init. Elle est expédiée en texte brut aux clients — l'authentification Microsoft Entra ID n'est pas supportée pour la télémétrie navigateur. Utilisez une ressource App Insights séparée avec authentification locale activée pour le RUM navigateur si vous devez l'isoler de la télémétrie backend.
# Vite / CRA / Next.js — exposez aux clients via le préfixe env public
VITE_APPINSIGHTS_CONNECTION_STRING="InstrumentationKey=...;IngestionEndpoint=https://...;LiveEndpoint=https://..."
NEXT_PUBLIC_APPINSIGHTS_CONNECTION_STRING="InstrumentationKey=..."
Démarrage rapide (npm)
import { ApplicationInsights } from "@microsoft/applicationinsights-web";
export const appInsights = new ApplicationInsights({
config: {
connectionString: import.meta.env.VITE_APPINSIGHTS_CONNECTION_STRING,
enableAutoRouteTracking: true, // Changements de route SPA -> pages visitées
enableCorsCorrelation: true, // Propagez Request-Id / traceparent à AJAX cross-origin
enableRequestHeaderTracking: true,
enableResponseHeaderTracking: true,
distributedTracingMode: 2, // DistributedTracingModes.AI_AND_W3C — émettez traceparent pour corrélation backend
autoTrackPageVisitTime: true,
disableFetchTracking: false, // fetch() est auto-instrumenté par défaut
excludeRequestFromAutoTrackingPatterns: [/livemetrics\.azure\.com/i]
}
});
appInsights.loadAppInsights();
appInsights.trackPageView();
Appelez loadAppInsights() exactement une fois, aussi tôt que possible (avant les interactions utilisateur que vous voulez tracker). Puis trackPageView() pour le chargement initial — quand enableAutoRouteTracking est activé, les changements de route suivants sont automatiques.
Démarrage rapide (script du chargeur SDK)
Recommandé quand vous voulez un SDK auto-mis à jour et zéro pipeline de build. Collez ceci comme le premier <script> dans <head> :
<script type="text/javascript" src="https://js.monitor.azure.com/scripts/b/ai.3.gbl.min.js" crossorigin="anonymous"></script>
<script type="text/javascript">
var appInsights = window.appInsights || function (cfg) {
/* Voir : https://learn.microsoft.com/azure/azure-monitor/app/javascript-sdk
Utilisez le dernier snippet de la page Microsoft Learn ci-dessus — il inclut
le basculement CDN de secours (cr), le rapport de non-chargement SDK et le shim queue
donc les appels avant que le SDK soit prêt ne sont pas perdus. */
}({ src: "https://js.monitor.azure.com/scripts/b/ai.3.gbl.min.js",
crossOrigin: "anonymous",
cfg: { connectionString: "YOUR_CONNECTION_STRING" } });
</script>
API chargeur-only (mise en queue jusqu'au chargement du SDK) : trackEvent, trackPageView, trackException, trackTrace, trackDependencyData, trackMetric, trackPageViewPerformance, startTrackPage, stopTrackPage, startTrackEvent, stopTrackEvent, addTelemetryInitializer, setAuthenticatedUserContext, clearAuthenticatedUserContext, flush.
APIs de tracking principal
// Pages visitées (SPAs qui désactivent enableAutoRouteTracking)
appInsights.trackPageView({ name: "Checkout", uri: "/checkout", properties: { cartSize: 3 } });
// Événements personnalisés (actions utilisateur, événements métier)
appInsights.trackEvent({ name: "PurchaseCompleted" }, { orderId: "ord_123", amountUsd: 49.95 });
// Exceptions (erreurs capturées)
try {
await pay(order);
} catch (err) {
appInsights.trackException({ exception: err as Error, severityLevel: 3, properties: { orderId: order.id } });
}
// Traces (logs, sévérité 0=Verbose, 1=Info, 2=Warning, 3=Error, 4=Critical)
appInsights.trackTrace({ message: "Cart hydrated from local storage", severityLevel: 1 });
// Métriques personnalisées (numériques)
appInsights.trackMetric({ name: "checkout.duration_ms", average: 1234 });
// Dépendances (appels sortants trackés manuellement — fetch/XHR sont auto-trackés)
appInsights.trackDependencyData({
id: crypto.randomUUID(),
name: "GET /api/orders",
duration: 87, success: true, responseCode: 200,
data: "https://api.example.com/api/orders", target: "api.example.com", type: "Fetch"
});
// Identité utilisateur (défini UNE FOIS par session authentifiée — les valeurs sont PII ; ne passez pas les emails)
appInsights.setAuthenticatedUserContext("user-id-123", "tenant-456", /*storeInCookie*/ true);
appInsights.clearAuthenticatedUserContext(); // à la déconnexion
// Force l'envoi avant déchargement
appInsights.flush();
Initialiseurs de télémétrie (enrichissement & filtrage)
S'exécutent pour chaque enveloppe avant envoi. Retournez false pour rejeter.
import type { ITelemetryItem } from "@microsoft/applicationinsights-web";
appInsights.addTelemetryInitializer((item: ITelemetryItem) => {
item.tags ??= {};
item.tags["ai.cloud.role"] = "web-shop";
item.tags["ai.cloud.roleInstance"] = window.location.hostname;
item.data ??= {};
item.data["app.version"] = import.meta.env.VITE_APP_VERSION;
item.data["app.build"] = import.meta.env.VITE_BUILD_SHA;
// Rejetez les pages visitées de santé bruyantes
if (item.baseType === "PageviewData" && item.baseData?.uri?.endsWith("/healthz")) return false;
// Nettoyez les secrets de chaîne de requête
if (item.baseData?.uri) {
item.baseData.uri = item.baseData.uri.replace(/([?&](token|sig|key)=)[^&]+/gi, "$1REDACTED");
}
});
Click Analytics
import { ClickAnalyticsPlugin } from "@microsoft/applicationinsights-clickanalytics-js";
const clickPlugin = new ClickAnalyticsPlugin();
const appInsights = new ApplicationInsights({
config: {
connectionString: import.meta.env.VITE_APPINSIGHTS_CONNECTION_STRING,
extensions: [clickPlugin],
extensionConfig: {
[clickPlugin.identifier]: {
autoCapture: true,
dataTags: { useDefaultContentNameOrId: true, customDataPrefix: "data-ai-" },
urlCollectHash: false,
behaviorValidator: (b: string) => /^[a-z0-9_]+$/.test(b) ? b : ""
}
}
}
});
appInsights.loadAppInsights();
Marquez les éléments avec des attributs data-ai-* ; les clics sont émis en tant qu'événements personnalisés avec métadonnées du contenu parent.
Tracking de route SPA
- Intégré : mettez
enableAutoRouteTracking: true. Hookshistory.pushState/replaceStateetpopstate. - React Router : utilisez le HOC
withAITrackingde@microsoft/applicationinsights-react-js(voir references/framework-extensions.md). - Manuel : appelez
appInsights.trackPageView({ name, uri })dans leuseEffectdu routeur au changement de route. DésactivezenableAutoRouteTrackingpour éviter le double comptage.
Distributed Tracing (corrélation au backend)
Mettez distributedTracingMode: 2 (DistributedTracingModes.AI_AND_W3C). Le SDK ajoute traceparent (et l'ancien Request-Id) à fetch/XHR sortant. Les backends instrumentés avec OpenTelemetry (par exemple @azure/monitor-opentelemetry) se lient auto aux operation_Id du navigateur.
Pour les appels cross-origin, mettez aussi enableCorsCorrelation: true et ajoutez l'origine appelante aux en-têtes exposés CORS sur l'API.
Traces d'agent GenAI (conventions sémantiques OTel)
Quand le navigateur invoque un agent IA (function-calling, tool-use, appels modèle direct du client), émettez une télémétrie Dependency d'App Insights dont les attributs suivent les conventions sémantiques GenAI d'OpenTelemetry pour qu'elles soient interrogeables aux côtés des spans d'agent backend dans App Insights / Log Analytics.
Définissez d'abord l'env opt-in pour que les instrumentations backend se mettent d'accord sur la même version de schéma :
OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental
Clés d'attribut requises (utilisez les noms OTel textuellement)
| Span / op | Attributs requis |
|---|---|
invoke_agent {agent.name} |
gen_ai.operation.name=invoke_agent, gen_ai.provider.name, gen_ai.agent.name, gen_ai.agent.id (quand connu) |
create_agent {agent.name} |
gen_ai.operation.name=create_agent, gen_ai.provider.name, gen_ai.agent.name, gen_ai.request.model |
chat {model} |
gen_ai.operation.name=chat, gen_ai.provider.name, gen_ai.request.model, gen_ai.response.model, gen_ai.usage.input_tokens, gen_ai.usage.output_tokens |
execute_tool {tool.name} |
gen_ai.operation.name=execute_tool, gen_ai.tool.name, gen_ai.tool.type (function | extension | datastore), gen_ai.tool.call.id |
Valeurs bien connues de gen_ai.provider.name : openai, azure.ai.openai, azure.ai.inference, anthropic, aws.bedrock, gcp.gemini, gcp.vertex_ai, cohere, mistral_ai, groq, deepseek, perplexity, x_ai, ibm.watsonx.ai.
Opt-in contenu sensible.
gen_ai.system_instructions,gen_ai.input.messages,gen_ai.output.messages,gen_ai.tool.call.arguments,gen_ai.tool.call.resultsont Opt-In par défaut. Gardez-les derrière un flag runtime et évitez-les en prod sauf si vous avez approuvé le traitement des données.
Pattern : invoke_agent + spans imbriqués tool/model
import { ApplicationInsights, SeverityLevel } from "@microsoft/applicationinsights-web";
type GenAiAttrs = Record<string, string | number | boolean | undefined>;
function startGenAiSpan(name: string, attrs: GenAiAttrs) {
const id = crypto.randomUUID();
const start = performance.now();
const baseProps: GenAiAttrs = { "gen_ai.span.id": id, ...attrs };
return {
end(success: boolean, extra: GenAiAttrs = {}, error?: Error) {
const duration = Math.round(performance.now() - start);
const properties = { ...baseProps, ...extra };
appInsights.trackDependencyData({
id, name, duration, success,
responseCode: error ? 500 : 200,
type: "GenAI",
target: String(attrs["gen_ai.provider.name"] ?? "genai"),
properties: properties as Record<string, string>
});
if (error) {
appInsights.trackException({
exception: error,
severityLevel: SeverityLevel.Error,
properties: { ...properties, "error.type": error.name } as Record<string, string>
});
}
}
};
}
// Invocation d'agent
const agentSpan = startGenAiSpan("invoke_agent ResearchAssistant", {
"gen_ai.operation.name": "invoke_agent",
"gen_ai.provider.name": "azure.ai.openai",
"gen_ai.agent.name": "ResearchAssistant",
"gen_ai.agent.id": "asst_5j66UpCpwteGg4YSxUnt7lPY",
"gen_ai.request.model": "gpt-4o-mini",
"server.address": "myresource.openai.azure.com"
});
try {
// Span chat completion imbriqué
const chat = startGenAiSpan("chat gpt-4o-mini", {
"gen_ai.operation.name": "chat",
"gen_ai.provider.name": "azure.ai.openai",
"gen_ai.request.model": "gpt-4o-mini"
});
const res = await callAzureOpenAi(/* ... */);
chat.end(true, {
"gen_ai.response.model": res.model,
"gen_ai.response.id": res.id,
"gen_ai.response.finish_reasons": JSON.stringify(res.choices.map(c => c.finish_reason)),
"gen_ai.usage.input_tokens": res.usage.prompt_tokens,
"gen_ai.usage.output_tokens": res.usage.completion_tokens,
"gen_ai.output.type": "text"
});
// Span exécution d'outil imbriqué
const tool = startGenAiSpan("execute_tool getWeather", {
"gen_ai.operation.name": "execute_tool",
"gen_ai.tool.name": "getWeather",
"gen_ai.tool.type": "function",
"gen_ai.tool.call.id": "call_abc123"
});
const toolResult = await runGetWeather({ location: "SF" });
tool.end(true);
agentSpan.end(true, {
"gen_ai.usage.input_tokens": res.usage.prompt_tokens,
"gen_ai.usage.output_tokens": res.usage.completion_tokens
});
} catch (err) {
agentSpan.end(false, { "error.type": (err as Error).name }, err as Error);
}
Le traceparent du navigateur est automatiquement attaché à fetch sortant (quand distributedTracingMode: 2), donc les spans agent/Azure OpenAI en aval pendent sous le même operation_Id dans App Insights.
Pour la référence complète d'attributs, les valeurs bien connues et les conseils de capture de contenu, voir references/agent-traces.md.
KQL : interroger les traces GenAI dans App Insights
dependencies
| where type == "GenAI"
| extend op = tostring(customDimensions["gen_ai.operation.name"]),
agent = tostring(customDimensions["gen_ai.agent.name"]),
model = tostring(customDimensions["gen_ai.request.model"]),
tin = toint(customDimensions["gen_ai.usage.input_tokens"]),
tout = toint(customDimensions["gen_ai.usage.output_tokens"])
| summarize calls=count(), p95_ms=percentile(duration, 95),
avg_in=avg(tin), avg_out=avg(tout) by op, agent, model, bin(timestamp, 5m)
React (TypeScript)
Voir references/framework-extensions.md pour les recettes complètes React, React Native, Angular, Next.js et Vite.
import { ApplicationInsights } from "@microsoft/applicationinsights-web";
import { ReactPlugin, withAITracking } from "@microsoft/applicationinsights-react-js";
import { createBrowserHistory } from "history";
const reactPlugin = new ReactPlugin();
const browserHistory = createBrowserHistory();
export const appInsights = new ApplicationInsights({
config: {
connectionString: import.meta.env.VITE_APPINSIGHTS_CONNECTION_STRING,
extensions: [reactPlugin],
extensionConfig: { [reactPlugin.identifier]: { history: browserHistory } }
}
});
appInsights.loadAppInsights();
export const TrackedCheckout = withAITracking(reactPlugin, Checkout, "Checkout");
React Native
import { ApplicationInsights } from "@microsoft/applicationinsights-web";
import { ReactNativePlugin } from "@microsoft/applicationinsights-react-native";
const rnPlugin = new ReactNativePlugin();
const appInsights = new ApplicationInsights({
config: {
connectionString: process.env.EXPO_PUBLIC_APPINSIGHTS_CONNECTION_STRING,
extensions: [rnPlugin],
disableFetchTracking: false
}
});
appInsights.loadAppInsights();
Performance — Web Vitals
Auto-collectés : timings de chargement de page via PerformanceTiming / PerformanceNavigationTiming. Pour ajouter Core Web Vitals :
import { onCLS, onLCP, onINP, type Metric } from "web-vitals";
function send(m: Metric) {
appInsights.trackMetric(
{ name: `web_vitals.${m.name.toLowerCase()}`, average: m.value },
{ rating: m.rating, navigationType: m.navigationType, id: m.id }
);
}
onCLS(send); onLCP(send); onINP(send);
Cookies & Privacy
new ApplicationInsights({ config: {
connectionString,
isCookieUseDisabled: true, // Désactiver dur tous les cookies
cookieCfg: { enabled: true, domain: ".example.com", path: "/", expiry: 365 }
}});
Pour honorer le consentement dynamiquement :
appInsights.getCookieMgr().setEnabled(userGaveConsent);
appInsights.config.disableTelemetry = !userGaveConsent;
Sampling
Le sampling d'ingestion côté serveur (recommandé) est configuré sur la ressource App Insights. Le sampling côté SDK réduit l'utilisation réseau :
new ApplicationInsights({ config: { connectionString, samplingPercentage: 50 } });
Sampling par type via initialiseur de télémétrie : rejetez avec return false basé sur item.baseType.
Offline / Send-on-Unload
Le SDK utilise sendBeacon (défaut onunloadDisableBeacon: false) pour vider sur pagehide / unload. Pour SPAs, appelez aussi appInsights.flush() avant les transitions destructives (déconnexion, rechargement dur).
Pièges courants
- N'initialisez pas deux fois. Ré-importer le module sous différents bundles produit des pages visitées en double. Utilisez une seule export de module partagé.
- Initialisez avant la première interaction utilisateur pour éviter de perdre les clics/exceptions précoces.
- La chaîne de connexion est publique — ne réutilisez jamais la même ressource App Insights pour les secrets backend.
enableAutoRouteTracking+trackPageViewmanuel = doublons. Choisissez-en un.- CORS distributed tracing nécessite que l'API autorise les en-têtes de requête
Request-Id,Request-Context,traceparent,tracestateet expose l'en-tête de réponseRequest-Context. - Contenu sensible GenAI (
gen_ai.input.messagesetc.) est Opt-In — ne loggez jamais sans un flag runtime explicite et traitement des données approuvé. - L'utilisation de tokens d'agent est sur les spans
chat, pasinvoke_agent— copiez l'utilisation agrégée au span d'agent parent uniquement si vous la connaissez. - React StrictMode double-invoque les effects en dev — gardez
loadAppInsights()avec un singleton au niveau du module.
Taille du bundle
Le SDK web complet fait ~110 KB minifié (~36 KB gzippé). Pour budgets agressifs, utilisez le chemin Loader Script pour que le SDK se charge asynchronement hors du chemin critique, ou tree-shake les plugins inutilisés.
Types clés
import {
ApplicationInsights,
SeverityLevel,
DistributedTracingModes,
type IConfiguration,
type IConfig,
type ITelemetryItem,
type ITelemetryPlugin,
type ICustomProperties,
type IPageViewTelemetry,
type IEventTelemetry,
type IExceptionTelemetry,
type ITraceTelemetry,
type IMetricTelemetry,
type IDependencyTelemetry
} from "@microsoft/applicationinsights-web";
Bonnes pratiques
- Une seule instance singleton exportée depuis un seul module.
- Initialisez tôt dans le point d'entrée de l'app, avant la configuration du routeur.
- Utilisez les initialiseurs de télémétrie pour attacher
app.version,tenantIdet pour nettoyer les PII / secrets de chaîne de requête. - Mettez
distributedTracingMode: 2et assurez-vous que vos APIs acceptent/exposent les en-têtes de contexte de trace W3C. - Pour GenAI, suivez les noms d'attribut OTel
gen_ai.*textuellement — ils sont interrogeables unifié sur la télémétrie navigateur et backend. - Gardez la capture de contenu sensible (
gen_ai.input.messages/gen_ai.output.messages) derrière un opt-in au moment du build ou runtime. - Videz à la déconnexion / navigation sensible pour que la télémétrie en vol ne soit pas perdue.
Références
- references/agent-traces.md — Semconv GenAI OTel complet distillé (spans d'agent / modèle / outil, attributs, capture de contenu).
- references/framework-extensions.md — Recettes React, React Native, Angular, Next.js, Vite.
- references/configuration.md — Référence
IConfigurationcomplète et guide d'optimisation. - Microsoft Learn : https://learn.microsoft.com/azure/azure-monitor/app/javascript-sdk
- Source ApplicationInsights-JS : https://github.com/microsoft/ApplicationInsights-JS
- Conventions sémantiques GenAI OTel : https://opentelemetry.io/docs/specs/semconv/gen-ai/