@multiplayer-app/session-recorder-browser 1.2.27 → 1.2.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -221,10 +221,37 @@ SessionRecorder.setSessionAttributes({
221
221
  // if you're not using widget (see: `showWidget: true/false`)
222
222
  // then you can programatically control the session recorder
223
223
  // by using the methods below
224
- SessionRecorder.start()
225
- SessionRecorder.pause()
226
- SessionRecorder.resume()
227
- SessionRecorder.stop('Finished session') // optional: pass reason for stopping the session
224
+
225
+ // Option A: fire-and-forget (simple)
226
+ // SessionRecorder.start()
227
+ // ... later ...
228
+ // SessionRecorder.stop('Finished session')
229
+
230
+ // Option B: wire up your own UI controls
231
+ const startButton = document.getElementById('start')
232
+ const pauseButton = document.getElementById('pause')
233
+ const resumeButton = document.getElementById('resume')
234
+ const stopButton = document.getElementById('stop')
235
+
236
+ startButton?.addEventListener('click', () => {
237
+ SessionRecorder.start()
238
+ })
239
+
240
+ startContinuousButton?.addEventListener('click', () => {
241
+ SessionRecorder.start(SessionType.CONTINUOUS)
242
+ })
243
+
244
+ pauseButton?.addEventListener('click', () => {
245
+ SessionRecorder.pause()
246
+ })
247
+
248
+ resumeButton?.addEventListener('click', () => {
249
+ SessionRecorder.resume()
250
+ })
251
+
252
+ stopButton?.addEventListener('click', () => {
253
+ SessionRecorder.stop('Finished session') // optional reason
254
+ })
228
255
  ```
229
256
 
230
257
  ### Continuous session recording
@@ -246,17 +273,28 @@ SessionRecorder.setSessionAttributes({
246
273
  // if you're not using widget (see: `showWidget: true/false`)
247
274
  // then you can programatically control the session recorder
248
275
  // by using the methods below
249
- SessionRecorder.start(SessionType.CONTINUOUS)
250
-
251
- // do something here
252
-
253
- SessionRecorder.save()
254
-
255
- // do something here
276
+ // Option A: fire-and-forget (simple)
277
+ // SessionRecorder.start(SessionType.CONTINUOUS)
278
+ // ... later ...
279
+ // SessionRecorder.save()
280
+ // ... later ...
281
+ // SessionRecorder.stop('Finished session')
282
+ // Option B: wire up your own UI controls
283
+ const startContinuousButton = document.getElementById('start-continuous')
284
+ const saveButton = document.getElementById('save')
285
+ const stopButton = document.getElementById('stop')
286
+
287
+ startContinuousButton?.addEventListener('click', () => {
288
+ SessionRecorder.start(SessionType.CONTINUOUS)
289
+ })
256
290
 
257
- SessionRecorder.save()
291
+ saveButton?.addEventListener('click', () => {
292
+ SessionRecorder.save()
293
+ })
258
294
 
259
- SessionRecorder.stop('Finished session') // optional: pass reason for stopping the session
295
+ stopButton?.addEventListener('click', () => {
296
+ SessionRecorder.stop('Finished session') // optional reason
297
+ })
260
298
  ```
261
299
 
262
300
  ### Capture exceptions
@@ -361,20 +399,64 @@ export default function MyApp() {
361
399
  }
362
400
  ```
363
401
 
402
+ ### Next.js 15.3+ (App Router) — instrumentation-client.ts
403
+
404
+ On Next.js 15.3+ you can initialize the Session Recorder as early as possible with `src/instrumentation-client.ts|js`, which runs before hydration. You can also export `onRouterTransitionStart` to observe navigation. See the official docs: [instrumentation-client.ts](https://nextjs.org/docs/app/api-reference/file-conventions/instrumentation-client).
405
+
406
+ 1. Create `app/instrumentation-client.ts|js`:
407
+
408
+ ```ts
409
+ import SessionRecorder from '@multiplayer-app/session-recorder-browser'
410
+
411
+ // Initialize as early as possible (before hydration)
412
+ try {
413
+ SessionRecorder.init({
414
+ application: 'my-next-app',
415
+ version: '1.0.0',
416
+ environment: process.env.NEXT_PUBLIC_ENVIRONMENT ?? 'production',
417
+ apiKey: process.env.NEXT_PUBLIC_MULTIPLAYER_API_KEY!,
418
+ showWidget: true,
419
+ // If your APIs are on different origins, add them so OTLP headers are propagated
420
+ // format: string | RegExp | Array
421
+ propagateTraceHeaderCorsUrls: [new RegExp('https://api.example.com', 'i')]
422
+ })
423
+ } catch (error) {
424
+ // Keep instrumentation resilient
425
+ console.warn('[SessionRecorder] init failed in instrumentation-client:', error)
426
+ }
427
+
428
+ // Optional: Next.js will call this when navigation begins
429
+ export function onRouterTransitionStart(url: string, navigationType: 'push' | 'replace' | 'traverse') {
430
+ try {
431
+ SessionRecorder.navigation.record({
432
+ path: url || '/',
433
+ navigationType,
434
+ framework: 'nextjs',
435
+ source: 'instrumentation-client'
436
+ })
437
+ } catch (error) {
438
+ console.warn('[SessionRecorder] navigation record failed:', error)
439
+ }
440
+ }
441
+ ```
442
+
364
443
  ## Note
365
444
 
366
445
  If frontend domain doesn't match to backend one, set backend domain to `propagateTraceHeaderCorsUrls` parameter:
367
446
 
368
447
  ```javascript
369
448
  import SessionRecorder from '@multiplayer-app/session-recorder-browser'
370
-
371
- SessionRecorder.init({
372
- version: '{YOUR_APPLICATION_VERSION}',
373
- application: '{YOUR_APPLICATION_NAME}',
374
- environment: '{YOUR_APPLICATION_ENVIRONMENT}',
375
- apiKey: '{YOUR_API_KEY}',
376
- propagateTraceHeaderCorsUrls: new RegExp(`https://your.backend.api.domain`, 'i')
377
- })
449
+ try {
450
+ SessionRecorder.init({
451
+ application: 'my-next-app',
452
+ version: '1.0.0',
453
+ environment: process.env.NEXT_PUBLIC_ENVIRONMENT ?? 'production',
454
+ apiKey: process.env.NEXT_PUBLIC_MULTIPLAYER_API_KEY!,
455
+ propagateTraceHeaderCorsUrls: new RegExp(`https://your.backend.api.domain`, 'i')
456
+ })
457
+ } catch (error) {
458
+ console.warn('[SessionRecorder] init failed:', error)
459
+ }
378
460
  ```
379
461
 
380
462
  If frontend sends api requests to two or more different domains put them to `propagateTraceHeaderCorsUrls` as array:
@@ -382,16 +464,17 @@ If frontend sends api requests to two or more different domains put them to `pro
382
464
  ```javascript
383
465
  import SessionRecorder from '@multiplayer-app/session-recorder-browser'
384
466
 
385
- SessionRecorder.init({
386
- version: '{YOUR_APPLICATION_VERSION}',
387
- application: '{YOUR_APPLICATION_NAME}',
388
- environment: '{YOUR_APPLICATION_ENVIRONMENT}',
389
- apiKey: '{YOUR_API_KEY}',
390
- propagateTraceHeaderCorsUrls: [
391
- new RegExp(`https://your.backend.api.domain`, 'i'),
392
- new RegExp(`https://another.backend.api.domain`, 'i')
393
- ]
394
- })
467
+ try {
468
+ SessionRecorder.init({
469
+ // ... other config ...
470
+ propagateTraceHeaderCorsUrls: [
471
+ new RegExp(`https://your.backend.api.domain`, 'i'),
472
+ new RegExp(`https://another.backend.api.domain`, 'i')
473
+ ]
474
+ })
475
+ } catch (error) {
476
+ console.warn('[SessionRecorder] init failed:', error)
477
+ }
395
478
  ```
396
479
 
397
480
  ### Framework notes