CartThrob 9 documentation for ExpressionEngine commerce teams Visit CartThrob.com
CartThrob.com

Notifications

Overview

CartThrob can send automatic notifications when checkout, inventory, order status, or add-on events occur. Email notification bodies are standard ExpressionEngine templates, so EE global variables, tags, conditionals, embeds, and layouts are available in addition to the variables injected by CartThrob.

You can create multiple notifications for the same event and send them to different people. Template parsing and notification delivery normally happen during the request that triggered the event. Expensive channel queries or other slow tags in a notification template can therefore delay the customer’s request.

To configure a notification:

  1. Create an EE template containing the message body.
  2. In CartThrob’s Notifications settings, click Add Notification.
  3. Set the subject, From name, From email, To email, and optional Reply-to values.
  4. Select the EE template.
  5. Select the event that should trigger the notification.
  6. For an order-status notification, select the original and new statuses.
  7. Select HTML or Plain Text.

Installed example templates

When you install CartThrob’s store example template group from the control panel, CartThrob creates these notification templates:

  • store/email_admin — completed-order email for the store administrator
  • store/email_customer — completed-order email for the customer
  • store/email_low_stock — short low-stock alert
  • store/email_status_change — short order-status-change alert

The default notification configuration refers to these paths. Installing the templates does not overwrite an existing template with the same name.

Address fields

The notification address settings have distinct jobs:

  • From name and From email identify the sender.
  • To email identifies the recipient. It may contain a parsed variable such as {customer_email} when the event supplies that value.
  • Reply-to name and Reply-to email control where replies are sent. If either reply-to value is empty, CartThrob falls back to the corresponding From value.

Test notifications with two different mailboxes so the visible sender, recipient, and reply destination can be checked independently. This also helps catch mail-provider policies that rewrite or reject the From address.

Template variables

The variables are not identical for every event. The tables under each event group list the data passed by that notification call. The built-in email delivery driver adds a small second group of variables to every email notification; those are listed separately below.

The same event variables are also parsed in the notification’s From, To, Reply-to, and Subject settings. For example, {customer_email} can be used in the To field for a payment event because payment events supply that variable. Low-stock events do not supply customer details, so {customer_email} should not be used for a low-stock recipient.

Variables available to every email notification

These values describe the configured email notification. They are usually more useful for diagnostics or shared email layouts than for the message itself.

Variable Output
{from} Configured From email address after CartThrob’s customer-address replacement, when applicable.
{from_name} Configured From name after CartThrob’s customer-name replacement, when applicable.
{from_reply_to} Configured Reply-to email, or the From email when Reply-to is empty.
{from_reply_to_name} Configured Reply-to name, or the From name when Reply-to name is empty.
{to} Configured recipient value after CartThrob’s customer-address replacement, when applicable.
{subject} Subject stored on the notification. Event variables in the actual outgoing subject are parsed separately.
{message_template} EE template path selected for the notification, such as store/email_customer.
{plaintext} 1 for a Plain Text notification and an empty value for an HTML notification.

For backward compatibility, the email parser also replaces ORDER_ID and {order_id}. They contain the payment event’s order entry ID when one was supplied; for non-order events they are empty. Prefer {order_id} in new templates. That is the ExpressionEngine entry ID, not the invoice ID contained in the title.

{customer_name} and {customer_email} are not universal variables. They are included in payment events and in custom events that explicitly provide them.

Using other template tags

A notification body is a normal EE template. It can use other ExpressionEngine and CartThrob tags, with notification variables passed into their parameters when useful. Variables produced by those tags are not notification variables and are not duplicated on this page; use the documentation for the tag itself.

See, for example:

The low-stock example below demonstrates this pattern with ExpressionEngine’s channel:entries tag.

Notification event groups

Payment events

The following control-panel events share the same checkout-order payload:

  • Successful Transaction (completed)
  • Declined Transaction (declined)
  • Failed Transaction (failed)
  • Customer completing transaction offsite (offsite)
  • Incomplete Transaction / processing (processing)
  • Refund alert (refunded)
  • Payment Expired (expired)
  • Payment Canceled (canceled)
  • Payment Pending (pending)

Values can be empty when they do not apply to the selected gateway or event. For example, an offsite event may not have a transaction ID yet, and a tokenized payment may not have a card type or last four digits.

Processing notifications for payment review

With the CartThrob 10 payment-reconciliation update, the existing Incomplete Transaction / processing event can also report a payment that needs merchant reconciliation. No new email recipient or notification is configured automatically.

These additional values are supplied for a reconciliation notification:

Variable Meaning
{payment_review} True for a payment requiring reconciliation.
{payment_review_kind} confirmed means the provider confirms collection; unknown means capture outcome is unconfirmed.
{transaction_id} The payment reference retained for investigation.
{error_message} Customer-safe review explanation, including instructions not to pay again.
{order_id} Saved order entry ID, when one exists.

Check the review flag before using ordinary “awaiting your check” wording:

{if payment_review}
    {if payment_review_kind == "confirmed"}
        <p>Payment was received, but this order needs review.</p>
    {if:else}
        <p>The payment outcome needs verification.</p>
    {/if}
    <p>{error_message}</p>
    <p>Payment reference: {transaction_id}</p>
{if:else}
    <p>Your order is processing. Follow the payment instructions supplied by the store.</p>
{/if}

A reconciliation hold dispatches Processing notifications, not the completed transaction event. Sending or resending an email does not resolve the payment or fulfill the order. Review any custom notification plugins or status-change emails that assume Processing means payment is safely complete.

Reconciliation, Purchased Items, and later status changes

Ordinary Processing creates Purchased Item channel entries when Save Orders and Save Purchased Items are enabled and configured. The payment-review hold withholds new entries while preserving available saved order line items. A Processing email must not assume that Purchased Item entries or download entitlements exist merely because the order is listed in Order Manager.

Mark reconciled dispatches neither Processing nor Completed notifications and does not create the withheld entries. Order Manager’s status edits can send configured Status Change notifications, but an EE status change does not run CartThrob’s full successful-checkout flow. The explicit Resend completed-order email action sends a receipt; it does not finish that flow.

The payment_review variables above are provided to the hold’s Processing notification. Do not assume they are also supplied to arbitrary status-change notifications or manually resent receipts. Review those rules separately, especially any rule that treats a status name as proof of collection.

Completed notifications after merchant acceptance

The paid-order completion workflow dispatches configured Completed notifications after supported local fulfillment steps finish. It supplies payment_review=false, clears payment_review_kind, and adds these values to the recovered order/customer payload:

Variable Meaning
{reconciliation_outcome} accepted or accepted_adjustment.
{reconciliation_amount} Net amount the merchant verified and accepted.
{reconciliation_currency} Original order currency for that amount.
{reconciliation_reference} Merchant-entered verification or adjustment reference.
{reconciliation_note} Merchant’s resolution note; consider whether it belongs in a customer-facing message.

The order total remains the original total, so an adjustment-aware receipt may need to show the accepted amount separately. These values are supplied to the completion dispatch, not automatically to every later resent receipt or arbitrary status-change event. Order Manager retains the recorded resolution for review.

Inventory processing can also send configured low-stock notifications. The action does not send another Processing notification. Record-only outcomes send neither checkout event. Existing notification selection and logging/sending settings still apply; no recipient is created automatically. A notification exception leaves the last step visible for manual follow-up, and completion is not automatically retried. Check notification logs before resending a message.

Order identifiers and site context

Variable Output
{entry_id}, {order_id} ExpressionEngine entry ID. Same source; same value in the normal saved-order flow.
{title}, {invoice_number} Full order entry title. Same source; same value. The invoice ID is the number contained in that title (prefix and suffix wrap it). It can match the entry ID depending on Order/Invoice Numbers; it is not always the same.
{order_number} Digits from the invoice ID contained in the title (on submitted_order_info only).
{member_id} Customer’s EE member ID, or 0 for a guest.
{author_id} Order author/member ID in subscription-update flows that explicitly set it. It is not present in every payment event.
{group_id} Customer’s EE member group ID.
{site_id} EE site ID for the checkout.
{site_name} Configured EE site name.

Totals

These are rounded numeric values from the checkout snapshot; they are not automatically formatted with a currency symbol.

Variable Output
{subtotal} Item subtotal before tax, shipping, and order discount.
{subtotal_plus_tax} Subtotal including applicable item tax.
{shipping} Shipping amount before shipping tax.
{shipping_plus_tax} Shipping amount including applicable tax.
{tax} Total tax amount.
{discount} Total cart/order discount.
{total}, {total_cart} Final checkout total. These are aliases in the payment payload.
{currency_code} Currency code supplied for the checkout, when present.
{subtotal_plus_shipping} Subtotal plus shipping. Added by certain subscription-update flows; do not assume it is present for every payment event.
{tax_rate} Effective tax rate. Added by certain subscription-update flows; do not assume it is present for every payment event.

Customer and billing details

Variable Output
{customer_name} Customer’s billing first and last names joined with a space.
{customer_email}, {email_address} Customer’s email address.
{customer_phone} Customer’s billing phone number.
{customer_ip_address}, {ip_address} IP address recorded for the checkout.
{billing_first_name}, {first_name} Billing first name.
{billing_last_name}, {last_name} Billing last name.
{billing_company}, {company} Billing company.
{billing_address}, {address} First billing address line.
{billing_address2}, {address2} Second billing address line.
{billing_city}, {city} Billing city.
{billing_state}, {state} Billing state, province, or region.
{billing_zip}, {zip} Billing postal code.
{billing_country}, {country} Billing country value stored with the customer.
{billing_country_code}, {country_code} Billing country code stored with the customer.
{full_billing_address} Billing street, city, state, and postal code combined as a multiline string.

The shorter names are aliases of the corresponding billing_* values.

Shipping details

When Use billing information is enabled at checkout, the shipping values contain the corresponding billing values.

Variable Output
{shipping_first_name} Shipping first name.
{shipping_last_name} Shipping last name.
{shipping_phone} Shipping phone number.
{shipping_company} Shipping company.
{shipping_address} First shipping address line.
{shipping_address2} Second shipping address line.
{shipping_city} Shipping city.
{shipping_state} Shipping state, province, or region.
{shipping_zip} Shipping postal code.
{shipping_country} Shipping country value stored with the customer.
{shipping_country_code} Shipping country code stored with the customer.
{full_shipping_address} Shipping street, city, state, and postal code combined as a multiline string.

Payment and checkout details

Variable Output
{payment_gateway} Selected gateway class name without the leading Cartthrob_.
{payment_gateway_method} Selected gateway method, when the gateway supports methods.
{transaction_id} Legacy top-level transaction value. It can be empty even after the gateway returns a reference; use submitted_order_info when a resolved transaction ID is required.
{card_type} Detected or submitted card brand, when available.
{last_four_digits} Last four digits supplied during checkout, when available.
{coupon_codes} Applied coupon codes joined with commas.
{subscription_id} Related subscription ID, when the event belongs to a subscription flow.
{create_user} Whether checkout requested member creation.
{return} General return URL saved with the checkout.
{authorized_redirect} Success redirect selected for the checkout.
{processing_redirect} Processing redirect selected for the checkout.
{declined_redirect} Declined-payment redirect selected for the checkout.
{failed_redirect} Failed-payment redirect selected for the checkout.

Custom checkout data

Scalar custom customer-information fields are merged into the payment payload under their configured names. Cart custom data is available with a custom_data: prefix:

{custom_data:your_key}

These names depend on the site’s customer-field and custom-data setup, so they cannot be listed globally.

Non-scalar and legacy payload values

The checkout payload also carries internal arrays named auth, coupon_codes_array, purchased_items, subscription, and subscription_options. They are not a stable set of directly printable template variables: CartThrob removes associative non-row arrays before parsing, and their shapes vary by checkout path. Use:

  • {coupon_codes} for a printable coupon list;
  • submitted_order_info for normalized authorization state, transaction ID, and error message;
  • order_items for saved purchased-item rows;
  • the CartThrob Subscriptions tags for subscription records.

Some subscription and rebill paths can also carry the legacy scalar keys authorized, processing, declined, failed, and error_message. These values are normally empty in the direct payment payload. Use submitted_order_info rather than relying on them.

Items

The checkout snapshot includes an {items} variable pair:

{items}
    {title} — {quantity} × {price}
{/items}

Each row can contain:

Variable Output
{row_id} Cart row identifier.
{entry_id}, {product_id} Product entry ID.
{site_id} Product’s EE site ID.
{title} Product/item title.
{quantity} Quantity purchased.
{price} Unit price after option-based pricing.
{price_plus_tax} Unit price including applicable tax.
{weight} Calculated item weight.
{shipping} Item shipping amount calculated by CartThrob.
{discount} Discount amount returned for the item.
{no_tax} Whether the item is marked tax exempt.
{no_shipping} Whether the item is marked as requiring no shipping.
{class} Cart item class, such as product or package, when present.

Rows can also contain the nested item_options, meta, discounts, and sub_items collections, plus an internal parent_item link in some item classes. These values are not a stable scalar template surface; their keys and shapes depend on the product and installed fieldtypes. For saved-order line items, formatted subtotals, package rows, and product channel fields, use the order_items tag.

Sensitive payment values

Some checkout internals can temporarily include CVV2, expiration_month, or expiration_year. Never output these values in a notification, subject, log, or stored template. They are not a supported notification-template API. CartThrob does not expose a full card-number template variable.

Low-stock event

The Low stock warning (low_stock) event adds only these variables:

Variable Output
{entry_id} Product entry ID whose inventory was reduced.
{inventory} Remaining inventory after the purchase quantity was deducted.

The event is sent when the resulting inventory is at or below the low-stock level configured in CartThrob’s product settings. It does not include customer or order variables.

Example: pass a notification variable to another tag

That is enough data to load the complete product entry with ExpressionEngine’s channel:entries tag. This fuller low-stock template outputs the remaining inventory alongside standard product fields:

<p><strong>Low stock warning:</strong> {inventory} remaining.</p>

{exp:channel:entries
    entry_id="{entry_id}"
    dynamic="no"
    limit="1"
    disable="categories|member_data|pagination"
}
    <h2>{title}</h2>
    <p>Product entry ID: {entry_id}</p>
    <p>Product URL title: {url_title}</p>

    {!-- Add site-specific product fields here, such as {product_sku}. --}
{/exp:channel:entries}

{entry_id} and {inventory} come from the low-stock event. {title}, {url_title}, and any custom product field short names are parsed by channel:entries. A channel parameter is not required because the entry ID uniquely identifies the product.

Order-status-change event

The Order status has been changed (status_change) event adds these core variables:

Variable Output
{entry_id} Order entry ID that changed.
{status} New EE order-entry status.
{previous_status} Status before the change.
{channel_id} Orders channel ID.
{url_title} Order entry URL title, when included by the update path.

Depending on whether the change was made through ExpressionEngine publishing, CartThrob Order Manager, Channel Form, or custom code, the payload can also contain entry metadata and saved order fields. Order Manager supplies channel field short names and field_id_N aliases, but templates intended to work across every update path should not depend on those optional values.

Other EE and CartThrob tags can retrieve the complete saved order by using {entry_id} as a tag parameter. Refer to that tag’s documentation for the variables it produces.

When both an original status and a new status are configured, CartThrob matches the complete transition. A notification configured for Backordered to Shipped does not run for a different starting status that also ends at Shipped.

Custom application events

CartThrob add-ons can register additional event names. A custom event receives the variables that the add-on passes when it dispatches the event, plus the shared email variables listed above. There is no universal CartThrob payload for application events.

Add-on developers can see Using CartThrob’s Notification System for event registration and dispatch examples.

Reviewing notifications after an upgrade

CartThrob continues to normalize legacy notification keys so existing configurations can be read. Compatibility does not guarantee that an old notification still expresses the desired event, template, addresses, or status transition. After an upgrade, review every notification in the control panel and send test messages for successful, failed, and status-change cases used by the site.