# Origamy playbook spec v1. Reference: /playbooks/spec-format/
spec_version: 1
id: retail.abandoned-cart
title: Abandoned cart
sector: retail
source:
  kind: synthesized
  notes: >-
    No shop has built this with us yet. Written from the base patterns: start on the checkout
    event, wait, message, and exit the moment an order arrives.
derived_from: null
vocabulary:
  person: shopper
  people: shoppers
  group: team
summary: >-
  When a shopper starts checkout and doesn't finish, they get an email an hour later showing
  what they left, and an SMS the next day. The moment they order, the reminders stop.
when_to_use:
  - Your store sends an event when checkout starts and another when an order is placed.
  - Most of your shoppers give an email or phone number before checkout.

requires:
  data_in:
    - how: app_events
      what: "Your store sends checkout and order events (a plugin, the Web SDK, or a webhook from your platform)."
  channels:
    - channel: email
      for: The first reminder
      needs: A verified sending domain for {{ params.email_from }}.
    - channel: sms
      for: The second reminder (optional)
      needs: An SMS provider, or Origamy managed SMS after business verification (KYC).
  events:
    - "{{ params.checkout_event }}"
    - "{{ params.order_event }}"
  traits: []

parameters:
  - key: org_name
    ask: true
    question: What's your shop called?
    label: Shop name
    type: string
    example: Northwind Store
  - key: checkout_event
    ask: true
    question: Which event means checkout started? Its properties should include the cart link and items.
    label: Checkout event
    type: event_name
    default: Checkout Started
  - key: order_event
    ask: true
    question: Which event means the order went through?
    label: Order event
    type: event_name
    default: Order Completed
  - key: send_sms
    ask: true
    question: Send an SMS the next day as well?
    label: SMS reminder
    type: boolean
    default: true
  - key: first_delay
    ask: true
    question: How long after checkout starts should the email go?
    label: Email after
    type: duration
    default: 1h
  - key: email_from
    label: Sender address
    type: email
    default: "{{ workspace.default_sender }}"
  - key: cart_url_property
    label: Event property with the cart link
    type: string
    default: cart_url
  - key: greeting_fallback
    label: Greeting when a first name is missing
    type: string
    default: there

timings:
  - Email {{ params.first_delay }} after {{ params.checkout_event }}; SMS 1 day after that, if switched on.
  - Stops as soon as {{ params.order_event }} arrives. At most one sequence per shopper per 3 days.

customer_must:
  - "Send {{ params.checkout_event }} with properties {{ params.cart_url_property }} (a link that restores the cart), item_names and total, and {{ params.order_event }} when an order is placed."
  - Verify the sending domain; for SMS, connect a provider or finish business verification.
  - Switch the follow-up on and test it with your own email and phone.

objects:
  - ref: tmpl_cart_email
    kind: template
    about: '"You left something behind" email with a button back to the cart.'
    body:
      name: Your cart is waiting (email)
      channel: email
      category: Cart
      style: html
      status: active
      subject: "You left something in your cart, {{ traits.first_name | default: \"{{ params.greeting_fallback }}\" }}"
      metadata: { email: { from: "{{ params.email_from }}", preview_text: We saved it for you. } }
      variables: {}
      body: >-
        <p>Hi {{ traits.first_name | default: "{{ params.greeting_fallback }}" }},</p>
        <p>You left {{ properties.item_names | default: "a few things" }} in your cart at
        {{ params.org_name }}. We've saved it for you.</p>
        <p><a href="{{ properties.{{ params.cart_url_property }} }}">Back to your cart</a></p>
        <p>Questions about sizes, delivery or payment? Just reply.</p>
        <p style="font-size:12px;color:#6b6b80"><a href="{{ unsubscribe_url }}">Unsubscribe</a></p>
  - ref: tmpl_cart_sms
    kind: template
    when: { param: send_sms, equals: true }
    about: Short SMS the next day.
    body:
      name: Your cart is waiting (SMS)
      channel: sms
      category: Cart
      style: text
      status: active
      subject: ""
      metadata: {}
      variables: {}
      body: "{{ params.org_name }}: your cart is still saved. Finish your order here: {{ properties.{{ params.cart_url_property }} }} Reply STOP to opt out."
  - ref: wf_cart
    kind: workflow
    about: Email, then SMS; exits on an order.
    body:
      name: Abandoned cart
      description: Reminders after checkout starts; stops when the order comes in.
      enabled: false
      trigger_type: event
      trigger_config: { event_name: "{{ params.checkout_event }}" }
      steps:
        - { id: s1, type: delay, config: { duration: "{{ params.first_delay }}" } }
        - { id: s2, type: action, config: { action_type: send_message, channel_config: { mode: single, single: { channel: email, template_id: "{{ ref.tmpl_cart_email.id }}" } } } }
        - { id: s3, when: { param: send_sms, equals: true }, type: delay, config: { duration: 1d } }
        - { id: s4, when: { param: send_sms, equals: true }, type: action, config: { action_type: send_message, channel_config: { mode: single, single: { channel: sms, template_id: "{{ ref.tmpl_cart_sms.id }}" } } } }
      re_entry_policy: cooldown
      re_entry_cooldown_hours: 72
      goal: { event_name: "{{ params.order_event }}", attribution_window_hours: 168 }
      exit_conditions: [{ event_name: "{{ params.order_event }}" }]

eval:
  name: 70_retail_abandoned_cart
  mode: task
  vertical: ""
  prompt: >-
    When someone starts checkout on our store and doesn't buy, email them an hour later with
    a link back to their cart, then text them the next day. Stop as soon as they place the
    order.
  expect_artifacts: [workflow, message_template]
  forbid_terms: []
