> For the complete documentation index, see [llms.txt](https://orbit-b2b.gitbook.io/orbit-b2b-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://orbit-b2b.gitbook.io/orbit-b2b-docs/b2b-customer-portal/schedule.md).

# Reorder reminder schedule

The reminder cron sends up to 3 reminder emails after an order is fulfilled — once at the first delay, again at the second, again at the third. Each is opt-in per shop.

## Where to configure

**Apps → Orders → Reorder Settings → Schedule tab.**

## Fields

| Field                                             | What it does                                                                                                                                      |
| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Enable reorder reminder emails**                | Master toggle. When OFF, no reminder is sent regardless of other settings                                                                         |
| **First reminder (days)**                         | Days after order fulfillment for the first reminder. Set to 0 to disable this step                                                                |
| **Second reminder (days)**                        | Same, for the second reminder. Leave empty to skip                                                                                                |
| **Third reminder (days)**                         | Same, for the third. Leave empty to skip                                                                                                          |
| **Only send to customers with marketing consent** | When ON (recommended), the cron skips customers whose Shopify `emailMarketingConsent.marketingState` isn't `SUBSCRIBED`. CAN-SPAM / GDPR friendly |

## How the cron runs

Daily at **06:00 UTC**, the job iterates all active merchants. For each shop:

1. Loads the shop's reorder settings (skip if not enabled or no delays)
2. For each configured delay (first/second/third), queries Shopify Orders matching:
   * Has `orb2b-b2b` order tag
   * Fulfilled within `[delay-2, delay]` days ago — a 3-day window so a single skipped cron tick (deploy, lock contention, MongoDB flap) doesn't drop the cohort
3. For each candidate order:
   * Skip if customer has no email
   * Skip if `respectMarketingConsent` is ON and customer isn't subscribed
   * Skip if customer has unsubscribed from reorder reminders (HMAC-verified per shop)
   * Skip if a reminder was already sent for this `(shop, orderId, step)` — dedupe via unique index
4. Load the `reorder_reminder` email template (subject + body + customer's locale)
5. Substitute shortcodes ({{first\_name}}, {{shop\_name}}, {{days\_ago}}, {{reorder\_link}}, {{unsubscribe\_link}})
6. Send via the shop's SMTP config
7. Record the send to `ReorderReminder` collection

## What if the cron misses a day?

The 3-day query window absorbs occasional misses. If the cron literally doesn't run for 3+ days (operational issue), those cohorts won't receive that reminder step. The next steps for the same customers still trigger normally.

The `ReorderReminder` unique index on `(shop, orderId, step)` guarantees no duplicate send — even if the cron re-runs the same day or the window double-counts orders.

## Pause sending temporarily

Set the **Enable** toggle to OFF and save. Sends stop immediately. Set it back ON whenever — the cron picks up from current state (no backfill of missed days).

## Stopping reminders for one customer

Each email has an unsubscribe link. When the customer clicks:

1. Backend verifies the HMAC token against `REORDER_UNSUB_SECRET`
2. Records `(shop, hashedEmail)` to `ReorderUnsubscribe` collection
3. Customer sees a "you have been unsubscribed" confirmation page

Future cron runs skip this customer for all 3 steps + all future orders. The unsubscribe is per-shop, so unsubscribing from one shop doesn't affect another shop they buy from.

There's no admin UI to re-subscribe a customer right now — they'd need to email support to be removed from the unsubscribe list.

## Recommended schedule

For consumable products (cosmetics, food, supplies):

* First: **21-30 days** — the natural reorder window
* Second: **45-60 days** — late but still actionable
* Third: leave empty or **90 days** — last-chance churn signal

For non-consumable B2B inventory (equipment, parts):

* First: **45-60 days**
* Second: **90-120 days**
* Third: leave empty

For high-frequency consumables (printer ink, cleaning supplies, etc.):

* First: **14 days**
* Second: **30 days**
* Third: empty

Test with one cycle, watch open + click rates, then iterate.

## Next

* [Customize the email template](/orbit-b2b-docs/b2b-customer-portal/email-template.md)
* [Test the customer flow](/orbit-b2b-docs/b2b-customer-portal/testing.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://orbit-b2b.gitbook.io/orbit-b2b-docs/b2b-customer-portal/schedule.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
