All-in-one widget
Add one script tag to ship login, logout, and personalisation
The Upod browser bundle ships a self-contained widget that handles the entire authentication UI for you — login, logout, account management, and a floating profile panel. You drop one script tag, call upod.initialize(...), and you're done.
After login, you can use the anonymized profile data (gender, age range, residence) to personalise your content.
When to use this
- You want the fastest possible integration
- You don't want to build any login/logout UI yourself
- You want to use anonymized profile data to personalise content on your site
Step 1: Add the script
Include the Upod client bundle in your HTML:
<script src="https://cdn.upod.eu/client/bundle.browser.js"></script>Step 2: Initialize the client
Initialize Upod with the client_id we issued you. The default initialization mounts the floating widget automatically:
<script>
const client = upod.initialize({
authority: 'https://account.upod.eu',
client_id: 'your-client-id',
redirect_uri: location.origin + location.pathname,
post_logout_redirect_uri: location.origin + location.pathname,
});
</script>Pass language: 'nl' in the settings object if you need Dutch UI strings. The default is 'en'.
That's it for the UI — the widget appears as a floating button in the bottom-left once the user logs in, and exposes login, logout, and a view of their anonymized profile.
The widget calls handleCallbackIfNeeded() and manages the session for you,
so you don't need to wire callback handling yourself for the basic case.
Controlling the widget programmatically
The widget starts in the closed state (visible, modal closed) by default. Pass widget: 'hidden' if you want it to stay off until you decide to show it:
const client = upod.initialize({
authority: 'https://account.upod.eu',
client_id: 'your-client-id',
redirect_uri: location.origin + location.pathname,
post_logout_redirect_uri: location.origin + location.pathname,
widget: 'hidden', // 'closed' (default) | 'open' | 'hidden'
});
client.showWidget(); // hidden -> closed: shows the floating button
client.openWidget(); // shows the button and opens its modal
client.hideWidget(); // hides the widget entirely (also closes the modal)These methods are safe to call at any point after initialize() — the widget element is always mounted, just visually hidden when its state is hidden.
Collecting cookie preferences during signup
If your site uses Upod cookie preferences (see Handling users' cookie consent), pass additional_profile: 'cookies' when initializing:
const client = upod.initialize({
authority: 'https://account.upod.eu',
client_id: 'your-client-id',
redirect_uri: location.origin + location.pathname,
post_logout_redirect_uri: location.origin + location.pathname,
additional_profile: 'cookies', // currently the only supported value
});Every login and register action started from the widget — or from your own code via client.login() — then carries the additionalProfile=cookies query parameter. Users who sign up go through an extended registration flow that also records their cookie preferences, so the preferences are available to your site right after their first login. For users who already have an account, logging in works exactly as before.
Step 3: Use the profile data for personalisation
Once a user is logged in, fetch their anonymized profile and personalise your content. Use the onLogin callback so personalisation kicks in both on first login and on subsequent page loads with a live session:
client.onLogin(() => {
client
.fetch({
path: '/storage/profile',
method: 'get',
query: { purpose: 'personalisation' },
})
.then(profile => {
// profile.gender: 'male' | 'female' | 'other'
// profile.ageRange: [number, number | null]
// profile.residence: string (e.g. 'Amsterdam')
personalise(profile);
});
});
client.onLogout(() => {
showGenericContent();
});
function personalise(profile) {
const [minAge] = profile.ageRange;
if (profile.residence.includes('Amsterdam')) {
showAmsterdamHeadlines();
}
if (minAge >= 55) {
showLongFormArticles();
} else {
showShortFormArticles();
}
}Always pass query: { purpose: 'personalisation' } when reading profile
data to personalise on-site content. The storage API enforces access per
purpose — see Purpose values.
Step 4: Apply cookie preferences
If your site has a cookie banner or consent layer, you can read the user's stored cookie preferences and apply them automatically. Unlike profile data, cookie preferences do not require vault consent. Once the user is logged in, you can always fetch them:
client.onLogin(async () => {
const consent = await client.getConsent();
if (consent) {
// Essential (Special Purpose 1) is always on, not returned by the API
// consent.cookiesAndSimilar, consent.advertising, consent.personalisedContent,
// consent.measurement, consent.socialMedia, consent.other (each a boolean)
applyToConsentLayer(consent);
}
});
client.onConsentChange(consent => {
if (consent) {
applyToConsentLayer(consent);
}
});See the Handling users' cookie consent guide for the full field list, TCF mapping, and CMP adapter setup.
Complete example
<!doctype html>
<html>
<head>
<title>My personalised site</title>
<script src="https://cdn.upod.eu/client/bundle.browser.js"></script>
</head>
<body>
<h1>Welcome</h1>
<div id="content">Loading…</div>
<script>
const client = upod.initialize({
authority: 'https://account.upod.eu',
client_id: 'your-client-id',
redirect_uri: location.origin + location.pathname,
post_logout_redirect_uri: location.origin + location.pathname,
});
client.onLogin(() => {
client
.fetch({
path: '/storage/profile',
method: 'get',
query: { purpose: 'personalisation' },
})
.then(profile => {
document.getElementById('content').textContent =
`Showing content for ${profile.gender} in ${profile.residence}`;
});
});
client.onLogout(() => {
document.getElementById('content').textContent =
'Showing generic content.';
});
</script>
</body>
</html>What about server-side personalisation?
client.fetch() only runs in the browser with an active Upod session. To use profile context on a backend, fetch in the browser after login and POST the fields your server needs to your own API. See Server-side and backend use.
Next steps
- Pick a purpose value that matches how you actually use the data
- Read the Anonymized profile data reference for the full schema
- Read Handling users' cookie consent to apply stored consent choices on your site
- If you want the login trigger inside your own UI instead of the floating widget, use
<upod-button>