Offer free trials
Section titled “Offer free trials”A plan can include a trial. While a workspace (called a tenant in the API)
is trialing, its subscription status is "trial" and endsAt holds the
trial end date, both live on the bridge surface (see
How billing works).
Surfacing trial state
Section titled “Surfacing trial state”The drop-in components already understand trials: <bridge-subscription-status />
shows the trialing status and <bridge-billing-notice /> surfaces an
end-of-trial prompt as the date approaches. You can also read it yourself.
Note that endsAt is optional on the snapshot, so guard it before formatting:
import { Component } from '@angular/core';
import { DatePipe } from '@angular/common';
import { BridgeService } from '@nebulr-group/bridge-angular';
@Component({
selector: 'app-trial-line',
standalone: true,
imports: [DatePipe],
template: `
@if (subscription()?.status === 'trial') {
@if (subscription()?.endsAt; as endsAt) {
<p>Trial ends {{ endsAt | date }}</p>
} @else {
<p>Trial active</p>
}
}
`,
})
export class TrialLineComponent {
protected readonly subscription = this.bridge.tenant.subscription;
constructor(private bridge: BridgeService) {}
}
Reacting to the trial lifecycle
Section titled “Reacting to the trial lifecycle”For side effects (emails, analytics, nudges), handle the trial events on the unified dispatcher; see React to billing changes:
import { inject } from '@angular/core';
import { BridgeService } from '@nebulr-group/bridge-angular';
const bridge = inject(BridgeService);
bridge.events.handle({
'subscription.trial_started': (m) => analytics.track('trial_started', m),
'subscription.trial_ending_soon': (m) => sendReminder(m),
'subscription.trial_converted': (m) => analytics.track('trial_converted', m),
'subscription.trial_expired': (m) => analytics.track('trial_expired', m),
});
When a trial expires without converting, the workspace becomes billing-locked:
the server sets gateEngaged: true on the subscription snapshot, the same lock
mechanism described in How billing works.
Gate your app with Require a plan so the
workspace can pick a paid plan and get back in.