The Web Offerwall JavaScript SDK: Complete Integration Guide (2026)
Published August 22, 2026 — by the Perkox Developer Team
Offerwalls are not just for mobile apps. If you run a web application, a browser game, a PWA, or any site with a virtual currency or premium content system, an offerwall lets your users earn rewards by completing surveys, downloading apps, signing up for trials, and more. The Perkox Web Offerwall JavaScript SDK makes this straightforward: a single script tag or npm package gives you a full offerwall experience with reward callbacks, cross-origin safety, and server-side postback support.
This guide covers the full integration from prerequisites to production: installation (script tag or npm), initialization, showing the offerwall in iframe or popup mode, handling rewards client-side, setting up server-side postbacks, managing cross-origin communication, testing, debugging, and a five-question FAQ.
New to offerwalls? Read our introduction to offerwalls first. For mobile integrations, see the Android SDK guide. For the server-side reward flow, our postback guide is essential reading. You may also find the Dynamic API guide useful for server-side offer fetching, and the security best practices guide for protecting your integration.
Table of Contents
- Prerequisites
- Installation (Script Tag or npm)
- Initialization
- Showing the Offerwall (iframe vs popup)
- Handling Rewards Client-Side
- Server-Side Postback Setup
- Cross-Origin Considerations
- Testing and Debugging
- FAQ
1. Prerequisites
The Perkox Web SDK has minimal requirements, making it suitable for everything from static sites to complex SPAs:
| Requirement | Details |
|---|---|
| Perkox Publisher Account | Required — sign up free at Perkox |
| App ID & API Key | Available in the Perkox dashboard after registering your web app |
| Domain Registration | Register your site’s domain(s) in the dashboard for postMessage security |
| JavaScript Environment | Any modern browser (ES2020+). No framework required. |
| Backend Server | Required for postback verification and user crediting |
| HTTPS | Required in production. The SDK works on localhost over HTTP for development. |
yourapp.com, www.yourapp.com) in the Perkox dashboard under App Settings → Allowed Origins. This prevents unauthorized sites from embedding your offerwall.
2. Installation (Script Tag or npm)
Perkox offers two installation methods depending on your build setup.
2.1 Script Tag (for static sites, vanilla JS, or non-bundled projects)
Add the SDK script tag in the <head> or before your closing </body> tag:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Web App</title>
<!-- Perkox Web SDK -->
<script src="https://cdn.perkox.com/sdk/web/perkox-offerwall.min.js"></script>
</head>
<body>
<!-- Your app content -->
<script>
// Access via window.PerkoxOfferwall
PerkoxOfferwall.initialize({
appId: 'your-app-id',
apiKey: 'your-api-key',
userId: 'user-12345',
});
</script>
</body>
</html>
2.2 npm / yarn (for bundled projects: React, Vue, Angular, Svelte, etc.)
npm install @perkox/web-offerwall
# or
yarn add @perkox/web-offerwall
# or
pnpm add @perkox/web-offerwall
Then import in your application:
// ES module import
import { PerkoxOfferwall } from '@perkox/web-offerwall';
// CommonJS
const { PerkoxOfferwall } = require('@perkox/web-offerwall');
The npm package ships with full TypeScript definitions, so you get type safety in TS projects out of the box.
3. Initialization
Initialize the SDK once after your page or app loads. The initialization call configures the SDK with your credentials and sets the current user. This must happen before you show the offerwall.
import { PerkoxOfferwall } from '@perkox/web-offerwall';
// Initialize with your credentials
PerkoxOfferwall.initialize({
appId: 'your-app-id',
apiKey: 'your-api-key',
userId: 'user-12345', // your internal user ID
isTestMode: false, // set to true for development
logLevel: 'error', // 'none' | 'error' | 'info' | 'debug'
onReady: () => {
console.log('Perkox SDK ready');
},
onError: (error) => {
console.error('Perkox SDK error:', error);
},
});
TypeScript Interface
interface PerkoxWebInitOptions {
appId: string;
apiKey: string;
userId: string;
isTestMode?: boolean;
logLevel?: 'none' | 'error' | 'info' | 'debug';
customParams?: Record<string, string>;
onReady?: () => void;
onError?: (error: PerkoxError) => void;
}
interface PerkoxError {
code: string;
message: string;
}
initialize() in a top-level useEffect. In Vue, call it in onMounted of your root component. In Angular, call it in ngOnInit of your AppComponent. Initialize once, not on every route change.
4. Showing the Offerwall (iframe vs popup)
The web SDK supports two display modes: iframe (embedded inline) and popup (full-screen overlay window). Choose based on your UX needs.
4.1 iframe Mode (Embedded)
Iframe mode renders the offerwall inside a container element on your page. This is ideal for a dedicated “Earn Rewards” section within a web app.
// HTML: create a container
// <div id="perkox-offerwall-container" style="width:100%;height:600px;"></div>
PerkoxOfferwall.showOfferwall({
mode: 'iframe',
container: document.getElementById('perkox-offerwall-container'),
placement: 'rewards_page',
onClose: () => {
console.log('Offerwall closed');
},
});
The iframe fills the container’s dimensions. Set your container’s width and height via CSS to control the offerwall’s size.
4.2 Popup Mode (Full-Screen Overlay)
Popup mode opens a full-screen modal overlay on top of your page. This is better for mobile web and for button-triggered flows where you want the offerwall to take over the screen.
document.getElementById('earn-button').addEventListener('click', () => {
PerkoxOfferwall.showOfferwall({
mode: 'popup',
placement: 'header_button',
onClose: () => {
console.log('Offerwall closed');
},
});
});
4.3 Comparison
| Feature | iframe Mode | popup Mode |
|---|---|---|
| Display | Embedded in container | Full-screen overlay |
| Best for | Rewards section in a web app | Button-triggered flow |
| Mobile web | Works but needs responsive container | Excellent — uses full viewport |
| User dismissal | Controlled by your page | Close button in overlay |
| Nesting | Inside your layout | Above all content (z-index: 2147483647) |
4.4 Checking Offer Availability
const hasOffers = await PerkoxOfferwall.hasOffersAvailable();
if (hasOffers) {
// Show "Earn Rewards" button
document.getElementById('earn-button').style.display = 'block';
} else {
document.getElementById('earn-button').style.display = 'none';
}
5. Handling Rewards Client-Side
The SDK emits events when a user earns a reward, opens the offerwall, closes it, or encounters an error. Subscribe to these events to update your UI in real time — for example, showing a “You earned 50 coins!” toast or refreshing the user’s balance display.
import { PerkoxOfferwall, PerkoxEvents } from '@perkox/web-offerwall';
// Subscribe to reward events
PerkoxEvents.on('reward', (reward) => {
console.log('Reward earned:', reward);
showToast(`You earned ${reward.payout} coins!`);
refreshUserBalance();
});
PerkoxEvents.on('offerwallOpen', () => {
console.log('Offerwall opened');
});
PerkoxEvents.on('offerwallClose', () => {
console.log('Offerwall closed');
});
PerkoxEvents.on('error', (error) => {
console.error('Perkox error:', error);
});
// Unsubscribe when done (e.g., in React useEffect cleanup)
// PerkoxEvents.off('reward', handler);
Reward Object Structure
interface PerkoxReward {
transactionId: string; // unique per completion
offerId: string;
offerName: string;
payout: number; // in your virtual currency units
payoutUSD: number; // in USD cents
userId: string;
timestamp: number; // Unix epoch ms
}
reward events via the browser console. Always credit actual balances based on the server-side postback. Use client events only for instant UI feedback — then reconcile with the postback.
6. Server-Side Postback Setup
The postback is the authoritative reward channel. When a user completes an offer, Perkox sends an HTTP request to your backend with transaction details and a cryptographic signature. Your server verifies the signature and credits the user.
Configuring the Postback URL
In the Perkox dashboard, navigate to App Settings → Postback and enter your endpoint:
https://api.yourapp.com/perkox/postback?user_id={user_id}&txn_id={txn_id}&payout={payout}&offer_id={offer_id}&signature={signature}
Server-Side Verification (Node.js / Express)
const express = require('express');
const crypto = require('crypto');
const app = express();
const PERKOX_SECRET = 'your-postback-secret';
app.get('/perkox/postback', async (req, res) => {
const { user_id, txn_id, payout, offer_id, signature } = req.query;
// Reconstruct signature
const data = `${user_id}${txn_id}${payout}${offer_id}`;
const expectedSig = crypto
.createHmac('sha256', PERKOX_SECRET)
.update(data)
.digest('hex');
if (signature !== expectedSig) {
console.error('Invalid postback signature');
return res.status(403).send('Invalid signature');
}
// Idempotency check — prevent double-crediting on retries
const existing = await db.transactions.findById(txn_id);
if (existing) {
return res.status(200).send('OK'); // Already processed
}
// Store transaction and credit user
await db.transactions.create({ id: txn_id, userId: user_id, amount: payout });
await creditUser(user_id, parseInt(payout, 10));
res.status(200).send('OK');
});
app.listen(3000);
User ID Consistency
The userId you pass to initialize() on the client must match the user_id that appears in the postback. Use a stable, server-assigned user ID — never a random ID generated in the browser, because that ID would not survive a page reload or device switch.
// Good: fetch user ID from your backend
const user = await fetchCurrentUser();
PerkoxOfferwall.initialize({
appId: 'your-app-id',
apiKey: 'your-api-key',
userId: user.id, // stable backend ID
});
7. Cross-Origin Considerations
The Perkox web SDK uses postMessage for cross-origin communication between your page and the offerwall iframe/popup. This means you do not need to configure CORS headers on your server. However, there are a few things to keep in mind:
7.1 Allowed Origins
Register every domain where you will use the SDK in the Perkox dashboard. For example, if your app runs on both yourapp.com and www.yourapp.com, add both. The SDK checks the origin of incoming postMessage events and ignores messages from unregistered origins for security.
7.2 HTTPS Requirement
In production, the SDK requires HTTPS. Mixed-content browsers will block the offerwall iframe if your page is served over HTTP but the offerwall is HTTPS. For local development, http://localhost and http://127.0.0.1 are allowed automatically.
7.3 Content Security Policy (CSP)
If your site uses a Content Security Policy, add the Perkox CDN and offerwall domain to your script-src and frame-src directives:
Content-Security-Policy:
script-src 'self' https://cdn.perkox.com;
frame-src 'self' https://offerwall.perkox.com;
connect-src 'self' https://api.perkox.com;
7.4 Subdomain Handling
If your app runs on wildcard subdomains (e.g., *.yourapp.com), register each subdomain or use the wildcard option in the dashboard. The SDK validates origins exactly, so app.yourapp.com and www.yourapp.com are treated as different origins.
8. Testing and Debugging
8.1 Test Mode
Enable test mode to display test offers that convert instantly. This lets you verify the full flow — show offerwall, complete offer, receive client event, receive postback — without real offer latency.
PerkoxOfferwall.initialize({
appId: 'your-app-id',
apiKey: 'your-api-key',
userId: 'test-user-1',
isTestMode: true,
logLevel: 'debug',
});
8.2 Log Levels
| Level | Output |
|---|---|
none |
No logs |
error |
Errors only (production default) |
info |
Errors + lifecycle events |
debug |
Verbose logs including postMessage traffic |
8.3 Browser DevTools
With logLevel: 'debug', the SDK logs all postMessage events to the console. You can also inspect the offerwall iframe directly in DevTools → Elements to see its DOM, and use the Network tab to watch API calls to api.perkox.com.
8.4 Postback Testing
Use the Postback Tester in the Perkox dashboard to send a test postback to your server. This verifies your endpoint, signature validation, and idempotency logic without completing a real offer. For server-side offer fetching and dynamic offer customization, see the Dynamic API guide.
8.5 Common Issues
| Issue | Cause | Fix |
|---|---|---|
| Offerwall iframe blank | Domain not registered in dashboard | Add your domain to Allowed Origins |
| CSP blocking the SDK | Content Security Policy too restrictive | Add cdn.perkox.com and offerwall.perkox.com to CSP |
| No reward event received | Event listener added after offerwall opened | Subscribe to events before calling showOfferwall() |
| Postback not received | Endpoint unreachable or not returning 200 | Test with curl, check server logs, ensure 200 response |
| Mixed content warning | Page on HTTP, SDK on HTTPS | Serve your page over HTTPS in production |
| Popup blocked by browser | Popup mode called outside user gesture | Call showOfferwall() inside a click handler |
9. FAQ
Should I use the iframe or popup display mode?
Use the iframe mode when you want the offerwall embedded inside a container on your page, such as a rewards section in a web app. Use the popup mode when you want a full-screen experience triggered by a button click. The popup mode is better for mobile web because it gives offers the full viewport.
Can I use the SDK with a bundler like Webpack or Vite?
Yes. The SDK is published on npm as @perkox/web-offerwall with full ESM and CommonJS support. Install it with npm or yarn and import it in your bundle. The script tag method is available for non-bundled sites.
Do I need a backend server, or can I handle everything client-side?
You need a backend server for secure reward crediting. The client-side SDK handles displaying the offerwall and emitting reward events for UX, but the actual crediting must happen via a server-side postback that you verify with an HMAC signature. Crediting based on client-side events alone is insecure.
Does the SDK work across different domains and subdomains?
Yes. The SDK uses postMessage for cross-origin communication between your page and the Perkox offerwall iframe/popup. No special CORS headers are needed on your server. You do need to register your domain(s) in the Perkox dashboard so the SDK accepts postMessage events from your origin.
Is the web SDK free to use?
Yes. The SDK is free to install and use. Perkox operates on a revenue-share model — you earn a percentage of each completed offer. There are no upfront costs, monthly fees, or minimum commitments.
Conclusion
The Perkox Web Offerwall JavaScript SDK gives web developers a clean, framework-agnostic way to integrate offerwall monetization. Whether you prefer a script tag or an npm package, an inline iframe or a full-screen popup, the SDK adapts to your architecture. With secure cross-origin communication via postMessage, typed event listeners, and a robust server-side postback system, you can go from install to first reward in a single afternoon.
Pair the web SDK with the server-side Dynamic API for maximum control over which offers your users see, and always follow the security best practices to protect your integration from abuse.
Ready to monetize your web app?
Create your free Perkox publisher account and get your API keys in minutes.
Related guides: What is an Offerwall? · Android SDK Guide · Postback Guide · Dynamic API Guide · Security Best Practices
