Tutorial: Show a Trial-Ending Countdown
In this tutorial, you’ll show a trial-ending banner that counts down the final days of a user’s trial and prompts them to upgrade before it expires. Takes about 10 minutes.
What You’ll Build
Section titled “What You’ll Build”A trial countdown that:
- Fires only in the final window of a trial (the last 3 days)
- Renders the days remaining via the
{{days_remaining}}token - Links to checkout with an upgrade CTA
Prerequisites
Section titled “Prerequisites”- A React 18+ application with
@revturbine/sdkinstalled - A
RevTurbineProviderset up (see Quickstart)
-
Add a trial-ending placement to your config
The
trial_endingtrigger fires when a trial enters its closing window. This is a complete, validExportedConfig.exported_config.json {"version": "v1","plans": [{ "id": "plan_pro", "unique_handle": "pro", "name": "Pro", "tier_position": 1, "sort_order": 1 }],"entitlements": [],"entitlement_rules": [],"segments": [],"content_ui_paths": [],"surface_templates": [{ "id": "banner_placement", "surface_type": "banner", "fields": [] }],"placements": [{"id": "pl_trial_ending","name": "Trial ending countdown","category": "trials","trigger": { "type": "trial_ending", "days_before_end": 3 },"payloads": [{"id": "pl_trial_ending_p0","target": { "plan_ids": [], "segment_chips": [] },"surfaces": [{"template_id": "banner_placement","fields": {"header": "Your trial ends in {{days_remaining}} days","body": "Upgrade now to keep your projects and Pro features.","dismissible": "Yes"},"ctas": [{ "label": "Upgrade to Pro", "path": "open_checkout", "config": { "purchase": "pro" } }]}],"caps": { "max_per_period": { "count": 1, "period": "day" } },"status": "active"}],"order": 0}]} -
Provide trial status to the SDK
The SDK reads trial state from a resolver in local mode (or from the user context in server mode). Supply the trial so the trigger and
{{days_remaining}}token can compute the window.src/App.tsx <RevTurbineProvideroptions={{localRuntime: {exportedConfig,// In local mode, hydrate trial status synchronously:resolvers: {getTrialStatus: () => ({ active: true, daysRemaining: 2, plan: 'pro' }),},},user: { id: 'user_123', context: { plan_handle: 'trial' } },}}><AppHeader /></RevTurbineProvider> -
Render the banner slot
src/components/AppHeader.tsx import { FixedSurfaceSlot } from '@revturbine/sdk';export function AppHeader() {return (<header>{/* Hidden until the trial enters its final 3 days */}<FixedSurfaceSlot id="app_header_banner" surfaceTemplateIds={['banner_placement']} /><nav>{/* ... */}</nav></header>);} -
(Optional) Read trial status directly
To drive your own UI — a sidebar countdown, a settings notice — read trial status imperatively:
import { useRevTurbine } from '@revturbine/sdk';function TrialNotice() {const { sdk } = useRevTurbine();const trial = sdk?.getTrialStatus();if (!trial?.active) return null;return <p>{trial.daysRemaining} days left in your trial</p>;}
How It Works
Section titled “How It Works”- The
trial_endingtrigger keeps the placement hidden until the trial is withindays_before_endof expiring. {{days_remaining}}is filled from the trial status the SDK holds.- As the trial advances day by day, the banner copy updates automatically.
- The CTA opens checkout through the resolvers from Quickstart.
Try It Live
Section titled “Try It Live”Next Steps
Section titled “Next Steps”- Entitlements Guide — trials, usage limits, and credits
- Placements Guide — triggers and targeting
- Tutorial: Show a Banner Placement — targeted banners without a trigger