Median

Context and diagnostics

What the browser sends with a message, and what you can add to a bug report.

Updated Oct 1, 20266 minute read
WhatDefaultSent withSwitch
TelemetryOnEvery message, feedback note, contact form send and crash reporttelemetry={false}
ScreenshotsDepends on the componentSee the table belowscreenshot={false}
DiagnosticsOffThe first send after mounting, then any send after something new went wrongdiagnostics
App stateNoneInside the diagnostics snapshotappState
Attached dataNothing queuedThe next widget message, feedback note, contact form send or crash reportmedianSupport.attach()

Crash reports from an error screen are on Crash reports.

Telemetry

The widget reads these when the visitor sends something. Nothing is watched or read before that.

FieldSourceShown to your team as
Time zoneThe browser's time zoneLocal time, with the zone under it
Languagenavigator.languageLanguage, as a name such as English (United Kingdom)
BrowserThe user agent, reduced to a name and major versionBrowser
OS, device, screenThe user agent, touch support, and the screen sizeUnder Browser, such as macOS · Desktop · 1512 × 982
PageThe URL without its query string or fragment, the page title, and the referrerStarted on, with the referrer's host under it
  • Device is Desktop, Tablet or Phone.
  • The raw user agent is never sent.
  • The page is kept from a conversation's first message. Later messages do not change it.
  • Each message refreshes the customer's time zone, language and browser.
  • Last seen is the time of the last message, feedback note or crash report. It is kept with or without telemetry.
  • telemetry={false} sends none of these. MedianSupport, MedianSupportModal, MedianFeedback, MedianContactForm, useMedianContact, sendMedianContact and reportError all take it.

Screenshots

ComponentWhen a picture is takenIf it fails
MedianSupport, MedianSupportModalWhen the agent asks to see the screen and the visitor presses Share my screenThe agent is told no picture is coming and asks in words
MedianFeedbackWith every note, unless the visitor attached 6 picturesA failed capture sends the note without it. A failed upload stops the send and shows the error
reportErrorWith every crash reportThe report goes without it
MedianContactFormNever
  • screenshot={false} turns it off. On reportError, pass screenshot: false. On the widget, the agent is then told no picture is coming.
  • When the agent asks, the panel shows Share my screen and Not now over the composer. Not now, or declining the browser's prompt, tells the agent the visitor chose not to share. With no answer after 2 minutes, the agent is told no picture is coming.
  • The widget's picture lands in the thread as the visitor's message, with no text, so the visitor sees what was sent.
  • A note's or crash report's picture lands on the report in Signal, beside any the visitor attached. Pictures the visitor sent in a thread are copied onto a bug filed from it, up to 6.
How it is takenThe agent's requestFeedback notes and crash reports
SourceThe browser's screen sharing. The visitor allows it, one frame is taken, and sharing stopsDrawn from the page's DOM. Nothing is recorded, and no permission prompt appears
AreaWhat the visitor shares. Chrome and Edge offer the current tab. Firefox and Safari ask for a window or screenThe visible part of the page
SizeScaled down to 1440px wide at mostScaled down to 1440px wide at most
FormatJPEG, named screenshot.jpgJPEG, named screenshot.jpg
Left outMedian panels fade out while the frame is takenEvery Median panel, launcher, contact form and highlight ring
Time limitNone for the frame. The request waits 2 minutes for an answer6 seconds, then the picture is skipped
  • Where the browser cannot share a screen, such as on phones, or a Permissions-Policy blocks display-capture, the agent's request draws the page from the DOM instead.
  • In a drawn picture, cross-origin images, <canvas> and <video> can come out blank. A font that fails to load is drawn in the browser's fallback.
  • In a drawn picture, a position: fixed element is drawn where it sits on screen. A position: sticky element is drawn where it sits in the page, so a sticky header can be missing from a picture taken further down.
  • The background of a drawn picture is the body's color, then the html element's, then white.
  • Everything on the page is in the picture. Pass screenshot={false} on pages that show somebody else's data.

Diagnostics

Off by default. When on, the component records what goes wrong on the page and sends it with the next message or note.

<MedianSupport
  apiKey="median_pk_..."
  diagnostics={{ network: true, console: true }}
  appState={{ version: BUILD_SHA, plan: user.plan }}
/>
SwitchRecordsHow
errorsUncaught errors and unhandled promise rejectionsListens on window. Failed image and script loads are skipped
networkfetch calls that threw or returned a status outside 200 to 299, with the method and URLWraps window.fetch. XMLHttpRequest is not watched
consoleconsole.error callsWraps console.error
You passerrorsnetworkconsole
diagnostics or diagnostics={true}OnOffOff
diagnostics={{ network: true }}OnOnOff
diagnostics={{ errors: false, console: true }}OffOffOn
Nothing, or falseOffOffOff
  • The wrappers call through to what they replaced. They are removed when the component unmounts.
  • MedianSupport, MedianSupportModal, MedianFeedback, MedianContactForm and useMedianContact take the same prop.
  • Every component on the page shares one list of events, and each kind of event is recorded once however many components ask for it. Each component sends the list only when its own diagnostics prop is on.
  • The first send after a component mounts carries a snapshot with the page URL, the viewport size, appState and the recorded events. Later sends carry one only when something new was recorded.
  • A snapshot carries the latest 12 events, not only the new ones.
  • On a conversation, the newest snapshot replaces the last one. It is copied onto a bug the agent files from that conversation.
  • reportError always sends a snapshot, whatever the props say.
LimitValue
Events kept12. Older events drop off
Event message300 characters
Source, as file and line or method and URL200 characters
Stack800 characters

URLs lose their query string and fragment. On a report in Signal, the snapshot shows as Page, Viewport, one row per appState entry, and Browser logs. An appState entry whose value the page URL already ends with is left out.

Your server can add its own half. A diagnostics function in median.config.ts runs when a bug is filed, and its answer shows on the report as Server check.

App state

appState puts facts about your app on a bug report, such as a build, a flag or a plan.

  • It is read at send time, so it can change as the visitor moves around.
  • It travels inside the diagnostics snapshot. Without diagnostics, MedianSupport, MedianFeedback and the contact form do not send it.
  • reportError sends the appState of the last Median component given one, with or without diagnostics.
LimitValue
Entries20. The rest are dropped
Key60 characters
Value200 characters. Numbers and booleans become text. null and undefined are skipped

Attach your own data

attach queues data for the next bug report, such as a trace, a request id or the state of a store.

import { medianSupport } from "@mediansh/widget";

window.addEventListener("error", (event) => {
  medianSupport.attach("Crash trace", event.error?.stack);
});

useMedianSupport().attach is the same function.

  • The queue lives in memory for the page load. A full reload empties it.
  • The next widget message, feedback note, contact form send or crash report takes the whole queue. A failed send puts it back.
  • It works with diagnostics off.
  • A second entry with the same label replaces the first.
  • Objects are written out as indented JSON. Numbers and booleans become text.
  • On a conversation, entries wait for the agent to file a bug from it. If no bug is filed, nobody sees them.
LimitValue
Entries8, newest kept
LabelTrimmed, cut at 60 characters
ValueCut at 4,000 characters

How an entry shows on a report:

ValueShows as
An http or https URL ending in .png, .jpg, .jpeg, .gif, .webp, .avif or .bmpThe picture, named with the label
Any other lone URLA link row
Anything elseA block titled with the label
medianSupport.attach(
  "Last render",
  "https://files.acme.com/shots/checkout-8812.png",
);
  • An empty label or value queues nothing. In development, the console says Median: attach() needs a label and a value, and nothing was queued.
  • In development, attaching with no MedianSupport, MedianFeedback or contact form mounted prints Median: data was attached, but no <MedianSupport>, <MedianFeedback> or contact form is on the page to send it. after one second. The next send from any of them still takes the queue.

The agent attaches data the same way when it files a bug. A trace, an error id or a failing request the customer pastes is kept on the report word for word.

Still need help?

    Esc