Skip to main content

Build widget apps and embedded experiences

Widget apps turn the Messenger home screen into a small support surface, not just a launcher for chat.

Instead of sending customers to another tab, you can open an embedded page directly inside the widget for common tasks like watching a walkthrough, booking time with support, or viewing account-specific information.

For supported status providers, OXVO can go one step further and render the current status directly on the widget home screen, then open a native status detail view inside the widget instead of a generic iframe.

Where to configure widget apps

Open:

  • Settings → Channels
  • Choose your Website inbox
  • Go to User Engagement → Applications

From there you can start with a template, save reusable apps to your library, and turn them on for a specific widget.

Good widget app use cases

The best widget apps solve a focused job in a few seconds:

  • Walkthrough video: product tour, setup checklist, or troubleshooting clip
  • Booking flow: onboarding session, office hours, renewal call, or escalation booking
  • Status update: outage banner, maintenance page, or uptime dashboard
  • Feedback capture: bug report, NPS, feature request, or churn survey
  • Personalized portal: account summary, order tracker, billing view, onboarding progress

If the experience needs deep navigation or a full application shell, link out instead of forcing the widget to behave like a full product workspace.

Native status integrations

OXVO supports a more integrated status experience for:

  • Atlassian Statuspage
  • Better Stack
  • Instatus

These templates behave differently from a normal embedded app:

  • The current status is shown directly on the widget home screen
  • Clicking the app opens a native detail view with incidents, maintenance, and service health
  • Visitors can still open the full provider status page when they need deeper history or subscription options

Behind the scenes, OXVO reads each provider's public status feed:

  • Atlassian Statuspage: /api/v2/summary.json
  • Better Stack: /index.json
  • Instatus: /summary.json

Use Custom status page when you want to embed your own status or incident page as a regular iframe app. Use one of the provider templates above when you want the smoother, native status experience.

How embedded apps receive visitor context

When a visitor opens an iframe-based widget app, OXVO loads your app inside an iframe and posts a message to it.

Current event shape:

{
source: 'oxvo-app',
type: 'oxvo.current_user',
payload: {
id: 42,
identifier: 'customer_123',
has_email: true,
has_name: true,
has_phone_number: false
}
}

This payload is intentionally lightweight. In practice, the most useful fields are:

  • id: internal OXVO contact id
  • identifier: your external user identifier if you set one through Messenger SDK identity
  • has_email, has_name, has_phone_number: quick hints about what visitor data is already available

For personalized widget apps, do not depend on the iframe payload alone to render everything.

A stronger pattern is:

  1. Listen for oxvo.current_user
  2. Read payload.identifier or payload.id
  3. Call your own backend
  4. Render account, order, billing, or onboarding data from your source of truth

That keeps the widget payload small while still letting you build useful customer-facing tools.

Listener example

<script>
window.addEventListener('message', async event => {
const message = event.data || {};

if (message.source !== 'oxvo-app') return;
if (message.type !== 'oxvo.current_user') return;

const visitor = message.payload || {};
const lookupKey = visitor.identifier || visitor.id;
if (!lookupKey) return;

const response = await fetch(
`/api/widget-portal?key=${encodeURIComponent(lookupKey)}`
);
const account = await response.json();

renderAccountPortal(account);
});
</script>

Example: personalized billing or order portal

This is a strong fit for widget apps because the user is already in a support context.

A practical flow:

  • Visitor opens Account status or Track my order
  • Your page receives oxvo.current_user
  • Your app looks up the customer by identifier or id
  • You render invoices, shipment checkpoints, renewal details, or onboarding blockers
  • The customer stays inside the widget while your team remains one click away in chat

This works especially well for:

  • subscription billing questions
  • shipping or delivery updates
  • onboarding task completion
  • plan or seat usage checks

Example: embed-first apps that need no personalization

Some widget apps are useful even without visitor lookup:

  • YouTube or Vimeo walkthroughs
  • Loom answer videos
  • changelog or release note pages
  • native status integrations for Statuspage, Better Stack, or Instatus
  • custom status pages
  • booking pages
  • feedback forms

These are often the fastest apps to launch because they only need an embed-friendly URL plus a clear title and description.

Production guidelines

  • Keep iframe apps lightweight. Widget apps open in a compact mobile-sized surface.
  • If you use a native status integration, confirm the provider exposes a stable public JSON feed and that the public page URL is correct.
  • Make sure iframe-based providers allow iframe embedding. Many public pages still block iframes.
  • Validate event.origin if your app is exposed on the public internet.
  • Do not put secrets in the iframe page or depend on frontend-only authorization for sensitive account data.
  • Treat identifier as the preferred lookup key when you already identify users through Messenger SDK.
  • Provide a graceful empty state for anonymous visitors when no identifier is available yet.

Launch checklist

  • Does the page render well at widget size on desktop and mobile?
  • If this is an iframe app, does the provider allow iframe embedding in production?
  • If this is a native status integration, does the public status feed resolve correctly from the real widget?
  • Does your app handle missing identifier or id safely?
  • Is the first screen focused on one support job instead of a full navigation tree?
  • Have you tested the open flow from the real widget, not just the standalone page?