Skip to content

Banners

Banners are persistent notification bars that appear at the top or bottom of the viewport. They span the full width of the page and deliver brief, important messages without blocking the user's workflow.

Overview

A banner consists of:

  • Bar -- A full-width strip fixed to the top or bottom of the viewport
  • Message -- Short text content with optional icon
  • Action -- Optional CTA button or link
  • Dismiss -- Close button to remove the banner

Banners are ideal for:

  • System-wide announcements (maintenance windows, new releases)
  • Promotional messages and upgrade prompts
  • Persistent warnings or status notifications
  • Cookie consent or legal notices
  • Trial expiration reminders

Creating a Banner

Via the Admin Panel

  1. Navigate to Content > Banners and click Create Banner.
  2. Write the banner message.
  3. Choose the position (top or bottom).
  4. Select a style variant (info, success, warning, error, or custom).
  5. Add an optional CTA button.
  6. Configure trigger, audience, and scheduling rules.
  7. Click Publish.

Via the API

All non-tour content shares one admin endpoint — POST /v1/admin/content — discriminated by content_type. Note the field name: body, not message.

bash
POST /v1/admin/content
Content-Type: application/json
X-Api-Key: sk_live_...

{
  "content_type": "banner",
  "name": "Maintenance Notice",
  "body": "Scheduled maintenance on Saturday, 10 PM - 2 AM UTC. Some features may be unavailable.",
  "cta": {
    "text": "Learn More",
    "action": "url",
    "url": "/status"
  },
  "trigger": { "trigger_type": "page_load" },
  "schedule": {
    "start": "2025-07-18T00:00:00Z",
    "end": "2025-07-20T02:00:00Z"
  }
}

Banner UI fields like position, variant, icon, dismissible, sticky are handled by the SDK renderer at display time and are configured in the dashboard's banner builder — they aren't part of the wire schema today.

Configuration

FieldTypeRequiredDescription
namestringYesInternal name for the banner
messagestringYesBanner message text (supports limited safe HTML)
positionstringNoWhere the banner appears: top or bottom (default: top)
variantstringNoVisual style: info, success, warning, error, custom (default: info)
iconstringNoIcon to display before the message: info, success, warning, error, none
ctaobjectNoCall-to-action button
dismissiblebooleanNoWhether the banner can be dismissed (default: true)
stickybooleanNoWhether the banner stays fixed on scroll (default: true)
triggerobjectNoWhen to show the banner
audienceobjectNoWho should see the banner
scheduleobjectNoStart and end dates for the banner

Position

Top

The banner appears at the very top of the viewport, above all page content. When sticky is true, it remains fixed during scroll.

json
{ "position": "top" }

TIP

Top banners push page content down. If your application has a fixed header or navigation bar, use the --spot-z-index theme variable to ensure the banner renders at the correct layer.

Bottom

The banner appears at the bottom of the viewport.

json
{ "position": "bottom" }

Style Variants

Each variant applies a distinct colour scheme to the banner:

VariantBackgroundTextIconUse Case
infoBlueWhiteInfo circleGeneral announcements
successGreenWhiteCheck circlePositive confirmations
warningAmber/orangeDarkWarning triangleMaintenance, caution
errorRedWhiteError circleCritical issues
customUses theme variablesUses theme variablesNoneBrand-specific styling
json
{ "variant": "warning" }

Custom Variant Styling

When using the custom variant, the banner inherits from your theme variables:

VariableEffect
--spot-primaryBanner background colour
--spot-primary-textBanner text colour
--spot-radiusBanner corner radius (set to 0 for edge-to-edge)

CTA Button

Add an action button to the banner:

json
{
  "cta": {
    "text": "Upgrade Now",
    "action": "url",
    "url": "/billing/upgrade"
  }
}

CTA actions:

ActionDescription
urlNavigate to a URL
dismissClose the banner
trackFire a custom event and close

Dismissal

When dismissible is true, a close button (X) appears on the right side of the banner. The user can click it to dismiss the banner.

Once dismissed, the banner's progress state is recorded. The banner will not reappear for that user on subsequent page loads (unless demoMode is enabled).

Set dismissible: false for banners that must remain visible (e.g., legal notices, critical system alerts):

json
{
  "dismissible": false
}

WARNING

Non-dismissible banners stay visible until the schedule ends or the banner is unpublished by an admin. Use sparingly -- persistent, non-dismissible UI is a poor user experience if overused.

Scheduling

Banners support start and end dates for time-limited messages:

json
{
  "schedule": {
    "start": "2025-12-20T00:00:00Z",
    "end": "2025-12-26T00:00:00Z"
  }
}

The banner is only shown between the start and end timestamps (inclusive). Outside this window, the banner does not render. This is evaluated server-side, so the banner is not included in the SDK content response outside the schedule.

Sticky Behaviour

When sticky is true (default), the banner is fixed to the viewport edge and remains visible during scroll. When false, the banner scrolls with the page content.

json
{ "sticky": false }

Rich Content

Banner messages support limited safe HTML for inline formatting:

json
{
  "message": "New feature: <b>PDF Export</b> is now available. <a href='/docs/export' target='_blank'>Learn how to use it</a>."
}

Supported tags in banners: b, i, strong, em, a, br, span.

TIP

Keep banner messages concise -- one or two sentences maximum. For detailed content, use a CTA button that links to a full page or opens a modal.

Multiple Banners

Multiple banners can be active simultaneously. When more than one banner targets the same position (e.g., two top banners), they stack vertically in the order they were triggered.

WARNING

Stacking more than two banners at the same position creates a poor user experience. Use audience targeting and scheduling to avoid showing multiple banners simultaneously.

Programmatic Control

Banners fire on their trigger + audience + schedule rules. Hook content:dismiss to react when one closes:

js
Spotlight.on('content:dismiss', (data) => {
  console.log(`User dismissed content: ${data.contentId}`);
});

Styling

Banners inherit --spot-* theme variables. For the custom variant, key variables include:

VariableEffect
--spot-primaryBackground colour (custom variant)
--spot-primary-textText colour (custom variant)
--spot-font-size-smBanner text size
--spot-font-weight-mediumBanner text weight
--spot-z-indexBanner stacking order

Accessibility

  • Banners use role="alert" for important messages and role="status" for informational messages.
  • The dismiss button has aria-label="Dismiss banner".
  • Banner text colour and background colour meet WCAG AA contrast requirements for all built-in variants.
  • Keyboard users can tab to the CTA button and dismiss button.

Spotlight