Skip to content

Functions & Constants ​

The PHP functions and constants you can safely use from your own code, plus where ShapedRecover keeps its jobs and data so you can find them.

These functions are ShapedRecover's public PHP interface. ShapedRecover Pro uses exactly the same ones, which is a good sign they'll stay stable. Anything not listed here, such as the plugin's classes, is internal and can change in any release.

Before you call a function ​

The functions are defined as soon as the plugin file loads, even when the plugin is dormant (for example while WooCommerce is deactivated). Several of them need WooCommerce, so call them only after shaped_recover_loaded has fired:

php
if ( did_action( 'shaped_recover_loaded' ) ) {
	$cart = shaped_recover_cart( 42 );
}

Code that runs from a ShapedRecover hook, on an admin page, or on a later front-end hook (init, wp, template_redirect) runs after that action. Keep the check anyway: while the plugin is dormant, the action never fires. See Before you start for where to put your code.

Times are UTC. Every date ShapedRecover stores or takes ends in _gmt and is UTC, formatted Y-m-d H:i:s. Convert with get_date_from_gmt() before showing one to a person.

Functions ​

FunctionReturns
shaped_recover_setting()One setting's value
shaped_recover_can()Whether a Pro feature is available
shaped_recover_capabilities()Every available feature key
shaped_recover_cart()One stored cart
shaped_recover_abandoned_carts()Carts abandoned in a date range
shaped_recover_recovered_sales()Recovered sales in a date range
shaped_recover_delete_carts_by_email()Nothing; deletes carts
shaped_recover_money()An amount as plain text
shaped_recover_email_headers()Mail headers using your sender settings
shaped_recover_register_feature()Nothing; Advanced

shaped_recover_setting() ​

php
shaped_recover_setting( string $key ): mixed

The value of one setting, as the plugin itself uses it.

  • A setting you've never saved returns its default.
  • A Pro setting returns its default while that Pro feature isn't available (Pro not installed, or its license inactive), even if a value is stored. That's how the plugin behaves too, so you see what it sees.
  • An unknown key returns null.
php
if ( shaped_recover_setting( 'tracking_enabled' ) ) {
	$minutes = shaped_recover_setting( 'abandon_after_minutes' ); // 15 unless changed.
}

Setting keys ​

KeySettingTypeDefault
tracking_enabledAbandoned Trackingboolfalse
abandon_after_minutesMark Cart as Abandoned Afterint (5–1,440)15
lost_after_daysMark Cart as Lost Afterint (1–365)30
exclude_rolesDisable Tracking Forrole slugsadministrator, shop_manager
never_trackNever Track These Addresses (Pro)lower-cased emailsempty
coupon_prefixCode PrefixstringSAVE
coupon_lengthCode Lengthint (6–20)10
coupon_combineAllow Coupons to Combine (Pro)boolfalse
coupon_exclude_saleExclude Sale Items (Pro)boolfalse
coupon_auto_cleanupDelete Coupons Automaticallybooltrue
coupon_cleanup_frequencyRun Cleanupdaily, weekly, monthlyweekly
consent_labelConsent Checkbox Labelstring"I agree to receive emails about my cart."
from_nameFrom Namestringempty (WooCommerce's sender name is used)
from_addressFrom Addressemailempty (WooCommerce's sender address is used)
reply_toReply-to Addressemailempty
link_opensRecovery Link Openscheckout, cartcheckout
link_expires_daysLink Expires Afterint (1–30)7
notify_recoveryNotify on Recovery (Pro)booltrue
notify_abandonmentNotify on Abandonment (Pro)boolfalse
notify_recipientsSend Notifications to (Pro)lower-cased emailsthe site's admin email
notify_frequencyHow Often (Pro)daily, realtime, twice_daily, weekly, offdaily
retention_cartsRecoverable Cartsarray( 'value' => int, 'unit' => string )90 days, or your Lost cutoff if longer
retention_sendsSend Historyarray( 'value' => int, 'unit' => string )180 days
delete_data_on_uninstallDelete Everything on Uninstallboolfalse

What each setting does is covered in Settings. There's no function to change a setting: use the Settings tab, which validates every value.

shaped_recover_can() ​

php
shaped_recover_can( string $key ): bool

Whether a Pro feature is available on this request. Pro's keys are never_track, coupon_restrictions, coupon_exclude_products, product_report_widget and admin_notifications. They're available while Pro is active with an active or expired license.

php
if ( shaped_recover_can( 'admin_notifications' ) ) {
	// Pro's Admin Notifications are switched on for this store.
}

Ask this, rather than checking whether the Pro plugin is active: Pro can be installed without a license.

shaped_recover_capabilities() ​

php
shaped_recover_capabilities(): string[]

Every feature key available on this request. In the free plugin alone it's an empty array. It's worked out fresh on every call and never stored, so installing or removing Pro shows up on the next request.

shaped_recover_cart() ​

php
shaped_recover_cart( int $id ): ?array

One stored cart by its ID (the number shown on the Abandoned tab), or null if there's no such cart.

Useful keys in the returned array:

KeyTypeWhat it holds
idintCart ID.
statusstringshopping, abandoned (shown as Recoverable), recovered, ordered or lost.
email, first_name, last_namestringThe shopper, email lower-cased.
user_idintCustomer account, 0 for a guest.
contentsarrayLine items: product_id, variation_id, variation, quantity, price, price_incl, name and more.
total, currencyfloat, stringCart total and currency code.
last_activity_gmtstringLast time the shopper touched the cart.
abandoned_gmtstring|nullWhen it most recently became Abandoned.
closed_gmtstring|nullWhen it was Recovered, Ordered or Lost.
order_idintThe order that closed it, 0 if none.
pausedint1 while you've paused its emails.

The full list of columns follows the database table and can grow in later releases, so read the keys you need and ignore the rest.

php
$cart = shaped_recover_cart( 42 );

if ( $cart && 'abandoned' === $cart['status'] ) {
	printf( '%s left %d items behind.', esc_html( $cart['email'] ), count( $cart['contents'] ) );
}

shaped_recover_abandoned_carts() ​

php
shaped_recover_abandoned_carts( string $start, string $end ): array

Every cart that most recently became Abandoned between $start (included) and $end (not included), whatever its status is now. Both are UTC, Y-m-d H:i:s. Each item has the same shape as shaped_recover_cart().

php
// Carts abandoned in the last 24 hours.
$carts = shaped_recover_abandoned_carts(
	gmdate( 'Y-m-d H:i:s', time() - DAY_IN_SECONDS ),
	gmdate( 'Y-m-d H:i:s' )
);

Keep ranges sensible on a large store: every matching cart is loaded at once.

shaped_recover_recovered_sales() ​

php
shaped_recover_recovered_sales( string $start, string $end ): array

The recovered sales credited in a range, counted exactly as Reports and the Dashboard count them. A sale is credited when its order becomes paid; orders that are missing, no longer paid, or whose credit was taken back by a full refund or cancellation are left out. Dates are UTC, $end not included.

Each sale has:

KeyTypeWhat it holds
order_id, numberint, stringThe order's ID and its number as WooCommerce shows it.
urlstringThe order's edit screen.
name, emailstringBilling name and email.
value, currencyfloat, stringOrder total minus refunds, and its currency.
credited_gmtstringWhen the sale was credited.
ttrintTime to recover: seconds from abandonment to the order being placed.
cart_idintThe recovered cart.
campaignstringThe name of the campaign whose email brought the shopper back, or empty.
sent_gmtstringWhen that email was sent.
token_idintThe recovery link (token) the order came through.
php
$sales = shaped_recover_recovered_sales( '2026-10-01 00:00:00', '2026-11-01 00:00:00' );
$total = array_sum( array_column( $sales, 'value' ) );

Amounts are in each order's own currency, so only add them up on a single-currency store. The function loads each order in turn, so cache the result if you show it often.

shaped_recover_delete_carts_by_email() ​

php
shaped_recover_delete_carts_by_email( string[] $emails ): void

Permanently deletes every stored cart for these addresses, along with their send history and recovery links. Pro's Never Track list calls it for every listed address each time the list is saved. Orders and coupons in WooCommerce aren't touched.

  • Pass addresses lower-cased: they're matched exactly, and ShapedRecover stores them lower-cased.
  • There's no undo. To erase a shopper at their request, WordPress's Tools › Erase Personal Data is usually the better route; see Unsubscribe & Privacy.
php
shaped_recover_delete_carts_by_email( array( strtolower( 'Test@MyStore.com' ) ) );

shaped_recover_money() ​

php
shaped_recover_money( float $amount, string $currency = '' ): string

An amount as plain text in your store's price format, for example $12.50. No HTML. Pass a currency code to format in that currency; leave it empty for your store's.

php
echo esc_html( shaped_recover_money( 12.5 ) ); // $12.50

shaped_recover_email_headers() ​

php
shaped_recover_email_headers(): string[]

Mail headers for an HTML email from your store, built from Settings › Sending: Content-Type: text/html, the From Name and From Address (WooCommerce's sender when they're empty), and Reply-to Address when it's set. Use it so your own emails come from the same sender as recovery emails.

php
wp_mail(
	'owner@mystore.com',
	'Weekly recovery summary',
	'<p>Your summary…</p>',
	shaped_recover_email_headers()
);

shaped_recover_register_feature() ​

php
shaped_recover_register_feature( string $key ): void

Advanced: used by ShapedRecover Pro. Records that loaded code implements a feature key. A key becomes available only when it's registered here and the shaped_recover_capabilities filter allows it. That's why a filter on its own can't unlock a Pro feature. You won't need this unless you're building an add-on with its own gated features.

Constants ​

Read these; never define or change them.

ConstantPluginValue
SHAPED_RECOVER_VERSIONFreeThe installed version, e.g. 1.0.0.
SHAPED_RECOVER_MIN_WCFreeThe lowest WooCommerce version the plugin loads with: 8.3.
SHAPED_RECOVER_FILEFreeFull path to the main plugin file.
SHAPED_RECOVER_PATHFreeThe plugin folder's path, with a trailing slash.
SHAPED_RECOVER_URLFreeThe plugin folder's URL, with a trailing slash.
SHAPED_RECOVER_BASENAMEFreeshaped-recover/shaped-recover.php on a standard install.
SHAPED_RECOVER_PRO_VERSIONProThe installed Pro version.
SHAPED_RECOVER_PRO_MIN_FREEProThe lowest free-plugin version Pro boots with: 1.0.0.
SHAPED_RECOVER_PRO_FILE, _PATH, _URL, _BASENAMEProThe same as Free's, for Pro.

SHAPED_RECOVER_VERSION is defined whenever the free plugin is active, even when it's dormant. To know whether it actually loaded, check did_action( 'shaped_recover_loaded' ). Pro defines a few more constants for its license server; they're internal.

The plugin files also define global functions that run their own start-up: shaped_recover_activate(), shaped_recover_deactivate(), shaped_recover_init() and shaped_recover_dependencies_met() in Free, and a set of shaped_recover_pro_*() functions in Pro. They aren't part of the public interface; don't call them.

Background jobs ​

ShapedRecover's jobs run through Action Scheduler and all sit in the group shaped-recover. To see them, go to WooCommerce › Status › Scheduled Actions and search for shaped_recover. The View Scheduled Actions link in the late-jobs notice opens that same view.

HookWhenWhat it does
shaped_recover_sweepEvery 5 minutes by default (recurring)Moves cart statuses on, then sends due emails.
shaped_recover_daily03:00 site time (each run schedules the next)Retention clear-out and coupon cleanup.
shaped_recover_dispatchStraight away, when a backlog is waitingA follow-up run that only sends due emails. At most one waits at a time.
shaped_recover_purgeWhen a retention clear-out has more to deleteContinues the clear-out in batches.
shaped_recover_coupon_cleanupAfter the daily job, when there's more to deleteContinues coupon cleanup in batches.
shaped_recover_migrateAfter an update that changes stored dataBrings old data up to date in batches.
  • You can attach your own code to shaped_recover_sweep and shaped_recover_daily; see Hooks. Leave the other four alone: they're internal steps of a larger task.
  • If you delete the sweep or daily job by hand, the next admin page load puts it back. Deactivating the plugin removes all of them.
  • While tracking is on, a sweep that's more than 15 minutes overdue shows the late-jobs notice on ShapedRecover's tabs. See Requirements for keeping jobs on time.

Stored data ​

This is for orientation: when you're looking at a database, a backup or a migration, you'll know what belongs to ShapedRecover. Don't write to these directly. Use the admin screens and the functions above. Writing to the tables can skip the checks that keep sending, attribution and reports correct, and the layout changes between versions.

  • Options are prefixed sprcv_. Your settings live in one option, sprcv_settings, which holds only the values you've saved; anything missing uses its default. Pro adds one option, sprcv_license. Short-lived transients use the same prefix.
  • Tables are prefixed with your WordPress table prefix plus sprcv_, e.g. wp_sprcv_carts:
TableHolds
sprcv_cartsCaptured carts and their status.
sprcv_campaignsYour recovery campaigns.
sprcv_sendsEvery scheduled and sent email (the send history).
sprcv_tokensRecovery links, stored hashed.
sprcv_unsubscribesUnsubscribed addresses, stored hashed.
  • User meta keys also start with sprcv_, for example a logged-in customer's consent choice.
  • Order meta on orders placed through a recovery link: _sprcv_cart_id, _sprcv_send_id, _sprcv_token_id, _sprcv_placed (when the order was placed) and _sprcv_reversed (credit taken back).
  • Coupon meta on generated coupons: _sprcv_generated, _sprcv_send_id, and _sprcv_used_gmt once used.
  • What's removed on uninstall is covered in Uninstalling & Data.

REST API ​

ShapedRecover registers REST routes under the namespace shaped-recover/v1. They exist only for the plugin's own admin screens: every route requires a user who can manage the store (manage_woocommerce), and the routes can change in any release without notice. They aren't a public API, so please don't build integrations on them. Use the functions and hooks on these pages instead.

Where to go next ​