Measuring the performance of user journeys

This article explains how to use DebugBear to measure the performance of user scenarios following the initial page load.

User journey performance metrics

Limitations

The steps described here only work for user interactions in a single-page app. Data won't be collected if a redirect occurs after the initial page load.

If your user journey includes page reloads, set up multiple separate pages on DebugBear. Use setup flows to go through any preceding steps in the user journey, and then test the final page.

Injecting JavaScript to script user interaction and capture custom performance metrics

To script user journeys you need to run JavaScript code on the page. This code behaves similarly to code pasted into the DevTools console.

Script capturing custom timings in user journey

This example code clicks on a button that opens a modal.

const btn = await waitForElement("button.open-modal")
performance.mark("Button rendered")
btn.click()

await waitForElement("div.modal")
performance.mark("Modal rendered")

Use the waitForElement helper function to wait for DOM elements before clicking them or saving a custom timing metric. Paste this file in the console when testing user journeys in the browser DevTools.

You can use performance.mark to capture custom performance metrics. These metrics will be included in the DebugBear report.

Scripting form input

Just like before you can script form input using standard JavaScript.

const form = await waitForElement("#add-todo")
form.querySelector("input[name='title']").value = "Clean kitchen"
form.querySelector("input[type='button]").click()
await waitForElement(".todoCreatedMessage")

In a JavaScript app this sometimes won't be enough, as just updating the field value will not trigger the event listener for the form field.

Manually triggering the event can resolve this:

form.querySelector("input[name='title']").value = "Clean kitchen"
// Trigger keyup
form.querySelector("input[name='title']").dispatchEvent(new Event("keyup", { bubbles: true }))
// Trigger change
form.querySelector("input[name='title']").dispatchEvent(new Event("change", { bubbles: true }))
// (You'll need to trigger the right event for your app)

An example user journey

This example shows how to navigate between pages on SourceGraph.

// Wait for homepage to load
const jsLink = await waitForElement(`.search-filter-keyword`, { containingText: "JavaScript" })
await new Promise(resolve => setTimeout(resolve, 1000))
performance.mark("1. Click JS link");
jsLink.click()

// Wait for search results
const link = await waitForElement(`.result-container__header-title a`)
performance.mark("2. Search results rendered");
await new Promise(resolve => setTimeout(resolve, 1000))
performance.mark("3. Click search result");
await link.click()

// Wait for details page
await waitForElement(".tree-page__title");
performance.mark("4. Repo rendered");

The script includes two 1s delays. Normally you won't need these, but I added them so each fully rendered page shows up in the filmstrip.

Navigation in timeline

The Performance tab lets you compare the User Timings in a single chart.

Navigation in timeline


Still need help? Contact matt@debugbear.com for support.
DebugBear is a website monitoring tool built for front-end teams. Track performance metrics and Lighthouse scores in CI and production. Learn more.
© 2021 DebugBear Ltd