The most surprising thing about New Relic Browser’s SPA and AJAX monitoring is that it doesn’t just passively observe your application; it actively injects itself into the browser’s lifecycle to capture every interaction, even those initiated by third-party scripts or browser features you might not expect.

Let’s see this in action. Imagine a typical Single Page Application (SPA) built with React. When a user clicks a link to navigate to a new "page" without a full browser reload, New Relic Browser is already listening.

// Inside your SPA's routing logic (e.g., React Router)
history.push('/users/123');

At this exact moment, New Relic Browser intercepts the history.pushState call. It then records:

  1. The start of the "page view": This isn’t a traditional window.onload event. It’s a custom event triggered by the SPA’s router.
  2. The AJAX request: If the new "page" requires fetching data from your backend (e.g., /api/users/123), New Relic captures this XMLHttpRequest or fetch call.
  3. The rendering time: It measures how long it takes your JavaScript framework to update the DOM and make the new "page" visible to the user.
  4. The end of the "page view": This is often tied to the completion of the AJAX request and subsequent DOM updates.

This entire sequence is then reported back to New Relic as a single, cohesive transaction, allowing you to see the complete user experience, from initial click to rendered content, all within the context of a single page load in the browser.

The Problem It Solves: The Black Box of Client-Side Performance

Before tools like New Relic Browser’s SPA monitoring, diagnosing performance issues in SPAs was a nightmare. You’d see slow page loads in your backend APM, but you wouldn’t know why. Was it slow API calls? Was your JavaScript taking ages to render? Was a third-party script hogging the CPU? The browser was a black box.

New Relic Browser breaks open that box. It provides visibility into:

  • Client-side errors: JavaScript exceptions, uncaught errors, and even errors occurring within AJAX responses.
  • AJAX request performance: Latency, throughput, and error rates for every asynchronous request your frontend makes.
  • Page load times: From initial HTML download to the final rendering of the page, broken down into network, backend, and frontend processing.
  • Browser-specific performance: How your app performs across different browsers and versions.
  • User session tracing: The ability to follow a single user’s journey through your application, seeing every interaction and its associated performance metrics.

How It Works Internally: The JavaScript Agent

The magic happens via a small JavaScript snippet that you include in the <head> of your HTML. This snippet loads the New Relic Browser agent. This agent is designed to be lightweight and non-blocking.

Once loaded, it hooks into various browser APIs:

  • XMLHttpRequest and fetch: It wraps these to time network requests, capture response times, and record status codes.
  • History API (pushState, replaceState): Crucial for SPAs, this allows the agent to detect route changes that don’t involve a full page reload, treating them as distinct "page views."
  • PerformanceTiming and PerformanceNavigationTiming APIs: Used to measure the browser’s own timing metrics for page loads.
  • MutationObserver: Can be used (though less common now for core SPA tracking) to detect DOM changes for more granular timing.
  • Error handling (window.onerror, window.addEventListener('unhandledrejection')): Captures JavaScript errors.

The agent collects this data and batches it up, sending it to New Relic’s collectors periodically. This batching is key to minimizing the agent’s own impact on performance.

The Levers You Control

While much of the agent’s operation is automatic, you have several ways to influence its behavior and reporting:

  • applicationID: This is the unique identifier for your New Relic application, ensuring data goes to the right place.
  • licenseKey: Your account’s license key, used for authentication with New Relic.
  • spaEnabled: true: Explicitly enables SPA monitoring. If this is false, it won’t track route changes as separate page views.
  • ajaxEnabled: true: Enables AJAX transaction monitoring.
  • jserrorsEnabled: true: Enables JavaScript error reporting.
  • maxBeacons and maxSamples: Controls how many page views and AJAX requests are sent to New Relic per minute, helping manage data volume.
  • distributedTracingEnabled: true: If enabled, the agent can participate in and initiate distributed traces, linking browser activity to backend services.
  • Custom Attributes: You can add custom attributes to your browser monitoring data using newrelic.addPageAction() or by configuring the agent to inject specific data.

The "Phantom" Page View

One of the most common points of confusion is the concept of a "phantom" page view. When you enable SPA monitoring, New Relic Browser will often report an initial "page view" that doesn’t correspond to a direct URL navigated by the user. This initial page view is typically triggered by the loading of your index.html file and the subsequent bootstrapping of your SPA framework. It represents the start of your application’s client-side execution, and without it, you’d lose the critical timing data for the initial render and any subsequent AJAX calls made immediately upon load. Understanding that this initial event is a legitimate part of your SPA’s lifecycle is crucial for accurate performance analysis.

The next step in understanding your frontend performance is correlating these browser transactions with backend traces to get a full picture of distributed requests.

Want structured learning?

Take the full Newrelic course →