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 ididentifier: your external user identifier if you set one through Messenger SDK identityhas_email,has_name,has_phone_number: quick hints about what visitor data is already available
Recommended pattern: use identifier or id to fetch richer data
For personalized widget apps, do not depend on the iframe payload alone to render everything.
A stronger pattern is:
- Listen for
oxvo.current_user - Read
payload.identifierorpayload.id - Call your own backend
- 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
identifierorid - 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.originif 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
identifieras the preferred lookup key when you already identify users through Messenger SDK. - Provide a graceful empty state for anonymous visitors when no
identifieris 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
identifieroridsafely? - 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?