Navigation Examples
This page covers navigation implementation patterns and the URL parameters that the controller reads on initialization.
Navigation Handling Examples
Spaaza’s controller does not handle navigation. It only emits content:select events when users click content. How you respond to those events is up to you. Below are example implementations for different environments.
URL-Driven (Simplest)
Listen to content:select, change window.location.search. Page reloads, controller reads URL params to show correct view.
// spaaza controller emits content:select when user clicks content
document.addEventListener('content:select', (event) => {
const { campaign, voucher } = event.detail;
// your code — preserve auth params and change the navigation params
const params = new URLSearchParams(window.location.search);
if (voucher) {
params.delete('campaign_id');
params.delete('name');
params.set('voucher_id', voucher.id);
window.location.search = params.toString();
} else if (campaign?.image_link) {
if (campaign.image_link.startsWith('http')) {
window.open(campaign.image_link, '_blank'); // external link
} else {
// merge image_link params (e.g. ?campaign_id=123) with existing auth params
const intentParams = new URLSearchParams(campaign.image_link);
intentParams.forEach((value, key) => params.set(key, value));
window.location.search = params.toString();
}
}
});
Two WebViews (React Native)
Listen to content:select, postMessage to native app. Native manages two separate WebView instances (page + detail) and swaps between them.
WebView URLs:
- Page:
elements.html?name=home - Detail:
elements.html?campaign_id=123orelements.html?voucher_id=456
Page WebView — send intent to native:
// spaaza controller emits content:select when user clicks content
document.addEventListener('content:select', (event) => {
const { campaign, voucher } = event.detail;
// your code — forward the click intent to the native app
window.ReactNativeWebView?.postMessage(JSON.stringify({
type: 'navigate',
contentType: voucher ? 'voucher' : 'campaign',
id: voucher?.id || campaign?.id,
imageLink: campaign?.image_link
}));
});
Native side — handle the message:
// your code — native receives the message and loads the detail WebView with URL params
function onWebViewMessage(message) {
const { contentType, id, imageLink } = JSON.parse(message);
if (imageLink?.startsWith('http')) {
Linking.openURL(imageLink); // external link
} else if (contentType === 'voucher') {
showDetailWebView(`?voucher_id=${id}`); // controller reads params on init
} else {
showDetailWebView(`?campaign_id=${id}`); // controller reads params on init
}
}
Back button: Native toggles WebView visibility. No WebView communication needed.
SPA (Client-Managed)
Listen to content:select, set properties on the mounted components to trigger data loading, and manage component visibility yourself. No page reload.
// spaaza controller initializes and mounts both components
const controller = await initializeSpaazaElements({
target: '#spaaza-elements',
config: config,
pageName: 'home',
componentBaseUrl: 'https://elements.spaaza.com/'
});
// your code — get references to both mounted components (see Web Components for IDs)
const pageEl = document.getElementById('spaazaContentPage');
const detailEl = document.getElementById('spaazaContentPageDetail');
// your code — show campaign detail by setting campaignId property
function showCampaignDetail(campaignId) {
detailEl.campaignId = campaignId; // controller reactively fetches campaign data
pageEl.style.display = 'none';
detailEl.style.display = 'block';
}
// your code — show voucher detail by setting voucherId property
function showVoucherDetail(voucherId) {
detailEl.voucherId = voucherId; // controller reactively fetches voucher data
pageEl.style.display = 'none';
detailEl.style.display = 'block';
}
// your code — show page view by setting pageName property
function showPage(name) {
if (name) pageEl.pageName = name; // controller reactively fetches page data
detailEl.style.display = 'none';
pageEl.style.display = 'block';
}
// spaaza controller emits content:select when user clicks content
document.addEventListener('content:select', (event) => {
const { campaign, voucher } = event.detail;
// your code — decide what to show based on the clicked content
if (voucher) {
showVoucherDetail(voucher.id);
} else if (campaign?.image_link) {
const intent = controller.parseImageLink(campaign.image_link);
if (intent.type === 'detail') {
showCampaignDetail(intent.campaignId);
} else if (intent.type === 'page') {
showPage(intent.pageName);
} else if (intent.type === 'external') {
window.open(intent.url, '_blank');
}
}
});
URL Parameters
When using URL-driven navigation, the controller reads these query parameters on initialization to determine what to display.
| Parameter | Required | Description |
|---|---|---|
session_key | Yes | Session key from login |
user_id | Yes | User ID from login |
my_price_app_host | Yes | Spaaza app hostname |
origin | No | API origin (defaults to production) |
name | No | Page name (default: “home”) |
business_id | No | Store ID for filtering |
campaign_id | No | Campaign ID for detail view |
voucher_id | No | Voucher ID for detail view |
Example URLs (staging):
Home page:
https://elements-test01.spaaza.com/demo.html?session_key=KEY&user_id=ID&my_price_app_host=yourapp.spaaza.com&origin=https://apistage0.spaaza.com&name=home
Page filtered by store:
https://elements-test01.spaaza.com/demo.html?session_key=KEY&user_id=ID&my_price_app_host=yourapp.spaaza.com&origin=https://apistage0.spaaza.com&name=home&business_id=3522
Campaign detail page:
https://elements-test01.spaaza.com/demo.html?session_key=KEY&user_id=ID&my_price_app_host=yourapp.spaaza.com&origin=https://apistage0.spaaza.com&campaign_id=4911
Campaign detail page with home route:
https://elements-test01.spaaza.com/demo.html?session_key=KEY&user_id=ID&my_price_app_host=yourapp.spaaza.com&origin=https://apistage0.spaaza.com&campaign_id=4911&name=home