The Application Insights JavaScript snippet explained
The Application Insights JavaScript snippet, now called the JavaScript (Web) SDK Loader Script, is a small inline script that creates a global appInsights object, queues any calls you make, loads the real SDK asynchronously from Microsoft's CDN, and reports a load failure if the SDK can't be fetched. It's Microsoft's recommended setup because the SDK then updates itself; the npm package is for apps that bundle the SDK or use the React, React Native or Angular extensions. Browser telemetry doesn't use OpenTelemetry, and the connection string in the page is visible to anyone.
The snippet is the most copied and least read piece of Application Insights. It’s minified into one long line, so most people paste it, change the connection string and move on. That works, until a content security policy blocks it, a consent banner requires cookies to wait, or page views don’t line up with server requests.
What the loader script does
Microsoft’s current loader is an inline function followed by a configuration object. The configuration is the readable part:
<script type="text/javascript">
!(function (cfg){ /* minified loader, copied unchanged from Microsoft's documentation */ })({
src: "https://js.monitor.azure.com/scripts/b/ai.3.gbl.min.js",
crossOrigin: "anonymous",
cfg: {
connectionString: "InstrumentationKey=...;IngestionEndpoint=https://..."
}
});
</script>
The minified function does five things, in order:
- Creates the global instance,
window.appInsightsby default (change it withnameif two SDKs share a page). - Adds proxy methods such as
trackEvent,trackPageView,trackExceptionandsetAuthenticatedUserContext. Calls made before the SDK arrives go into a queue and run once it loads, so your page code never has to wait. - Hooks
window.onerrorto catch errors that happen while the SDK is still loading, unless exception tracking is disabled. - Adds a script tag for
srcafter a delay set byld(0 ms by default; a negative value blocks the page load and puts the tag in<head>). Withsri: trueit fetches an integrity file and checks the script;crossOriginadds that attribute to the tag. - Handles failure. If the script can’t be loaded from the public CDN, the
croption retries from Microsoft’s backup CDN hosts, and the loader then sends anSDKLoadFailedexception straight to the ingestion endpoint in your connection string, so a blocked SDK still shows up in your data.dle: truesuppresses that report.
Once loaded, the SDK tracks the page view (Microsoft collects page views by default) and calls onInit with the SDK instance, the right place to add browser telemetry initializers.
Content Security Policy
The loader is an inline script that adds another script from a CDN, so a strict Content Security Policy has to allow both: the inline block (with a nonce or hash) and the CDN host in script-src. The SDK then sends telemetry to the ingestion endpoint from your connection string, which connect-src must allow. On ASP.NET Core, the server SDK’s ScriptBody (below) exists precisely so you can write the <script> tag with your own nonce. The snippet package also documents Trusted Types support from version 1.2.2, for sites that require require-trusted-types-for 'script'.
Loader script or npm package
| SDK Loader Script | npm @microsoft/applicationinsights-web | |
|---|---|---|
| Updates | Automatic: the CDN serves the latest SDK | You update the package |
| Where it runs | Pages you paste it into | Your bundle |
| Typings and IntelliSense | No | Included |
| React, React Native, Angular extensions | No | Required |
| Microsoft’s recommendation | Most customers | Custom events and configuration, framework extensions |
The npm form, for comparison:
import { ApplicationInsights } from "@microsoft/applicationinsights-web";
const appInsights = new ApplicationInsights({
config: {
connectionString: "InstrumentationKey=...;IngestionEndpoint=https://...",
enableCorsCorrelation: true,
disableCookiesUsage: true,
},
});
appInsights.loadAppInsights();
appInsights.trackPageView();
If you generate pages server-side and want the loader without pasting minified code into a template, the @microsoft/applicationinsights-web-snippet package returns the script for a configuration (getSdkLoaderScript(config)), including the integrity-checked variant.
Classic SDK 2.x
The server SDK has long been able to write the snippet for you. In ASP.NET Core 2.x, inject JavaScriptSnippet in _ViewImports.cshtml and render it at the end of <head>:
@inject Microsoft.ApplicationInsights.AspNetCore.JavaScriptSnippet JavaScriptSnippet
...
@Html.Raw(JavaScriptSnippet.FullScript)
</head>
ScriptBody (from SDK 2.14) gives you just the script body, so you can write your own <script> tag with a CSP nonce. With EnableAuthenticationTrackingJavaScript, the injected script also passes the signed-in user’s name to setAuthenticatedUserContext. The injected version uses default settings only; for any other configuration, Microsoft says to remove the injection and add the SDK yourself.
Today: SDK 3.x and the Microsoft OpenTelemetry Distro
SDK 3.x keeps JavaScriptSnippet for ASP.NET Core (its IHttpContextAccessor constructor parameter became optional) and keeps EnableAuthenticationTrackingJavaScript. The Microsoft OpenTelemetry Distro has no snippet helper: server-side OpenTelemetry doesn’t replace browser telemetry, so add the loader script to your layout yourself, or render it with the snippet package.
Page views and server requests in one trace
The JavaScript SDK records Ajax and fetch calls as dependencies of the page view and sends correlation headers with them: W3C traceparent and tracestate, plus the older Request-Id while distributedTracingMode is left at its default AI_AND_W3C. Your server SDK or distro reads them, so the server request becomes a child of the browser call, and the end-to-end transaction view shows both.
Headers are only added to calls to the page’s own domain. For an API on another host, including a subdomain, set enableCorsCorrelation: true, make sure the API’s CORS policy allows the headers, and exclude third parties that reject unknown headers with correlationHeaderExcludedDomains (Microsoft’s example excludes *.auth0.com). See request naming for how those server requests are grouped.
Switching it off, and consent
- One page: don’t include the loader on it, or set
disableTelemetry: truein that page’scfg; the SDK then neither collects nor sends. - Cookies before consent: set
disableCookiesUsage: true, thenappInsights.getCookieMgr().setEnabled(true)after the user agrees. Without cookies, user and session IDs can’t persist across page loads, which affects user counts; see users and sessions. - Volume:
samplingPercentage(default 100) keeps a share of browser telemetry; choose a value of 100/N, and match the server’s rate if you use fixed-rate sampling there too. The sampling guide explains why.
Telemetry initializers enrich or drop items: add one in onInit (or with addTelemetryInitializer in the npm form) and return false to drop an item. That’s also where you’d attach browser context such as the connection type the browser reports, as a custom property.
The connection string in the browser
Anything in the page is public, and Microsoft is explicit that the connection string isn’t a security token. Two consequences follow. Anyone can send telemetry to that resource, and browser telemetry can’t simply use Microsoft Entra authentication. Microsoft’s suggestions are a separate Application Insights resource with local authentication for browser telemetry, or a relay (for example Azure API Management) that authenticates with a managed identity, with the connection string’s IngestionEndpoint pointing at it. The telemetry channels guide covers that override.
Troubleshooting
| Symptom | Likely cause |
|---|---|
Only SDKLoadFailed exceptions arrive | The CDN script is blocked (ad blocker, CSP, firewall); allow the CDN host or self-host the SDK |
| Page views but no server requests in the same trace | API on another origin without enableCorsCorrelation, or CORS rejects the headers |
| Third-party calls fail after enabling CORS correlation | That host rejects traceparent; add it to correlationHeaderExcludedDomains |
| Errors about multiple SDK versions on one page | Two loaders with the same name; give one a different name |
| Load fails immediately | connectionString isn’t in InstrumentationKey=...; form |
Queries for this topic
-
Page views by page name and country
pageViews usage
Returns: Up to 50 rows, one per page name and country or region, with the sampling-adjusted page view count and the number of distinct users, most viewed first.
-
Daily active users and sessions
requestspageViews usage
Returns: One point per UTC day for the last 30 complete days with the number of distinct user IDs and distinct session IDs seen on requests and page views.
Frequently asked questions
Is it a problem that the connection string is visible in the page source?
Microsoft says the connection string isn't a security token or key, but anyone who reads it can send telemetry to your resource. Browser telemetry can't easily use Microsoft Entra authentication, so Microsoft suggests a separate resource for browser data, or a relay such as API Management in front of ingestion.
Should browser monitoring move to OpenTelemetry?
No. Microsoft states the Application Insights JavaScript SDK is the supported client-side path, that it doesn't use OpenTelemetry, and that customers aren't expected to migrate browser monitoring to OpenTelemetry. Use OpenTelemetry for server-side code, including Node.js.
How do I stop the SDK from setting cookies until the user consents?
Initialise with disableCookiesUsage set to true (or cookieCfg.enabled false), then call appInsights.getCookieMgr().setEnabled(true) once consent is given. While cookies are off, the SDK neither stores nor reads anything from cookies.
Sources, checked
- Application Insights JavaScript SDK setup in Azure Monitor
- Microsoft Azure Monitor Application Insights JavaScript SDK configuration
- Microsoft Application Insights JavaScript SDK (GitHub README)
- Application Insights JavaScript SDK web snippet package (README)
- Monitor .NET and Node.js applications with Application Insights (Classic API 2.x)
- Breaking changes: Application Insights 2.x to 3.x (JavaScriptSnippet)
- Connection strings in Application Insights (authenticated browser telemetry)