ASRouter New Tab Multistage Message
An inline multistage message surface for displaying multi-screen flows on the Firefox New Tab page.
Like asrouter-newtab-message, this component is packaged to take advantage of newtab train-hopping. The newtab extension knows to package this component at build-time both to the built-in instance of newtab and the train-hoppable XPI. It is the responsibility of the owners of this component to maintain newtab train-hop compatibility. At this time, the owners of this component are the OMC team.
Overview
The ASRouter New Tab Multistage Message embeds the full MultiStageAboutWelcome React component inline on about:newtab, inside a shadow root managed by ExternalComponentWrapper. This allows the same multi-screen onboarding flows used in about:welcome and Spotlight to be surfaced directly on the New Tab page without a modal or overlay.
A dismiss button is rendered above the multistage content. Clicking it blocks the message permanently.
Integration
The component is loaded dynamically through the newtab page’s ExternalComponentWrapper using the react-bundle mount strategy. It is wrapped by the MessageWrapper component, which provides impression tracking and message lifecycle management.
The mount function exposed by the bundle is window.mountMultistageMessage. It receives props injected by ExternalComponentWrapper (which in turn receives them from MessageWrapper via React.cloneElement), sets up the AW handler bridge, renders the React tree, and returns a cleanup function.
AW Handler Bridge
MultiStageAboutWelcome communicates with its host environment through a set of window.AW* globals. mountMultistageMessage installs a bridge that maps these to the newtab message lifecycle:
Handler |
Behaviour in this context |
|---|---|
|
Forwarded to ASRouter via |
|
Returns the message |
|
Calls |
|
Forwarded to ASRouter as a |
|
Forwarded to ASRouter via |
|
Routes non-impression events to |
|
Returns a resolved promise (themes not applicable in this context) |
|
Returns a resolved promise (not applicable in this context) |
All handlers are deleted from window when the component is unmounted.
Message Configuration
Messages use the newtab_message template with messageType: "ASRouterMultistageMessage":
{
id: "MY_NEWTAB_MULTISTAGE_MESSAGE",
template: "newtab_message",
content: {
messageType: "ASRouterMultistageMessage",
id: "MY_NEWTAB_MULTISTAGE_MESSAGE",
transitions: false,
backdrop: "transparent",
screens: [
{
id: "SCREEN_1",
content: {
position: "center",
title: { raw: "Title" },
primary_button: {
label: { raw: "Primary" },
action: { navigate: true },
},
},
},
],
},
frequency: { lifetime: 3 },
trigger: { id: "newtabMessageCheck" },
}
The screens array follows the standard aboutwelcome multistage screen schema. See the about:welcome documentation for the full list of supported screen properties.
Handler Functions
The following functions are injected by MessageWrapper and provide message lifecycle management:
handleClose (Function)
Closes the message and removes it from the DOM without recording any telemetry. The message may appear again in future sessions.
handleDismiss (Function)
Dismisses the message, records a DISMISS telemetry event, and removes it from the DOM. Internally calls handleClose after recording telemetry.
handleBlock (Function)
Permanently blocks the message by adding its ID to ASRouter’s block list. Blocked messages are never shown again across browser restarts. The dismiss button calls both handleBlock and handleDismiss.
handleClick (Function)
Records a CLICK telemetry event for user interaction with the message.
Parameters:
elementId(string, optional): An identifier for the clicked element, used for telemetry tracking.
Telemetry
Impression: fired once by
MessageWrapper’s intersection observer when the component enters the viewport.Screen impression: recorded via
AWAddScreenImpressionwhen each screen becomes active, forwarded toASRouter.addScreenImpressionfor per-screen frequency capping.Click: fired via
AWSendEventTelemetryfor user interactions (e.g. button clicks). IMPRESSION events fromAWSendEventTelemetryare suppressed becauseMessageWrapperhandles the overall message-level impression.Dismiss/Block: fired by
handleDismiss/handleBlockwhen the user clicks the dismiss button.
Strings
Since this component supports train-hopping, its strings must live within newtab.ftl, be statically provided through the messageData object (e.g. { raw: "..." } values in screen content), or be included in the set in l10nURLs for the ASROUTER_MULTISTAGE_MESSAGE external component definition. Usage of new strings in newtab.ftl must be coordinated with the New Tab team to ensure translations are available in the target regions.
The dismiss button string key is newtab-activation-window-message-dismiss-button, defined in newtab.ftl.
Testing
See browser/components/asrouter/tests/browser/browser_asrouter_newtab_multistage_messages.js for browser tests that exercise the component. This test file has the newtab tag and is included in train-hop compatibility CI jobs.