How We Built a Preview Period System That Converts 3x Better Than Free Trials
How We Built a Preview Period System That Converts 3x Better Than Free Trials
TL;DR: We replaced traditional free trials with instant previews + smart countdown banners. Users see their website immediately, get 7 days to decide, and receive contextual nudges at the right moments. Conversion rate: 3x higher than our old “pay to see” model.
The Problem: Free Trials Are Broken for Website Builders
Here’s the paradox of website builders: users need to see the final product before buying, but generating a full website costs us real money (AI API calls, storage, compute).
Traditional approaches:
- Pay first, see later: Kills conversion. Nobody pays $19 without seeing results.
- Free trial with account required: Friction. Most users bounce at signup.
- Unlimited free tier: Abuse. Bots generate thousands of sites, costs explode.
We needed something different: Show first, convert later, prevent abuse.
The Insight: Preview Periods > Free Trials
The breakthrough came when we stopped thinking about “trials” and started thinking about “previews.”
Free Trial mindset:
- “You have 7 days to use our product”
- Starts a clock before user sees value
- Requires upfront commitment (account, card)
- Binary: trial expires → access denied
Preview Period mindset:
- “Your website is ready. Take 7 days to decide.”
- User sees value immediately
- No commitment required
- Gradual: preview → gentle nudges → conversion
The difference? Psychological ownership. Your website already exists. It’s yours. You just need to subscribe to keep it live.
How It Works: The Technical Architecture
1. Instant Website Generation (No Auth Required)
// User enters business name → website generates immediately
// No login, no payment, no friction
POST /api/select-business
{
"businessName": "Joe's Pizza Brooklyn"
}
// Returns:
{
"businessId": "joes-pizza-brooklyn",
"previewUrl": "https://joes-pizza-brooklyn.webzum.com",
"previewExpiresAt": "2025-11-04T00:00:00Z"
}
Key decision: Store createdAt timestamp in DynamoDB. Preview period = 7 days from creation, calculated on-the-fly.
2. Preview Period Tracking
Every business record includes:
{
businessId: string;
createdAt: string; // ISO timestamp
subscriptionStatus: 'none' | 'active' | 'canceled';
subscriptionId?: string;
}
Preview period logic:
function getPreviewStatus(business: Business) {
const created = new Date(business.createdAt);
const now = new Date();
const daysSinceCreation = (now - created) / (1000 * 60 * 60 * 24);
const previewDays = 7;
const daysRemaining = Math.max(0, previewDays - daysSinceCreation);
return {
isInPreview: business.subscriptionStatus === 'none',
daysRemaining: Math.floor(daysRemaining),
hoursRemaining: Math.floor(daysRemaining * 24),
hasExpired: daysRemaining <= 0
};
}
3. Smart Banner System
Here’s where it gets interesting. We built a contextual banner plugin that shows different messages based on preview status:
Banner States:
- Fresh preview (6-7 days left): Minimal banner, “Preview Mode”
- Mid-preview (3-5 days left): Gentle reminder with days remaining
- Expiring soon (1-2 days left): Urgent banner with countdown
- Expired (0 days): Modal overlay, “Subscribe to restore access”
Implementation:
// Core banner plugin (injected into generated websites)
class BannerPlugin {
async init() {
const businessId = this.getBusinessIdFromMeta();
const status = await this.fetchPreviewStatus(businessId);
if (status.hasExpired) {
this.showExpiredModal();
} else if (status.isInPreview) {
this.showPreviewBanner(status.daysRemaining);
}
}
showPreviewBanner(daysRemaining: number) {
const urgency = daysRemaining <= 2 ? 'high' :
daysRemaining <= 5 ? 'medium' : 'low';
const banner = this.createBanner({
message: this.getBannerMessage(daysRemaining, urgency),
style: this.getBannerStyle(urgency),
cta: 'Subscribe Now',
ctaUrl: `/billing/subscribe/${businessId}`
});
document.body.prepend(banner);
}
}
4. Real-Time Countdown
The banner updates in real-time using a countdown timer:
// Countdown logic (runs client-side)
function startCountdown(expiresAt: Date) {
setInterval(() => {
const now = new Date();
const remaining = expiresAt - now;
if (remaining <= 0) {
showExpiredModal();
return;
}
const days = Math.floor(remaining / (1000 * 60 * 60 * 24));
const hours = Math.floor((remaining % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = Math.floor((remaining % (1000 * 60 * 60)) / (1000 * 60));
updateBannerText(`${days}d ${hours}h ${minutes}m remaining`);
}, 60000); // Update every minute
}
The Results: 3x Conversion Improvement
Before (pay-to-see model):
- 100 users generate websites
- 12 convert to paid (12% conversion)
- High bounce rate at payment step
After (preview + smart banners):
- 100 users generate websites
- 36 convert to paid (36% conversion)
- Most conversions happen on days 5-7
Why it works:
- Zero friction: No signup, no payment, instant value
- Psychological ownership: “This is MY website”
- Urgency without pressure: Gentle reminders → increasing urgency
- Perfect timing: Users convert when they’re ready, not when we force them
The Technical Challenges
Challenge 1: Preventing Abuse
Problem: Anonymous generation = bot abuse potential
Solution: Rate limiting + fingerprinting
// Rate limit: 3 websites per IP per day
const rateLimiter = new RateLimiter({
windowMs: 24 * 60 * 60 * 1000,
maxRequests: 3,
keyGenerator: (req) => req.ip
});
// Business fingerprinting prevents duplicate generations
const fingerprint = generateFingerprint({
businessName: normalized(input),
location: extracted(input),
type: inferred(input)
});
Challenge 2: Banner Injection Without Breaking Sites
Problem: Injecting banners into user-generated HTML can break layouts
Solution: Shadow DOM + careful positioning
// Create banner in Shadow DOM (isolated styles)
const shadow = bannerContainer.attachShadow({ mode: 'open' });
shadow.innerHTML = `
<style>
/* Isolated styles that won't conflict */
.banner { position: fixed; top: 0; z-index: 999999; }
</style>
<div class="banner">...</div>
`;
// Adjust page content to avoid overlap
document.body.style.paddingTop = '60px';
Challenge 3: Subscription Status Sync
Problem: Banner needs real-time subscription status
Solution: Lightweight API + caching
// API endpoint: /api/business-registry/subscription-status
export async function GET(req: Request) {
const businessId = req.url.searchParams.get('businessId');
const business = await db.getBusiness(businessId);
const previewStatus = getPreviewStatus(business);
return Response.json({
subscriptionStatus: business.subscriptionStatus,
previewStatus,
// Cache for 5 minutes (balance freshness vs. cost)
headers: { 'Cache-Control': 'public, max-age=300' }
});
}
The UX Psychology
Progressive Urgency
Day 1-4: Subtle banner, easy to dismiss
“Preview Mode • 5 days remaining”
Day 5-6: More prominent, countdown visible
“⏰ Your preview expires in 2 days • Subscribe to keep your website live”
Day 7: Urgent, animated
“🚨 Preview expires today! Subscribe now to avoid losing your website”
Day 8+: Modal overlay (can’t dismiss)
“Your preview period has ended. Subscribe to restore access to your website.”
The Conversion Funnel
- Generate (100% of users): Instant website, zero friction
- Explore (80%): User visits their preview site multiple times
- Consider (50%): User sees banner, clicks “Subscribe”
- Convert (36%): User completes payment
Key insight: The banner isn’t annoying—it’s a reminder of value. Users WANT to subscribe because they’ve already fallen in love with their website.
Why This Matters for SaaS
Most SaaS products get the trial period wrong:
Bad: “Start your 7-day free trial” (before seeing product) Good: “Here’s your product. You have 7 days to decide.”
The difference? Value first, commitment second.
The Startup Lesson: Reduce Friction, Increase Value
We learned:
- Remove all barriers to value: No signup, no payment, just instant results
- Let users experience ownership: Generate their actual product, not a demo
- Nudge, don’t nag: Smart timing beats aggressive sales tactics
- Make the right thing easy: Subscribing should feel natural, not forced
What’s Next
We’re exploring:
- Email reminders: “Your website expires in 2 days” (for users who created accounts)
- Usage-based urgency: “You’ve edited your site 12 times—don’t lose your work!”
- Social proof: “127 businesses subscribed this week”
- Extended previews: Reward engagement with extra days
But the core insight remains: Show value first. Convert later. Make it effortless.
Try it yourself: Go to WebZum, enter a business name, watch your website generate. No signup. No payment. Just instant value. Then notice how the preview system works—it’s designed to convert without being pushy.
Building a SaaS? Key takeaway: Your free trial should deliver the actual product, not a limited version. Let users experience ownership before asking for commitment. Then use smart, contextual nudges to convert at the right moment.
The future of SaaS isn’t free trials—it’s instant value + preview periods.