Quickstart
Show a screen from a placement on your site, pass it prices, and run your own checkout when someone buys.
This page takes you from a published screen to a working screen on your site. It uses a placement, so you can change the screen later without a deploy.
What you need
- A published screen and a placement that points at it. See Placements.
- A public key from Install SDK or API keys.
- The IDs of the packages on the screen. Each package card has an ID set in the editor (see Packages and pricing). The Install SDK page lists them for the screen you pick.
Show the screen
Add the script and set your key. Use the URL that the Install SDK page shows.
<script src="https://sdk.miniwall.app/ui-kit.iife.js"></script>
<script>
UIKit.configure({ apiKey: 'pk_...' });
</script>Open the screen from a button. Pass a price for every package ID on the screen, and run your checkout in onPurchase.
<button id="upgrade">Upgrade</button>
<script>
document.querySelector('#upgrade').addEventListener('click', async () => {
const result = await UIKit.presentPaywall({
paywall: { placement: 'upgrade_button' },
products: {
monthly: { price: 9.99, currency: 'USD', period: 'month' },
annual: { price: 59.99, currency: 'USD', period: 'year' },
},
onPurchase: async ({ packageId }) => {
// Your checkout (Stripe, Paddle, your backend...).
// Return true when paid, false when the visitor cancelled. Throw on failure.
return startCheckout(packageId);
},
});
console.log(result);
});
</script>Handle the result. presentPaywall always resolves with an object whose outcome tells you what happened:
if (result.outcome === 'purchased') unlockPro(result.packageId);
if (result.outcome === 'skipped') console.log('Not shown:', result.reason);That is a complete integration. The paywall opens as a popup (or in the format you chose on the placement), shows your prices, calls onPurchase when the visitor taps buy, and closes.
Results you can get
outcome | When | Extra fields |
|---|---|---|
purchased | onPurchase finished without returning false. | packageId, answers if any |
restored | onRestore finished without returning false. | answers if any |
closed | The visitor closed the screen (close button, Esc, backdrop click, or a toast timing out). | answers if any |
action | A "Run your code" button was pressed and onAction did not return false. | actionId, answers if any |
skipped | The placement's targeting chose to show nothing. Nothing opened. | reason: frequency_cap, audience or holdout |
Make it show by itself
If you set a trigger on the placement (for example "After 10 seconds"), call startAutoPlacements() once instead of calling presentPaywall yourself.
<script>
UIKit.startAutoPlacements({
products: { monthly: { price: 9.99, currency: 'USD', period: 'month' } },
onPurchase: async ({ packageId }) => startCheckout(packageId),
});
</script>See Auto placements.
Show a screen inline
Put a screen inside your pricing section with mountPaywall, or with the <uikit-paywall> tag.
<uikit-paywall placement="pricing" api-key="pk_..."></uikit-paywall>
<script>
const el = document.querySelector('uikit-paywall');
el.products = { annual: { price: 59.99, currency: 'USD', period: 'year' } };
el.onPurchase = async ({ packageId }) => startCheckout(packageId);
el.addEventListener('uikit-purchased', (event) => unlockPro(event.detail.packageId));
</script>See Mount a paywall and Web component.
React
import { configure } from '@ui-kit/web';
import { usePaywall } from '@ui-kit/react';
configure({ apiKey: 'pk_...' });
export function UpgradeButton() {
const present = usePaywall({ products });
return (
<button
onClick={async () => {
const result = await present({ paywall: { placement: 'upgrade_button' }, onPurchase: ({ packageId }) => checkout(packageId) });
if (result.outcome === 'purchased') unlockPro();
}}
>
Upgrade
</button>
);
}See React.
If something does not show
- Open the browser console. The SDK logs a warning if a package ID has no price:
[UIKit] No price for package(s) .... - A rejected promise with
UIKit: Placement not foundmeans the key does not match a placement.Published paywall not foundmeans the screen was never published. - A 403
origin_not_allowedmeans your site is not in Allowed websites. - See Errors for every message.