# Origamy playbook spec v1. Reference: /playbooks/spec-format/
spec_version: 1
id: hospitality.post-stay-review-and-return
title: Post-stay review and come-back message
sector: hospitality
source:
  kind: synthesized
  notes: >-
    No hotel or host has built this with us yet. Written from the base feedback and win-back
    patterns: a daily run over guests who checked out yesterday, a rating form whose low scores
    give a manager a task, and a later daily run over guests who stayed about two months ago.
    The thank-you goes to every guest with the review link, so unhappy guests are never kept
    from reviewing.
derived_from: base.feedback-follow-up
vocabulary:
  person: guest
  people: guests
  group: guest relations
summary: >-
  The day after a guest checks out, thanks them and shares your review link and a short rating
  form. A low rating gives your manager a task to call and put things right. About two months
  later, invites them to book direct next time.
when_to_use:
  - You want more reviews on Google, Booking.com or Airbnb, and you want unhappy guests called before they write something public.
  - You would like past guests to book direct with you instead of through a platform.
  - Your check-out dates are in a Google Sheet or Excel file, or come from the Pre-arrival playbook's reservation form.

requires:
  data_in:
    - how: sheet_sync
      what: "Your reservations sheet, synced every hour as People: guest phone and check-out date (the same sheet as the pre-arrival playbook, if you use it)."
    - how: public_form
      what: "The Stay feedback form this playbook creates; the thank-you message links to it."
  channels:
    - channel: sms
      for: The thank-you and the come-back message
      needs: An SMS provider, or Origamy managed SMS after business verification (KYC).
  events:
    - onboarding.submitted
  traits:
    - check_out_date
    - last_stay_rating
    - stay_follow_up
    - stay_follow_up_note

parameters:
  - key: org_name
    ask: true
    question: What should messages call your property?
    label: Property name
    type: string
    example: Northwind Guesthouse
  - key: review_url
    ask: true
    question: Where should guests leave a review? (your Google, Booking.com or Airbnb review link)
    label: Review link
    type: url
    example: https://reviews.example.com/your-property
  - key: booking_url
    ask: true
    question: Where can past guests book direct with you?
    label: Direct booking link
    type: url
    example: https://yourproperty.example/book
  - key: offer_text
    ask: true
    question: Is there a small offer for guests who book direct? (leave empty for none)
    label: Direct-booking offer
    type: string
    default: ""
    example: Book direct and get a free breakfast.
  - key: care_team
    ask: true
    question: Which team calls guests who rated their stay low? (one person is fine)
    label: Guest relations
    type: team_name
    default: Guest relations
  - key: low_score
    label: Low scores are at or below (out of 5)
    type: number
    default: 2
  - key: call_due_hours
    label: Hours the team has to call
    type: hours
    default: 24
  - key: comeback_after
    label: Send the come-back message after this long
    type: duration
    default: 60d
  - key: comeback_window
    label: Stop trying for guests whose stay is older than this
    type: duration
    default: 75d
  - key: send_time
    label: Daily send time
    type: time
    default: "10:00"
  - key: default_country
    label: Default phone country on the form
    type: country_code
    default: "{{ workspace.country }}"
  - key: timezone
    label: Time zone for the daily runs
    type: timezone
    default: "{{ workspace.timezone }}"
  - key: greeting_fallback
    label: Greeting when a first name is missing
    type: string
    default: there

timings:
  - At {{ params.send_time }} the day after check-out (the run is daily, in {{ params.timezone }}), the guest gets a thank-you SMS with the review link and the feedback form.
  - A rating of {{ params.low_score }} or lower creates a call task straight away, due in {{ params.call_due_hours }} hours.
  - Guests whose stay ended more than {{ params.comeback_after }} but less than {{ params.comeback_window }} ago get one come-back message (a six-month cooldown).

customer_must:
  - "Keep the check-out date (a date like 2026-12-01) on each guest in the trait check_out_date: a column in your synced sheet, or the reservation form of the Pre-arrival playbook. Clear it for cancelled stays so the guest gets nothing."
  - Publish the Stay feedback form, then switch the three follow-ups on.
  - Add people to the {{ params.care_team }} team. If you run the place alone, put yourself in it. A task assigned to an empty team reaches nobody.
  - Use the review link the platform gives you, and do not offer anything in return for a review. Most platforms do not allow it.
  - Connect an SMS provider or finish business verification, and test with your own phone and a stay that ended yesterday.

objects:
  - ref: team_care
    kind: team
    about: Calls guests who gave a low rating.
    body: { name: "{{ params.care_team }}" }

  - ref: form_feedback
    kind: form
    about: A short rating form. The guest's phone matches the answer to their profile.
    body:
      name: Stay feedback
      slug: stay-feedback
      description: Tell us how your stay was.
      draft_state:
        version: 1
        meta: { layout: classic, submit_label: Send, success_message: "Thank you for telling us." }
        pages:
          - id: p1
            title: How was your stay?
            description: It takes ten seconds.
            fields:
              - { id: f_rating, key: rating, type: rating, label: "How would you rate your stay?", required: true, maps_to: { mode: custom, key: last_stay_rating, trait: true }, validation: { min: 1, max: 5 } }
              - { id: f_comment, key: comment, type: long_text, label: "Anything you'd like to tell us?", required: false, maps_to: { mode: custom, key: comment } }
              - { id: f_phone, key: phone, type: phone, label: "Your phone number (so we can follow up)", required: true, maps_to: { mode: mapped, slot: profile.phone }, config: { country_picker: true, default_country: "{{ params.default_country }}", verify: "off" } }
      verification_settings: { required: false }

  - ref: seg_checked_out
    kind: segment
    about: Guests who checked out in the last day.
    body:
      name: Checked out yesterday
      description: check_out_date within the last 24 hours.
      segment_type: dynamic
      status: active
      definition:
        operator: and
        conditions:
          - { type: trait, trait_key: check_out_date, cond_operator: within_last, value: 1d }
  - ref: seg_comeback
    kind: segment
    about: Guests who stayed a couple of months ago.
    body:
      name: Stayed a while ago
      description: "check_out_date more than {{ params.comeback_after }} ago but within {{ params.comeback_window }}."
      segment_type: dynamic
      status: active
      definition:
        operator: and
        conditions:
          - { type: trait, trait_key: check_out_date, cond_operator: older_than, value: "{{ params.comeback_after }}" }
          - { type: trait, trait_key: check_out_date, cond_operator: within_last, value: "{{ params.comeback_window }}" }

  - ref: tmpl_thanks
    kind: template
    about: Thank-you SMS with the review link and the feedback form.
    body:
      name: Thanks for staying (SMS)
      channel: sms
      category: After the stay
      style: text
      status: active
      subject: ""
      metadata: {}
      variables: {}
      body: "Hello {{ traits.first_name | default: \"{{ params.greeting_fallback }}\" }}, thank you for staying with {{ params.org_name }}. How was it? Tell us in ten seconds: {{ ref.form_feedback.url }} If you enjoyed your stay, a review helps us a lot: {{ params.review_url }} Reply STOP to opt out."
  - ref: tmpl_comeback
    kind: template
    about: Come-back SMS with the direct booking link and the optional offer.
    body:
      name: Come back soon (SMS)
      channel: sms
      category: After the stay
      style: text
      status: active
      subject: ""
      metadata: {}
      variables: {}
      body: "Hello {{ traits.first_name | default: \"{{ params.greeting_fallback }}\" }}, it's {{ params.org_name }}. We'd love to host you again.{% if \"{{ params.offer_text }}\" != \"\" %} {{ params.offer_text }}{% endif %} Book direct here: {{ params.booking_url }} Reply STOP to opt out."

  - ref: wf_thanks
    kind: workflow
    about: 'Daily run over "checked out yesterday": the thank-you, review link and feedback form.'
    body:
      name: "After the stay: thank you"
      description: Every day, a thank-you with the review link and the feedback form to guests who checked out yesterday.
      enabled: false
      trigger_type: schedule
      trigger_config: { segment_id: "{{ ref.seg_checked_out.id }}", rrule: FREQ=DAILY, starts_at: "{{ workspace.tomorrow }}T{{ params.send_time }}", timezone: "{{ params.timezone }}" }
      steps:
        - { id: s1, type: action, config: { action_type: send_message, channel_config: { mode: single, single: { channel: sms, template_id: "{{ ref.tmpl_thanks.id }}" } } } }
      re_entry_policy: cooldown
      re_entry_cooldown_hours: 720
      goal: {}
      exit_conditions: []
  - ref: wf_low
    kind: workflow
    about: A low rating gives the guest relations team a call task; the outcome is saved.
    body:
      name: "After the stay: low rating call"
      description: When a rating at or below the low line comes in, the team calls to put things right.
      enabled: false
      trigger_type: event
      trigger_config:
        event_name: onboarding.submitted
        form_id: "{{ ref.form_feedback.id }}"
        property_filters: [{ property: rating, cond_operator: lte, value: "{{ params.low_score }}" }]
        properties: { $origamy_property_filters: true }
      steps:
        - id: s1
          type: human_task
          config:
            human_task:
              title: "Unhappy guest: {{ traits.first_name }} {{ traits.last_name }}"
              instructions: |-
                {{ traits.first_name | default: "A guest" }} rated their stay {{ properties.rating }} out of 5.
                Their comment: {{ properties.comment | default: "none" }}
                Contact: {{ traits.phone }}

                Call, listen, and put it right if you can. Note what you agreed.
              assignee_refs: [{ type: team, id: "{{ ref.team_care.id }}" }]
              strategy: round_robin
              completion_policy: first_response_wins
              outcome_options:
                - { id: resolved, label: Resolved, intent: positive }
                - { id: follow_up, label: Needs more follow-up, intent: neutral }
                - { id: not_reached, label: Could not reach, intent: negative }
              due_hours: "{{ params.call_due_hours }}"
              wait: true
              wait_timeout_hours: 168
              notify: immediate
        - { id: s2, type: action, config: { action_type: set_trait, traits: { stay_follow_up: "{{ properties.task_outcome | default: \"unknown\" }}", stay_follow_up_note: "{{ properties.task_note }}" } } }
      re_entry_policy: every_time
      re_entry_cooldown_hours: 0
      goal: {}
      exit_conditions: []
  - ref: wf_comeback
    kind: workflow
    about: 'Daily run over "stayed a while ago": one come-back message every six months at most.'
    body:
      name: "After the stay: come back"
      description: Every day, a come-back message with the direct booking link to guests who stayed a couple of months ago.
      enabled: false
      trigger_type: schedule
      trigger_config: { segment_id: "{{ ref.seg_comeback.id }}", rrule: FREQ=DAILY, starts_at: "{{ workspace.tomorrow }}T{{ params.send_time }}", timezone: "{{ params.timezone }}" }
      steps:
        - { id: s1, type: action, config: { action_type: send_message, channel_config: { mode: single, single: { channel: sms, template_id: "{{ ref.tmpl_comeback.id }}" } } } }
      re_entry_policy: cooldown
      re_entry_cooldown_hours: 4320
      goal: {}
      exit_conditions: []

eval:
  name: 86_hospitality_post_stay_review_and_return
  mode: task
  vertical: ""
  prompt: >-
    After a guest checks out, text them the next morning to say thanks, with a link to leave a
    review and a short rating form. If someone rates us 2 or lower, give our manager a task to
    call within a day. Then about two months after their stay, text them an invitation to book
    direct with us. The check-out date is in check_out_date.
  expect_artifacts: [form, segment, workflow, message_template]
  forbid_terms: [discount code]
