# Origamy playbook spec v1. Reference: /playbooks/spec-format/
spec_version: 1
id: saas.trial-to-paid
title: Trial to paid
sector: saas
source:
  kind: synthesized
  notes: >-
    No SaaS customer has built this with us yet. Written from the base onboarding nudge: tips
    tied to the product's key action, a "few days left" email, and a sales call only for
    accounts that are actually using the product. Everything stops when they subscribe.
derived_from: base.welcome-onboarding
vocabulary:
  person: user
  people: users
  group: team
summary: >-
  Moves trial users toward the one action that shows the product's value, reminds them before
  the trial ends, and gives sales a task to call engaged trials. It all stops the moment they
  subscribe.
when_to_use:
  - You run a time-limited free trial and your app sends events for trial start, a key action and a subscription.
  - Sales should spend time only on trials that are using the product.

requires:
  data_in:
    - how: app_events
      what: "Your app sends trial, key-action and subscription events."
  channels:
    - channel: email
      for: Every message
      needs: A verified sending domain for {{ params.email_from }}.
  events:
    - "{{ params.trial_event }}"
    - "{{ params.key_action_event }}"
    - "{{ params.paid_event }}"
  traits: []

parameters:
  - key: org_name
    ask: true
    question: What's your product called?
    label: Product name
    type: string
    example: Northwind
  - key: trial_days
    ask: true
    question: How long is the trial, in days?
    label: Trial length
    type: number
    default: 14
  - key: key_action_event
    ask: true
    question: Which event is the "aha" action that predicts people will pay?
    label: Key action
    type: event_name
    default: Report Created
  - key: sales_team
    ask: true
    question: Which team calls engaged trials before they end?
    label: Sales team
    type: team_name
    default: Sales
  - key: app_url
    ask: true
    question: Where should buttons send people? (your app or upgrade page)
    label: App link
    type: url
    example: https://app.yourproduct.example
  - key: ending_delay
    label: Wait after the tip before "3 days left" (trial length minus 5 days)
    type: duration
    default: 9d
  - key: trial_event
    label: Trial started event
    type: event_name
    default: Trial Started
  - key: paid_event
    label: Subscription started event
    type: event_name
    default: Subscription Started
  - key: email_from
    label: Sender address
    type: email
    default: "{{ workspace.default_sender }}"
  - key: greeting_fallback
    label: Greeting when a first name is missing
    type: string
    default: there

timings:
  - "Day 2: a tip email if they haven't done {{ params.key_action_event }} yet."
  - "{{ params.trial_days }} days minus 3: a \"3 days left\" email to everyone still on the trial."
  - The same day, engaged trials (did the key action in the last 7 days) create a call task for {{ params.sales_team }}, due in 48 hours.
  - Everything stops when {{ params.paid_event }} arrives.

customer_must:
  - Send {{ params.trial_event }}, {{ params.key_action_event }} and {{ params.paid_event }} from your app.
  - "The \"3 days left\" email waits {{ params.ending_delay }} after the day-2 tip, which is your trial length minus 5 days. Change it if your trial isn't {{ params.trial_days }} days."
  - Add people to the {{ params.sales_team }} team, verify the sending domain, switch the follow-up on and test it with your own account.

objects:
  - ref: team_sales
    kind: team
    about: Calls engaged trials before they end.
    body: { name: "{{ params.sales_team }}" }
  - ref: seg_engaged
    kind: segment
    about: Did the key action in the last 7 days.
    body:
      name: Engaged trials
      description: "{{ params.key_action_event }} in the last 7 days."
      segment_type: dynamic
      status: active
      definition:
        operator: and
        conditions:
          - { type: event, event_name: "{{ params.key_action_event }}", cond_operator: has_done, time_window: 7d }
  - ref: seg_no_key_action
    kind: segment
    about: Hasn't done the key action in the last 14 days.
    body:
      name: Trial, no key action yet
      description: "No {{ params.key_action_event }} in the last 14 days."
      segment_type: dynamic
      status: active
      definition:
        operator: and
        conditions:
          - { type: event, event_name: "{{ params.trial_event }}", cond_operator: has_done, time_window: 14d }
          - { type: event, event_name: "{{ params.key_action_event }}", cond_operator: has_not_done, time_window: 14d }
  - ref: tmpl_tip
    kind: template
    about: Tip pointing to the key action.
    body:
      name: Trial tip (email)
      channel: email
      category: Trial
      style: html
      status: active
      subject: "The fastest way to get value from {{ params.org_name }}"
      metadata: { email: { from: "{{ params.email_from }}", preview_text: "Two minutes, and you'll see why people stay." } }
      variables: {}
      body: >-
        <p>Hi {{ traits.first_name | default: "{{ params.greeting_fallback }}" }},</p>
        <p>The people who get the most from {{ params.org_name }} do one thing in their first few
        days. It takes a couple of minutes.</p>
        <p><a href="{{ params.app_url }}">Try it now</a></p>
        <p>Stuck? Reply and a real person will help.</p>
        <p style="font-size:12px;color:#6b6b80"><a href="{{ unsubscribe_url }}">Unsubscribe</a></p>
  - ref: tmpl_ending
    kind: template
    about: '"3 days left" email.'
    body:
      name: Trial ending (email)
      channel: email
      category: Trial
      style: html
      status: active
      subject: "3 days left in your {{ params.org_name }} trial"
      metadata: { email: { from: "{{ params.email_from }}", preview_text: "Keep everything you've set up." } }
      variables: {}
      body: >-
        <p>Hi {{ traits.first_name | default: "{{ params.greeting_fallback }}" }},</p>
        <p>Your {{ params.org_name }} trial ends in 3 days. Choose a plan to keep everything you've
        set up.</p>
        <p><a href="{{ params.app_url }}">Choose a plan</a></p>
        <p>Not sure which plan fits? Reply and we'll help you pick.</p>
        <p style="font-size:12px;color:#6b6b80"><a href="{{ unsubscribe_url }}">Unsubscribe</a></p>
  - ref: wf_trial
    kind: workflow
    about: Tip, "3 days left", and a sales call for engaged trials; exits on subscription.
    body:
      name: Trial to paid
      description: Trial nudges and a sales call for engaged trials; stops when they subscribe.
      enabled: false
      trigger_type: event
      trigger_config: { event_name: "{{ params.trial_event }}" }
      steps:
        - { id: s1, type: delay, config: { duration: 2d } }
        - { id: s2, type: filter, config: { condition: { type: segment, cond_operator: member_of, value: "{{ ref.seg_no_key_action.id }}" } } }
        - { id: s3, type: action, config: { action_type: send_message, channel_config: { mode: single, single: { channel: email, template_id: "{{ ref.tmpl_tip.id }}" } } } }
        - { id: s4, type: delay, config: { duration: "{{ params.ending_delay }}" } }
        - { id: s5, type: action, config: { action_type: send_message, channel_config: { mode: single, single: { channel: email, template_id: "{{ ref.tmpl_ending.id }}" } } } }
        - { id: s6, type: filter, config: { condition: { type: segment, cond_operator: member_of, value: "{{ ref.seg_engaged.id }}" } } }
        - id: s7
          type: human_task
          config:
            human_task:
              title: "Engaged trial ending: {{ traits.first_name }} {{ traits.last_name }}"
              instructions: |-
                {{ traits.first_name }} {{ traits.last_name }} ({{ traits.email }}) is using {{ params.org_name }} and their trial ends in 3 days.
                Reach out to answer questions and help them pick a plan.
              assignee_refs: [{ type: team, id: "{{ ref.team_sales.id }}" }]
              strategy: round_robin
              completion_policy: first_response_wins
              outcome_options:
                - { id: converting, label: Will subscribe, intent: positive }
                - { id: needs_time, label: Needs more time, intent: neutral }
                - { id: not_reached, label: Could not reach, intent: negative }
              due_hours: 48
              wait: false
              notify: immediate
      re_entry_policy: once
      re_entry_cooldown_hours: 24
      goal: { event_name: "{{ params.paid_event }}", attribution_window_hours: 720 }
      exit_conditions: [{ event_name: "{{ params.paid_event }}" }]

eval:
  name: 76_saas_trial_to_paid
  mode: task
  vertical: ""
  prompt: >-
    We have a 14-day free trial. Two days in, email people who haven't created a report yet
    with a tip. Three days before the trial ends, email everyone still on the trial, and give
    sales a task to call the ones who are actively creating reports. Stop when they subscribe.
  expect_artifacts: [segment, workflow, message_template]
  forbid_terms: []
