0
# Browser Monitoring
1
2
Generate Real User Monitoring (RUM) scripts for correlating server-side performance with client-side metrics.
3
4
## Capabilities
5
6
### Get Browser Timing Header
7
8
Generate the browser monitoring script tag for injection into HTML pages.
9
10
```javascript { .api }
11
/**
12
* Generate browser monitoring script for Real User Monitoring injection.
13
* Must be called for each page request - do not reuse between users or requests.
14
* @param {object} [options] - Configuration options
15
* @param {string} [options.nonce] - CSP nonce for script tag
16
* @param {boolean} [options.hasToRemoveScriptWrapper] - Return script content without <script> tags
17
* @param {boolean} [options.allowTransactionlessInjection] - Allow injection without active transaction
18
* @returns {string} HTML script tag or script content, empty string or HTML comment on error
19
*/
20
function getBrowserTimingHeader(options);
21
```
22
23
**Usage Examples:**
24
25
```javascript
26
const newrelic = require('newrelic');
27
28
// Basic usage in Express templates
29
app.get('/', (req, res) => {
30
const browserScript = newrelic.getBrowserTimingHeader();
31
res.render('index', { browserScript });
32
});
33
34
// Template usage (EJS example)
35
// In your HTML head section:
36
// <%- browserScript %>
37
38
// With CSP nonce
39
app.get('/secure-page', (req, res) => {
40
const nonce = generateNonce();
41
const browserScript = newrelic.getBrowserTimingHeader({ nonce });
42
43
res.set('Content-Security-Policy', `script-src 'nonce-${nonce}' 'self'`);
44
res.render('secure-page', { browserScript });
45
});
46
47
// For React/SPA applications (script content only)
48
app.get('/api/browser-script', (req, res) => {
49
const scriptContent = newrelic.getBrowserTimingHeader({
50
hasToRemoveScriptWrapper: true
51
});
52
53
res.json({ scriptContent });
54
});
55
56
// Allow injection without active transaction
57
app.get('/static-page', (req, res) => {
58
const browserScript = newrelic.getBrowserTimingHeader({
59
allowTransactionlessInjection: true
60
});
61
res.render('static-page', { browserScript });
62
});
63
```
64
65
## Browser Timing Options
66
67
```javascript { .api }
68
interface BrowserTimingOptions {
69
/** CSP nonce to inject into the script tag for security */
70
nonce?: string;
71
/** Return script content without <script> wrapper tags */
72
hasToRemoveScriptWrapper?: boolean;
73
/** Allow browser agent injection when no active transaction exists */
74
allowTransactionlessInjection?: boolean;
75
}
76
```
77
78
## Script Output Formats
79
80
### Default Output (with script tags)
81
```html
82
<script type='text/javascript'>
83
window.NREUM||(NREUM={});NREUM.info = {"beacon":"bam.nr-data.net","errorBeacon":"bam.nr-data.net","licenseKey":"abc123","applicationID":"12345","transactionName":"xyz","queueTime":0,"applicationTime":123,"ttGuid":"def456","agent":"js-agent.newrelic.com/nr-spa-1234.min.js"};
84
// ... agent loader script
85
</script>
86
```
87
88
### With CSP Nonce
89
```html
90
<script type='text/javascript' nonce="abc123xyz">
91
// ... same content as above
92
</script>
93
```
94
95
### Without Script Wrapper
96
```javascript
97
window.NREUM||(NREUM={});NREUM.info = {"beacon":"bam.nr-data.net",...};
98
// ... agent loader script (content only)
99
```
100
101
## Error Conditions
102
103
The function returns HTML comments with error codes when browser monitoring cannot be generated:
104
105
- `<!-- NREUM: (0) -->` - Browser monitoring disabled in configuration
106
- `<!-- NREUM: (1) -->` - No active transaction or transaction ignored
107
- `<!-- NREUM: (2) -->` - Browser monitoring configuration missing
108
- `<!-- NREUM: (3) -->` - Transaction name missing
109
- `<!-- NREUM: (4) -->` - Application ID missing (agent not connected)
110
- `<!-- NREUM: (5) -->` - Browser key missing (server disabled monitoring)
111
- `<!-- NREUM: (6) -->` - Agent loader script missing
112
- `<!-- NREUM: (7) -->` - Browser monitoring disabled by server
113
114
## Configuration Requirements
115
116
Browser monitoring requires:
117
118
1. **Agent Connection**: Agent must have successfully connected to New Relic servers
119
2. **Browser Monitoring Enabled**: `browser_monitoring.enable: true` in configuration
120
3. **Server Configuration**: New Relic servers must provide browser monitoring settings
121
4. **Active Transaction**: Usually requires an active transaction (unless `allowTransactionlessInjection: true`)
122
123
## Common Integration Patterns
124
125
### Express with Template Engines
126
127
```javascript
128
// EJS template
129
app.get('/', (req, res) => {
130
res.render('index', {
131
title: 'My App',
132
browserScript: newrelic.getBrowserTimingHeader()
133
});
134
});
135
136
// In views/index.ejs:
137
// <!DOCTYPE html>
138
// <html>
139
// <head>
140
// <title><%= title %></title>
141
// <%- browserScript %>
142
// </head>
143
// <body>...</body>
144
// </html>
145
```
146
147
### React/Next.js Applications
148
149
```javascript
150
// API route to get browser script
151
app.get('/api/newrelic-browser', (req, res) => {
152
const scriptContent = newrelic.getBrowserTimingHeader({
153
hasToRemoveScriptWrapper: true
154
});
155
156
res.json({
157
success: scriptContent.length > 0,
158
script: scriptContent
159
});
160
});
161
162
// In React component:
163
useEffect(() => {
164
fetch('/api/newrelic-browser')
165
.then(res => res.json())
166
.then(data => {
167
if (data.success && data.script) {
168
const script = document.createElement('script');
169
script.innerHTML = data.script;
170
document.head.appendChild(script);
171
}
172
});
173
}, []);
174
```
175
176
### Middleware for Automatic Injection
177
178
```javascript
179
// Middleware to automatically add browser script to all HTML responses
180
app.use((req, res, next) => {
181
const originalRender = res.render;
182
183
res.render = function(view, options = {}) {
184
// Add browser script to all template renders
185
options.browserScript = newrelic.getBrowserTimingHeader();
186
return originalRender.call(this, view, options);
187
};
188
189
next();
190
});
191
```
192
193
### CSP-Compliant Implementation
194
195
```javascript
196
// Generate nonce for each request
197
function generateNonce() {
198
return require('crypto').randomBytes(16).toString('base64');
199
}
200
201
app.use((req, res, next) => {
202
// Generate nonce for this request
203
const nonce = generateNonce();
204
res.locals.nonce = nonce;
205
206
// Set CSP header
207
res.set('Content-Security-Policy',
208
`script-src 'nonce-${nonce}' 'self' js-agent.newrelic.com bam.nr-data.net`
209
);
210
211
next();
212
});
213
214
app.get('/', (req, res) => {
215
const browserScript = newrelic.getBrowserTimingHeader({
216
nonce: res.locals.nonce
217
});
218
219
res.render('index', { browserScript });
220
});
221
```
222
223
### Error Handling and Fallbacks
224
225
```javascript
226
function getSafeBrowserScript(options = {}) {
227
try {
228
const script = newrelic.getBrowserTimingHeader(options);
229
230
// Check if script generation failed (returns HTML comment)
231
if (script.startsWith('<!-- NREUM:')) {
232
console.warn('Browser monitoring script generation failed:', script);
233
return ''; // Return empty string for failed generation
234
}
235
236
return script;
237
} catch (error) {
238
console.error('Error generating browser monitoring script:', error);
239
return ''; // Fail gracefully
240
}
241
}
242
243
// Usage with fallback
244
app.get('/', (req, res) => {
245
const browserScript = getSafeBrowserScript();
246
res.render('index', { browserScript });
247
});
248
```
249
250
### Single Page Application (SPA) Support
251
252
```javascript
253
// For SPAs, you might want to inject the script only on initial page load
254
app.get('/', (req, res) => {
255
const browserScript = newrelic.getBrowserTimingHeader();
256
res.render('spa-shell', { browserScript });
257
});
258
259
// API routes don't need browser monitoring
260
app.get('/api/*', (req, res, next) => {
261
// Skip browser monitoring for API calls
262
next();
263
});
264
```
265
266
### Development vs. Production
267
268
```javascript
269
// Only inject in production environment
270
function getBrowserScriptForEnvironment(options = {}) {
271
if (process.env.NODE_ENV !== 'production') {
272
return ''; // No browser monitoring in development
273
}
274
275
return newrelic.getBrowserTimingHeader(options);
276
}
277
278
app.get('/', (req, res) => {
279
const browserScript = getBrowserScriptForEnvironment();
280
res.render('index', { browserScript });
281
});
282
```
283
284
## Best Practices
285
286
1. **Placement**: Inject the script as high as possible in the `<head>` section, after any X-UA-Compatible meta tags
287
2. **Per-Request Generation**: Always generate fresh scripts for each request - never cache or reuse
288
3. **Error Handling**: Check for HTML comments indicating failed generation
289
4. **CSP Compliance**: Use nonce parameter when Content Security Policy is enabled
290
5. **Environment Control**: Consider disabling in development environments
291
6. **Performance**: The script is small but generated per-request, consider caching requirements if performance is critical
292
7. **HTTPS**: Browser monitoring works best with HTTPS applications
293
8. **Correlation**: Browser monitoring data correlates with server-side transaction data automatically when properly implemented