Trial Implementation (SDK v2)
How before-paywall trial works in the legacy Client-Side SDK (wall.x.x.js). Concept and dashboard configuration: Paywall → Trial. For SDK v3, see SDK v3 → Trial.
Regular paywalls only. Tokenized paywalls deposit trial tokens into the user’s balance instead — they don’t use this client-side counter. See Tokenization.
Time-Based Trial Flow
When the user performs a “paid action” and paywall.open() is called:
Technical details:
- First opening — timestamp is saved to
localStorage(orchrome.storagein extensions). - Subsequent openings — SDK checks whether the configured trial duration has elapsed.
- After expiration —
paywall.open()rejects with an error carryingvisibility_reason = 'trial-time'. - Storage location — trial state is local to the device; clearing storage resets the trial.
Action-Based Trial Flow
Same as above, but tracks a counter rather than a timestamp:
Technical details:
- Counter stored in
localStorage/chrome.storageand incremented on eachpaywall.open(). - Limit check — once the counter exceeds the configured number (e.g. 5).
- After exceeding —
paywall.open()rejects withvisibility_reason = 'trial-actions'. - Reset — only by clearing storage or fresh installation.
Handling Trial in Code
Use paywall.getTrialInfo() to read current trial state without triggering the modal:
const trial = await paywall.getTrialInfo();
if (trial.type === 'time') {
const msLeft = trial.expirationEnd - Date.now();
showTrialBanner(`Trial: ${Math.ceil(msLeft / 3600000)} h left`);
} else if (trial.type === 'actions') {
showTrialBanner(`${trial.actionsLeft} free actions remaining`);
}Full signature: paywall.getTrialInfo().
When trial expires and paywall.open() rejects, branch by visibility_reason:
try {
await paywall.open({ resolveEvent: 'success-purchase' });
unlockFeature();
} catch (err) {
switch (err.visibility_status_reason) {
case 'trial-time':
case 'trial-actions':
// trial just expired — paywall is now shown to the user
break;
case 'active-payment-found':
unlockFeature(); // already subscribed
break;
}
}Limitations
- Device-bound — clearing browser data resets the trial.
- No server-side enforcement — the trial check happens in the browser. A determined user can wipe storage to repeat the trial.
- No incognito protection — private mode starts with empty storage, so trial restarts.
For server-enforced trials, use after-paywall trials (free days after payment method capture) — those are stored on the platform and survive storage clears. See dashboard → paywall → trial config.