From 306ba785516b00b4ef582af4b7b6634f68387bda Mon Sep 17 00:00:00 2001 From: Nolimit release Date: Fri, 30 Oct 2026 08:36:02 +0000 Subject: [PATCH] Update the public pages to 0.1.1 --- README.md | 1 - docs/CONTRACT.md | 63 +++++++++++++++++++++++++++++++++++++++++++ docs/README.md | 33 +++++++++++++++++++++++ docs/SETUP.md | 69 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 165 insertions(+), 1 deletion(-) delete mode 100644 README.md create mode 100644 docs/CONTRACT.md create mode 100644 docs/README.md create mode 100644 docs/SETUP.md diff --git a/README.md b/README.md deleted file mode 100644 index efdcb8e..0000000 --- a/README.md +++ /dev/null @@ -1 +0,0 @@ -# nolimit-reminder-dist diff --git a/docs/CONTRACT.md b/docs/CONTRACT.md new file mode 100644 index 0000000..dad20ff --- /dev/null +++ b/docs/CONTRACT.md @@ -0,0 +1,63 @@ +# Contract + +Hooks this plugin emits (`do_action`) or consumes (`apply_filters`) that +cross a repository boundary. Internal wiring (`add_action` / `add_filter` +on `nlrem_*`) is not a contract and is not listed here. + +## Emitted by this plugin + +These `do_action` calls are the plugin's outward signal. A sibling plugin +or a site developer can subscribe to any of them with `add_action`. + +| Hook | Args | Fired when | +|------|------|------------| +| `nlrem_cart_abandoned` | `$cart_id` (int) | A cart crosses the abandon threshold and is marked `abandoned`. | +| `nlrem_cart_resumed` | `$cart_id` (int) | A customer revisits an abandoned cart before purchase. | +| `nlrem_cart_completed` | `$cart_id` (int) | An order for the cart reaches `completed` status. | +| `nlrem_cart_expired` | `$cart_id` (int) | The retention sweep expires a cart record. | +| `nlrem_abandon_sweep_complete` | `$marked` (int, count) | The hourly abandon sweep finishes. | +| `nlrem_send_sweep_complete` | `$sent` (int, count) | The hourly send sweep finishes. | +| `nlrem_retention_complete` | `$cutoff` (string, datetime) | The daily retention sweep finishes. | +| `nlrem_email_sent` | `$cart_id` (int), `$step` (int), `$email` (string) | A reminder email dispatches successfully. | +| `nlrem_email_failed` | `$cart_id` (int), `$step` (int), `$email` (string), `$sent` (WP_Error or false) | `wp_mail()` returns a failure for a reminder email. | +| `nlrem_unsubscribed` | `$cart_id` (int), `$email` (string) | A customer clicks the unsubscribe link. | + +## Consumed by this plugin + +This plugin calls `apply_filters` on the following family hooks. A sibling +plugin (or site code) can alter the behaviour by adding a filter. + +| Hook | Default | Where | Effect of filtering | +|------|---------|-------|---------------------| +| `wpmgr_menu_title` | `'Manager'` | `includes/shared-menu.php` | Changes the parent menu label in the wp-admin sidebar. | +| `wpmgr_menu_glyph` | `'∞'` | `includes/shared-menu.php` | Changes the sidebar glyph for the Nolimit menu group. | +| `wpmgr_dashboard_cards` | `array()` | `includes/shared-menu.php` | Supplies the dashboard summary cards shown on the family landing page. This plugin contributes one card via `add_filter`. | + +## Internal cron hooks + +The following are WordPress cron event names registered by this plugin. +They are **not** a contract: no sibling plugin should subscribe to them, +and they will not appear in the tables above. They exist so that an +administrator can see the schedule in a cron plugin and so that +`wp_clear_scheduled_hook()` can target them on deactivation. + +| Cron hook | Schedule | +|-----------|----------| +| `nlrem_sweep_abandoned` | `nlrem_five_minutes` | +| `nlrem_sweep_send` | `nlrem_five_minutes` | +| `nlrem_cleanup_retention` | `daily` | + +## Notes + +- The `wpmgr_dashboard_cards` filter is answered by this plugin via + `add_filter( 'wpmgr_dashboard_cards', ... )` in + `includes/shared-menu.php`. The returned array element carries the + plugin's summary counts (tracked carts, abandoned, emails sent, + unsubscribe rate). +- No REST routes are registered. The only front-end surface is the + unsubscribe query argument `?nlrem_unsub={token}`, which is handled on + `template_redirect`. +- No options are exposed as a filter. Settings are read via + `NLREM_Settings::get()` and written via the admin form. A sibling that + needs to override a default should use `add_filter` on + `pre_option_nlrem_settings` (the standard WordPress options filter). diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..c1dbed7 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,33 @@ +# Nolimit Reminder + +Remind WooCommerce customers about the carts they leave behind. Time-based or +activity-based triggers, an email sequence with a discount, and the numbers +behind every send. No telemetry, no account, no upsell. + +**Version:** 0.1.1 + +## What it does + +- Watches WooCommerce carts for guest and logged-in customers. +- Marks a cart as abandoned after a configurable inactivity window. +- Sends a short email sequence (welcome, nudge, final) with optional discount. +- Records every send, delivery, and unsubscribe in its own tables. +- Exposes a dashboard with per-cart state, activity log, and settings. +- Integrates with the shared Nolimit family menu and dashboard card. + +## Requirements + +- WordPress 5.9+ +- PHP 7.4+ +- WooCommerce 6.0+ + +## Install + +1. Upload the plugin directory to `wp-content/plugins/nolimit-reminder`. +2. Activate from the Plugins screen. +3. Configure under **Nolimit → Nolimit Reminder → Settings**. + +## Docs + +- [SETUP.md](SETUP.md) — activation, configuration, cron. +- [CONTRACT.md](CONTRACT.md) — hooks this plugin emits and answers. diff --git a/docs/SETUP.md b/docs/SETUP.md new file mode 100644 index 0000000..3b94258 --- /dev/null +++ b/docs/SETUP.md @@ -0,0 +1,69 @@ +# Setup + +## Activation + +Activate the plugin from **Plugins → Installed Plugins → Nolimit Reminder**. +On activation the plugin: + +1. Creates three tables: `nlrem_carts`, `nlrem_steps`, `nlrem_sends`. +2. Registers the WooCommerce hooks that track cart state. +3. Schedules the cron events `nlrem_abandon_sweep`, `nlrem_send_sweep`, and + `nlrem_retention`. +4. Registers the admin menu page under the shared Nolimit family menu. + +Deactivation removes the cron events but leaves the tables. Uninstall drops +the tables and deletes all `nlrem_` options. + +## First-run configuration + +After activation, open **Nolimit → Nolimit Reminder → Settings** and set: + +- **Abandon threshold** (minutes): how long a cart sits before it is marked + abandoned. Default 30. +- **Sequence length**: number of emails in the reminder sequence. Default 3. +- **Email interval** (hours): gap between sequence steps. Default 24. +- **Discount code** (optional): a WooCommerce coupon code appended to the + final email. +- **Retention days**: how long completed or expired cart records are kept + before the retention sweep deletes them. Default 30. +- **From name** and **From email**: the sender identity for reminder emails. + Default to the site title and admin email. + +## Cron + +The plugin relies on WordPress cron for its three scheduled jobs: + +| Hook | Default frequency | Purpose | +|------|-------------------|---------| +| `nlrem_abandon_sweep` | hourly | Marks carts abandoned past the threshold. | +| `nlrem_send_sweep` | hourly | Sends the next sequence step for due carts. | +| `nlrem_retention` | daily | Deletes cart records older than the retention window. | + +If your site uses an external cron (WP-Cron-Disable, etc.), point it at +`wp-cron.php` or replace these with system cron. The sweeps are idempotent: +running them more often than scheduled does not duplicate sends because each +send is recorded in `nlrem_sends` before the cart is advanced. + +## Email deliverability + +Reminder emails use `wp_mail()`. No SMTP plugin is required, but if your host +blocks outbound mail on port 25 you will need an SMTP relay. The unsubscribe +link in each email is a plain `?nlrem_unsub=...` query argument on the shop +front; no JavaScript, no account, no tracking pixel. + +## Multi-site + +The plugin is network-agnostic: each site in a network has its own tables and +options. The shared menu appears on each site's admin separately. + +## Troubleshooting + +- **No emails sent:** check that `wp_mail()` works on your host (send a test + from Settings → General → site admin email). Check the Activity tab for + failed sends and their error string. +- **Carts not marked abandoned:** verify the threshold is not set to 0 and + that the `nlrem_abandon_sweep` cron has run (Activity tab shows the last + sweep timestamp). +- **Duplicate emails:** should not happen; the `nlrem_sends` table is + checked before each send. If you see duplicates, check for a second + installation of this plugin (e.g. a stale `mu-plugin` copy).