Skip to main content

Widget SDK

The Widget SDK is a small JavaScript library that you embed directly in your website. It provides builders for rendering a payment button that opens the Vipps MobilePay app on mobile devices and a payment dialog on desktop devices, as shown below.

Screenshots showing the flow: 1. The merchant's checkout page with Vipps selected as the payment method. The dialog is not yet open. 2. A dialog showing a phone number entry form. The checkout page is visible and dimmed behind the dialog. 3. A dialog prompting the customer to open the Vipps app to complete the payment.

The button's appearance is served by the SDK, ensuring it always reflects the current Vipps MobilePay design guidelines and the correct brand for your market.

Installation​

Include the Widget SDK script on your page. The SDK exposes a global window.vipps object.

<script src="https://cdn.vippsmobilepay.com/js/widget-sdk/vipps-widget.js"></script>

Quick start​

Start a desktop host on the top-level page, then add a payment trigger:

vipps.host().start();

vipps
.trigger(async () => {
const { paymentUrl } = await fetch("/api/create-session").then((r) => r.json());
return paymentUrl;
})
.button()
.mount("#pay-button");

Calling .button() on the trigger returns a pre-wired payment button. Clicking it asks the top-level host to open a desktop payment dialog; if no host accepts the request, it falls back to a full-page redirect. On mobile and tablet, it redirects directly. On success or cancel, the SDK automatically closes the dialog and redirects the page.

By default, the desktop modal close button cancels the payment. This is the recommended behavior for most integrations.

If you want customers to close only the modal and keep the payment active, pass cancelPaymentOnClose: false:

vipps
.trigger(createSession, {
cancelPaymentOnClose: false,
})
.button()
.mount("#pay-button");

With this option, the modal close button only closes the modal. A cancel action from inside the payment iframe still cancels the payment.

Use the "close" event if you need custom handling when the modal is closed without canceling the payment:

vipps
.trigger(createSession, {
cancelPaymentOnClose: false,
})
.on("close", () => {
// The modal has been closed. Add custom cleanup, analytics,
// or UI updates here.
})
.button()
.mount("#pay-button");

The SDK closes the modal before calling your "close" handler. The payment remains active, and your handler only reacts to the closed modal.

Custom event handling​

Override the default success or cancel behavior by chaining .on() before .button():

vipps
.trigger(async () => {
const { paymentUrl } = await fetch("/api/create-session").then((r) => r.json());
return paymentUrl;
})
.on("success", (close, redirectUrl) => {
close();
analytics.track("payment_success");
window.location.href = redirectUrl ?? "/thank-you";
})
.on("cancel", (close) => {
close();
})
.button()
.mount("#pay-button");

Branding​

Switch between Vipps and MobilePay by calling .brand() on the button:

vipps.trigger(createSession).button().brand("mobilepay").mount("#pay-button");

Trigger API​

The trigger builder starts a Vipps/MobilePay payment flow. On desktop, it asks the top-level host to open a modal dialog; on mobile and tablet, it redirects directly to the payment page.

By default, the trigger automatically closes and redirects the page when a success or cancel event is received. Call .on() to override either default.

The builder accepts a resolver function that returns (or resolves to) the payment URL. The resolver is called each time .open() is invoked, so a fresh session URL is fetched on every attempt. The builder returns a TriggerHandlerBuilder interface:

Method / PropertyDescription
.on(event, callback)Override the callback for "success" or "cancel", or react to "close" when cancelPaymentOnClose is false.
.button()Return a VippsButtonBuilder pre-wired to this trigger. Clicking the button calls .open() automatically.
.open()Start the trigger. Calls the resolver to get the payment URL, then asks the host to show the modal (desktop) or redirects (mobile/tablet).
.close()Programmatically close the trigger.
.isOpenRead-only boolean indicating whether the trigger is currently open.

Desktop behavior​

On desktop, the top-level host renders a modal <dialog> with an embedded <iframe> pointing to the payment URL. The dialog supports:

  • A close button in the top-right corner
  • Dynamic resizing based on messages from the iframe content

Mobile behavior​

On mobile and tablet devices, the trigger redirects the current page to the payment URL instead of opening a modal. Event callbacks registered with .on() do not fire on mobile — the customer is redirected to the URL provided at session creation.

Host API​

Use the Host API on the top-level page that should display desktop payment dialogs. Without a host, desktop triggers fall back to a full-page redirect. This applies to hosted desktop triggers, including triggers running inside embedded iframes.

The host owns desktop dialog hosting only. Mobile and tablet payment launch should stay in the user's click flow and should not be delegated through postMessage.

Start a desktop host on the top-level page:

const host = vipps.host();
host.start();

The host opens payment URLs in the same desktop dialog used by normal triggers, and forwards success, cancel, close, or error responses back to the requesting frame.

Method / PropertyDescription
vipps.host()Create a desktop host.
host.start()Start listening for child-frame trigger requests.
host.stop()Stop listening for child-frame trigger requests.

Button API​

The button builder creates and mounts Vipps/MobilePay payment buttons into the DOM. Most integrations should use trigger.button() (see Quick start above) rather than creating a standalone button.

The SDK renders a lightweight placeholder button immediately, then upgrades it to the full <vipps-mobilepay-button> web component once the component definition is registered. This ensures the button is visible before the web component scripts finish loading.

Standalone usage​

vipps
.button()
.brand("vipps")
.mount("#pay-button-container")
.triggers(async () => {
// Handle payment initiation
});

API​

The builder returns a chainable VippsButtonBuilder interface:

MethodDescription
.brand(value)Set the brand — "vipps" or "mobilepay".
.language(value)Set the language — "no", "en", "da", "fi", or "sv". Defaults to the user's preferred language.
.verb(value)Set the call to action — "pay", "login", "register", "continue", "confirm", "donate", "express", or "buy". Defaults to "pay".
.variant(value)Set the color variant — "primary", "dark", or "light". Defaults to "primary".
.type(value)Set the button type — "button" or "submit". Defaults to "button".
.compact(value)Toggle the compact (logo-only) layout. Defaults to false.
.rounded(value)Toggle fully rounded corners. Defaults to true.
.stretched(value)Toggle full-width (stretched) layout. Defaults to false.
.continueAsFirstName(name)Set the name shown by the "continue" verb (e.g. "Continue as Ada").
.mount(selector)Mount button(s) into all elements matching the CSS selector.
.triggers(target)Connect the button to a trigger target. Clicks call .open().
.onclick(handler)Register an additional click handler. The handler can be sync or async.
.rerender()Re-mount the button at the previously used selector.
.unmount()Remove the button(s) from the DOM and detach event listeners.
.toElement()Return the raw button HTMLElement without mounting it.

All presentation methods are chainable and can be called before or after .mount(). For example:

vipps
.trigger(createSession)
.button()
.brand("mobilepay")
.verb("express")
.variant("dark")
.stretched(true)
.mount("#pay-button");
note

On desktop, the button is rendered in an iframe hosted on the Vipps domain, which currently only honors brand, language, and verb. The remaining presentation methods apply to the button rendered directly on the page (mobile/tablet and toElement() on mobile).