Skip to main content

Trial Management

Trials give users time to evaluate your product before they’re charged. Subscribd handles the full trial lifecycle — from starting a no-card trial to converting it to a paid subscription.

Starting a trial

Trials start automatically when a plan defines trial_days. No extra code is needed in the subscription creation call:
// config/subscribd.php
'plans' => [
    'pro' => [
        'trial_days' => 14,
        // ...
    ],
],
use Pixelworxio\Subscribd\Actions\CreateSubscription;
use Pixelworxio\Subscribd\Models\Plan;

$plan = Plan::where('key', 'pro')->firstOrFail();
app(CreateSubscription::class)->execute($user, $plan);

$subscription = $user->subscription();
$subscription->onTrial();       // true
$subscription->trial_ends_at;   // CarbonImmutable 14 days from now

Card-free trials

Set trial_requires_payment_method to false on the plan to start a trial without collecting payment details:
'pro' => [
    'trial_days'                    => 14,
    'trial_requires_payment_method' => false,
    // ...
],
With this setting, CreateSubscription makes no gateway API call. The subscription’s gateway_id is null until the trial is converted to active via ConvertTrialToActive, at which point the gateway creates the subscription and collects payment.

Converting a trial to active

Use ConvertTrialToActive to end the trial immediately and collect payment:
use Pixelworxio\Subscribd\Actions\ConvertTrialToActive;

$subscription = $user->subscription();
app(ConvertTrialToActive::class)->execute($subscription);
What happens:
  1. The gateway creates or updates the subscription and triggers the first charge.
  2. On payment success, the subscription transitions to Active and TrialEnded is fired with $converted = true.
  3. On payment failure, the subscription transitions to PastDue and TrialEnded is fired with $converted = false. Dunning retries begin.

Extending a trial

Add days to a trial, or set an explicit end date:
use Pixelworxio\Subscribd\Actions\ExtendTrial;
use Carbon\CarbonImmutable;

// Add 14 days to the trial
app(ExtendTrial::class)->execute($subscription, days: 14);

// Set an explicit trial end date
app(ExtendTrial::class)->execute($subscription, until: CarbonImmutable::parse('2026-09-01'));
When the active gateway supports trial extension, the new date is pushed to the gateway. Otherwise, only the local trial_ends_at column is updated. Gateway support for trial extension:
GatewaySupported
Stripe✅ Yes
PayPal❌ No
Braintree❌ No
Paddle❌ No
FastSpring❌ No
Square❌ No

Canceling a trial

Cancel a Trialing subscription before it converts:
use Pixelworxio\Subscribd\Actions\CancelTrial;

app(CancelTrial::class)->execute($subscription);
This delegates to CancelSubscription with immediately: true. Throws SubscriptionException if the subscription is not in Trialing status.

Trial helpers on the billable

// Extend the default subscription's trial by 7 days
$user->extendTrial(days: 7);
$user->extendTrial('team', days: 7);           // named slot

// Cancel the trial
$user->cancelTrial();
$user->cancelTrial('team');

// Convert the trial to active (triggers payment)
$user->convertTrial();
$user->convertTrial('team');
These helpers delegate to the corresponding action classes.

Listening to trial events

use Pixelworxio\Subscribd\Events\TrialEnded;

Event::listen(TrialEnded::class, function (TrialEnded $event): void {
    if ($event->converted) {
        // Payment succeeded — subscription is now Active
    } else {
        // Payment failed — subscription is now PastDue
    }
});
Other trial-related events dispatched by the package:
EventFired when
TrialEndedTrial converts or payment fails at conversion
SubscriptionUpdatedTrial extended
SubscriptionCanceledTrial canceled

The TrialStatus Livewire component

Drop the trial-status component into any Livewire view to give subscribers a self-service trial management UI:
<livewire:subscribd::subscriber.trial-status />

{{-- Named subscription slot --}}
<livewire:subscribd::subscriber.trial-status :subscription-name="'team'" />
The component shows:
  • Days remaining in the trial
  • A “Convert to paid” button (triggers ConvertTrialToActive)
  • An “Extend trial” button when the gateway supports it (Stripe)
  • A “Cancel trial” button with inline confirmation
It is automatically composed into subscription-manager when the subscription is on trial — no extra wiring needed.

Blade static component

A read-only variant with no action buttons:
<x-subscribd-trial-status />
<x-subscribd-trial-status subscription-name="team" />
Renders nothing when the user is not on a trial.

Scheduled trial expiry

Add the following scheduled command to expire trials automatically. Subscribd runs this via subscribe:expire-trials:
// routes/console.php
Schedule::command('subscribd:expire-trials')->hourly();
Schedule::command('subscribd:dispatch-trial-ending-events')->daily();
dispatch-trial-ending-events fires TrialEnding for each trial that ends within the next 72 hours, giving you time to send reminder emails.

Next steps