Firefox Source Docs Logo

Quick search

Overview

  • A Glossary of Common Terms
  • A Quick Guide to Mozilla Applications

Getting Started

  • Getting Set Up To Work On The Firefox Codebase

Working On Firefox

  • Working on Firefox
  • Bug Handling
  • Firefox Crash Reporting

Firefox User Guide

  • 3D view
  • about:debugging
  • Accessibility Inspector
  • Application
  • Browser Console
  • Browser Toolbox
  • Custom Formatters
  • The Firefox JavaScript Debugger
  • Debugger-API
  • Deprecated tools
  • DevTools API
  • DevToolsColors
  • DOM Property Viewer
  • Eyedropper
  • Index
  • JavaScript Tracer
  • JSON viewer
  • All keyboard shortcuts
  • Local Mode
  • Measure a portion of the page
  • Memory
  • Migrating from Firebug
  • Network Monitor
  • Page Inspector
  • Performance
  • Responsive Design Mode
  • Rulers
  • Settings
  • Shader Editor
  • Storage Inspector
  • Style Editor
  • Taking screenshots
  • Tips
  • Toolbox
  • Validators
  • View Source
  • Web Audio Editor
  • Web Console
  • Working with iframes
  • Firefox DevTools User Docs

Source Code Documentation

  • Governance
  • Firefox Front-end
    • How-To’s
    • Address Bar
    • Browser Usage Telemetry
    • Frontend Code Review Best Practices
    • Command Line Parameters
    • Browser Startup
    • Category manager indirection (callModulesFromCategory)
    • CustomizableUI Component
    • Enterprise Policies
    • Web Apps in Firefox
    • Form Autofill
    • Firefox Home (New Tab)
    • Firefox Welcome Experience (about:welcome)
    • Installer
    • Installation Attribution
    • Default Browser Agent
    • Migration
    • PageDataService
    • Places
    • Messaging System
      • Vision
      • What does Messaging System support?
      • Messaging System Overview
      • Message Routing
      • UI Templates
        • ActionOnlyMessage
        • Moments Page
        • Feature Callout
        • Contextual Feature Recommendation
        • About Welcome
        • Infobars
        • Spotlight
        • PrivateBrowsing
        • Multi-Message
        • MenuMessage
        • Sidebar Chatbot Promo
      • Detailed Docs
    • Search UI
    • Tabbed Browser
    • Touch Bar
    • UITour
    • Firefox Branding
    • Storybook for Firefox
    • Reusable UI widgets
    • Other types of UI Widgets
    • Lit
    • XUL and HTML
    • Figma Code Connect
    • Typography
    • Design Tokens
    • Backup Component
    • Sidebar
    • moz-cached-ohttp Protocol
    • Desktop Launcher app
    • Tab Unloading
    • Private Browsing Proxy
    • Installation Directory Layout
  • DOM
  • Editor
  • Style system (CSS) & Layout
  • Graphics
  • Processes, Threads and IPC
  • Getting started
  • Architecture overview
  • Contributing
  • Bugs and issues
  • Firefox DevTools Contributor Docs
  • Toolkit
  • SpiderMonkey
  • JS Loader
  • GeckoView
  • Fenix
  • Focus for Android
  • WebIDL
  • libpref
  • Networking
  • Remote Protocols
  • Services
  • Permissions
  • File Handling
  • Firefox on macOS
  • Firefox on Windows
  • Firefox AI Runtime
  • Accessibility
  • Media Playback
  • Code quality
  • Writing Rust Code
  • Rust Components
  • Gecko Profiler
  • Performance
  • Database bindings (SQLite, KV, …)
  • XPCOM
  • NSPR
  • Web Security Checks in Gecko

The Firefox Build System

  • Mach
  • Pushing to Try
  • Build System
  • Firefox CI and Taskgraph
  • Managing Documentation
  • Vendoring Third Party Components

Testing & Test Infrastructure

  • Automated Testing
  • Understanding Treeherder Results
  • Sheriffed intermittent failures
  • Turning on Firefox tests for a new configuration
  • Avoiding intermittent tests
  • Debugging Intermittent Test Failures
  • Testing Policy
  • Configuration Changes
  • Browser chrome mochitests
  • Chrome Tests
  • Marionette
  • geckodriver
  • Test Verification
  • WebRender Tests
  • Mochitest
  • XPCShell tests
  • TPS
  • web-platform-tests
  • GTest
  • Fuzzing
  • Sanitizer
  • Performance Testing
  • Code coverage
  • Testing & Debugging Rust Code

AI Agent Tools

  • AI Agent Tools for Firefox Development

Releases & Updates

  • Mozilla Update Infrastructure
  • Watershed Updates
  • Desupport Updates
  • Update Verify

Localization & Internationalization

  • Internationalization
  • Localization

Firefox and Python

  • mozbase
  • Using third-party Python packages

Metrics Collected in Firefox

  • Metrics
Firefox Source Docs
  • Firefox Front-end
  • Messaging System
  • Sidebar Chatbot Promo
  • Report an issue / View page source

Sidebar Chatbot Promo

sidebar_chatbot_promo renders a promotional card in the genai chat sidebar, above the summarize button in the sidebar footer.

The chatbot-promo custom element only renders and reports interactions. All messaging-system behavior — content resolution, impressions, button actions and teardown — lives in SidebarChatBotPromo.sys.mjs, which ASRouter dispatches to based on the message template.

Content

Field

Purpose

type

Visual style, passed through to moz-promo

heading

Card heading

message

Card body text

primary_button

Label plus the action to run when clicked

additional_button

Label plus the action to run when dismissed

Use additional_button, not secondary_button. The onboarding provider pre-translates secondary_button labels via Fluent, which breaks on labels that aren’t { string_id }.

Text fields use the localizableText shared definition: either a plain string or { "string_id": "..." }. The { "raw": "..." } form used by multistage screen content is not valid here.

Messages deployed from a Nimbus experiment usually use experiment localization: an $l10n object carrying id, text, and comment. The schema doesn’t need to account for this — Nimbus substitutes the localized string before the message is validated.

A message whose content resolves to nothing at all is a no-op — the surface is wired up, but nothing renders.

Dismissal and blocking

This surface does not block messages on its own. Both buttons run whatever action the message specifies and then hide the card; the message remains eligible until its frequency cap is exhausted.

If the promo should never return once the user has interacted with it, the message must say so with BLOCK_MESSAGE. Use MULTI_ACTION on the primary button to both run the real action and block:

"primary_button": {
  "label": { "string_id": "some-fluent-id" },
  "action": {
    "type": "MULTI_ACTION",
    "data": {
      "actions": [
        { "type": "FXA_AIWINDOW_SIGNIN_FLOW" },
        { "type": "BLOCK_MESSAGE", "data": { "id": "MY_PROMO_ID" } }
      ]
    }
  }
},
"additional_button": {
  "label": { "string_id": "some-other-fluent-id" },
  "action": { "type": "BLOCK_MESSAGE", "data": { "id": "MY_PROMO_ID" } }
}

Targeting

The message is routed by the sidebarToolOpened trigger, which fires for every sidebar tool. Targeting must narrow it to the chat sidebar:

view == 'viewGenaiChatSidebar' && 'browser.ml.chat.provider'|preferenceValue != ''

The browser.ml.chat.provider clause keeps the promo from showing during onboarding, before a chatbot has been selected — otherwise it would render over the onboarding overlay and count impressions the user never really saw. SidebarChatBotPromo.showPromo also returns early when that pref is empty, so test providers that override targeting stay gated too.

sidebarToolOpened is fired from sidebar-main.mjs when the user opens a tool. The promo appears the next time the chat sidebar view is opened.

Targeting is also rewritten automatically: an expression that doesn’t mention isAIWindow becomes ((<your expression>) && !isAIWindow), so a message is Classic-window-only unless it opts in explicitly.

Example JSON

{
  "id": "EXAMPLE_SIDEBAR_CHATBOT_PROMO",
  "template": "sidebar_chatbot_promo",
  "groups": [],
  "targeting": "view == 'viewGenaiChatSidebar' && 'browser.ml.chat.provider'|preferenceValue != ''",
  "trigger": { "id": "sidebarToolOpened" },
  "frequency": {
    "custom": [{ "period": 604800000, "cap": 3 }]
  },
  "content": {
    "type": "default",
    "heading": { "string_id": "example-promo-heading" },
    "message": { "string_id": "example-promo-message" },
    "primary_button": {
      "label": { "string_id": "example-promo-primary-button" },
      "action": { "type": "FXA_AIWINDOW_SIGNIN_FLOW" }
    },
    "additional_button": {
      "label": { "string_id": "example-promo-dismiss-button" },
      "action": { "type": "BLOCK_MESSAGE", "data": { "id": "EXAMPLE_SIDEBAR_CHATBOT_PROMO" } }
    }
  }
}

Schema

SidebarChatBotPromo.schema.json

Testing

No sidebar_chatbot_promo message ships enabled.

Development

Set browser.newtabpage.activity-stream.asrouter.devtoolsEnabled to true, open about:asrouter, find (or edit) a sidebar_chatbot_promo message, and click Show. “Show” passes force, so it opens the chat sidebar to the right tool for you. The Share button copies an about:messagepreview URL that renders the promo for anyone who also has the devtools pref enabled.

QA verification

A test message is available through PanelTestProvider:

  1. Set browser.newtabpage.activity-stream.asrouter.devtoolsEnabled to true.

  2. Set browser.newtabpage.activity-stream.asrouter.providers.panel_local_testing to:

    {"id":"panel_local_testing","type":"local","localProvider":"PanelTestProvider","enabled":true,"cohort":"SHOW_TEST"}
    
  3. Select a chatbot provider — the promo is gated on browser.ml.chat.provider and won’t show during onboarding.

  4. Open the sidebar and click the chatbot icon. The promo appears the next time the chat sidebar view is opened.

Supply a real message via a Nimbus experiment for production.

Related Docs

  • Targeting attributes

  • Guide to targeting with JEXL

  • Frequency and Frequency Caps

  • User actions

  • Triggers

Previous Next

Built with Sphinx using a theme provided by Read the Docs.