etechflow / module-abandoned-cart

etechflow/module-abandoned-cart

Abandoned Cart Email + Exit-Intent Popup extension for Magento 2 — recovers lost sales via automated email reminders and on-site discount popups. Fully compatible with Luma, Hyva, and Adobe Commerce.

magento2-module Compatibility: 2.4.7-2.4.8 Code Quality: Fail Tests: N/A Security: Pass proprietary

ETechFlow Abandoned Cart Email for Magento 2

Recover lost sales with automated, personalised abandoned-cart email reminders. Fully compatible with Luma, Hyvä, and Adobe Commerce.


Features

  • Configurable email sequences — send up to 9 reminders per cart at custom intervals (e.g., 1 hour, 24 hours, 72 hours)
  • One-click cart restore — customers click the link in the email and their cart is back exactly as they left it, optionally with auto-login
  • Auto-generated discount coupons — incentivise recovery with unique single-use coupon codes per email
  • Open & click tracking — measure exactly which emails are working and which carts they recovered
  • Rich targeting — per-store, per-customer-group, by cart subtotal range, by item count, by Magento price-rule conditions
  • Guest cart support — track and email visitors who reached checkout but never logged in
  • Test mode — preview emails by redirecting to a dev inbox before going live
  • Unsubscribe link — built into every email, with confirmation page
  • Recovery dashboard — total abandoned, total recovered, recovery rate, revenue recovered, by date range
  • Per-rule analytics — at-a-glance recovery rate per rule in the rules grid

Compatibility

Open Source 2.4.6 Open Source 2.4.7 Adobe Commerce 2.4.6 Adobe Commerce 2.4.7
Luma theme
Hyvä theme 1.3+
PHP 8.1 / 8.2 8.2 / 8.3 8.1 / 8.2 8.2 / 8.3

Installation

Via Composer (recommended)

composer require etechflow/module-abandoned-cart
bin/magento module:enable Etechflow_AbandonedCart
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush

Manual (upload zip)

  1. Upload the ETechFlow/AbandonedCart folder to app/code/ETechFlow/AbandonedCart/ on your server
  2. SSH in and run:
cd /path/to/magento
bin/magento module:enable Etechflow_AbandonedCart
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush

Verify the install

bin/magento module:status Etechflow_AbandonedCart
# Expected: Module is enabled
bin/magento etechflow:abc:verify
# Expected: ALL CHECKS PASSED

Cron must be running

The module's emails are sent by Magento cron. If you haven't already set up Linux cron:

bin/magento cron:install
crontab -l   # verify it was added

Configuration

Go to Stores → Configuration → ETechFlow → Abandoned Cart Email.

Key settings to review on first install:

  • General → Enable Module: Yes
  • General → Cart Abandonment Threshold: 30 minutes (default — adjust to your store's checkout flow)
  • License → License Key: Paste the key from your purchase email (development hosts skip this)
  • Email Sending → Sender Identity: Pick which "Store Email Address" sends the recovery emails
  • Cart Restore → Restore Token Expiry: 30 days default

Then create your first rule under Marketing → ETechFlow Abandoned Cart → Email Rules → Add New Rule.

A typical sequence:

  1. Rule 1: send 1 hour after abandonment, friendly reminder, no coupon
  2. Rule 2: send 24 hours later, includes 5% coupon
  3. Rule 3: send 72 hours later, "last chance" with 10% coupon

CLI commands

Command Purpose
bin/magento etechflow:abc:verify End-to-end smoke test. Run after install and after upgrade.
bin/magento etechflow:abc:perf Micro-benchmark of hot paths. Add --iterations=N and --json=path.
bin/magento etechflow:abc:send Force a cron tick now (don't wait for the schedule).
bin/magento etechflow:abc:cleanup Force the cleanup cron now.

Performance

This module is built for high-traffic stores. Performance characteristics on warm cache:

Hot path p95 target
Frontend cart-save observer < 0.5 ms
Per-cron-tick batch (50 carts) < 1.5 s
1-click restore controller < 50 ms
Tracking pixel < 20 ms

Storefront pages take ZERO additional work from this module — all heavy lifting happens in cron.


Hyvä theme

Hyvä compatibility ships in the same package. The module detects the active theme automatically and:

  • Sends Hyvä-styled email templates (Tailwind classes) on Hyvä storefronts
  • Sends Luma-styled templates on Luma storefronts
  • Restore + Unsubscribe pages render with both Block (Luma) and ViewModel (Hyvä) paths — no Knockout on Hyvä

Adobe Commerce

The module works fully on Adobe Commerce 2.4.6 / 2.4.7 and adds:

  • Future v1.1.0: B2B company-account abandoned-cart support
  • Future v1.1.0: Customer Segments integration
  • Future v1.1.0: GraphQL endpoints for headless

v1.0.0 already handles multi-website / multi-store and AC's customer-group targeting.


Uninstall

bin/magento module:disable Etechflow_AbandonedCart
composer remove etechflow/module-abandoned-cart
bin/magento setup:upgrade

Database tables (etechflow_abandoned_cart, etechflow_abandoned_cart_rule, etechflow_abandoned_cart_email_log) are dropped by the schema patch on uninstall.


Support


License

Proprietary. See LICENSE.txt for terms. A per-installation license is required for production use.

Changelog

All notable changes to Etechflow_AbandonedCart are documented here. Format follows Keep a Changelog and the project adheres to Semantic Versioning per ETechFlow Module Development Standards §3.


v1.0.1 — 2026-06-05

Security + bundle-consistency fix.

  • Rotated per-module SECRET_FRAGMENTS (closes accidental plaintext-secret exposure in v1.0.0)
  • Replaced plain BUNDLE_SECRET constant with BUNDLE_SECRET_FRAGMENTS array (aligned with other ETechFlow modules)
  • BUNDLE_ID changed from 'ETECHFLOW_MAGENTO_BUNDLE_V1' to 'etechflow-bundle' (matches the rest of the suite — bundle keys interoperate)
  • MODULE_ID changed from 'abandoned-cart-popup' to 'abandoned-cart' (matches composer package name)
  • Dropped backward-compat for legacy v1.0–v1.2 'host|hmac' key format (no merchants on those versions)

⚠️ v1.0.0 keys (per-module or bundle) no longer validate. Re-issue keys via tools/generate-license.php.

Unreleased

Nothing pending — see v1.0.0 below for the initial release.

1.0.0 — 2026-05-21

Released after the 22-phase build + bulk re-deploy + end-to-end verification on the magento-dev.etechflow.com Docker stack.

Initial release — production-ready abandoned-cart recovery for Luma, Hyvä, and Adobe Commerce

Etechflow_AbandonedCart ships with a complete cart-recovery email system that detects abandoned carts via cron (no per-request scanning), sends configurable email sequences with 1-click restore links and optional auto-generated discount coupons, and attributes recovered revenue back to the originating emails for reporting. Built to match Amasty's feature surface with five concrete UX improvements (plain-English tooltips, inline rule preview, specific CSV-error messages, per-rule recovery rate in the rules grid, multi-recipient test mode).

Added

  • Cart abandonment trackingCartSaveObserver records every cart save into etechflow_abandoned_cart, with all four mandatory observer guards (enabled / bulk-importer / indexer-processing / relevant-change).
  • Configurable email sequences — up to 9 rules per cart, ordered by priority, with per-rule store / customer-group / cart-subtotal / Magento-price-rule conditions.
  • One-click cart restoreController/Restore/Index with HMAC-signed single-use tokens, configurable token expiry, optional auto-login for logged-in customers, optional merge with the customer's current cart.
  • Auto-generated discount couponsModel/CouponGenerator issues per-email single-use coupon codes tied to a Magento sales rule the merchant chooses.
  • Email open & click tracking — 1×1 pixel + URL wrapping via Controller/Track/Open and Controller/Track/Click. UTM parameters auto-appended (configurable).
  • Unsubscribe flow — every email carries an unsubscribe link; the confirmation page is Luma + Hyvä compatible.
  • Recovery attributionOrderPlaceAfterObserver + Quote\SubmitPlugin mark carts as RECOVERED and link them back to the email that drove the conversion.
  • Test Mode — redirect all outbound emails to a comma-separated list of dev inboxes for safe pre-launch testing.
  • Hyvä compatibilityview/frontend/templates/hyva/ + ViewModel/ + hyva_default.xml deliver Alpine-powered restore + unsubscribe pages with no Knockout dependencies.
  • Admin Rules grid + form — full CRUD UI Component at Marketing → ETechFlow Abandoned Cart → Email Rules, with inline per-rule recovery rate.
  • Admin Carts grid + view — list every tracked cart with filters by status / customer / store / date, plus per-cart "Send Now" manual trigger.
  • Admin Reports dashboard — total abandoned, total recovered, recovery rate, open rate, click rate, revenue recovered, by date range.
  • CLI commandsetechflow:abc:verify (end-to-end smoke), etechflow:abc:perf (micro-benchmark with --iterations and --json), etechflow:abc:send (manual cron trigger), etechflow:abc:cleanup (manual cleanup trigger).
  • License validator — HMAC-signed per-installation licenses with .test / .local / .docksal / .ddev / .lando / localhost / 127.0.0.1 dev-host auto-bypass and bundle-key support.
  • Performance instrumentationModel/Performance/Profiler.php wraps every hot path (ETechFlow_ABC_CronTick, ETechFlow_ABC_RuleMatch, ETechFlow_ABC_EmailSend, ETechFlow_ABC_Restore) with no-op-when-absent Tideways spans.
  • Declarative schema — 3 tables (etechflow_abandoned_cart, etechflow_abandoned_cart_rule, etechflow_abandoned_cart_email_log) with 11 indexes including composite indexes tuned for the cron's hot queries.
  • Data patchesInstallDefaultRules ships sensible 1h/24h/72h rules disabled by default; RegisterEmailTemplates registers 3 Luma + 3 Hyvä templates.
  • i18n — 130+ translatable strings in i18n/en_US.csv ready for localisation.
  • Adobe Commerce support — works on AC 2.4.6 / 2.4.7. Composer suggests magento/module-company (B2B) and magento/module-graph-ql (headless) for future v1.1.0 features.

Backwards compatibility

  • This is the initial release — no prior versions exist.
  • Module ships with general/enabled=1 BUT no active rules. Merchants must explicitly create + activate rules before any email is sent. Per §0 mindset rule 2 (zero behavioural change until opt-in).

Migration tip

  • After install, run bin/magento etechflow:abc:verify to confirm everything is wired.
  • Create at least one rule under Marketing → ETechFlow Abandoned Cart → Email Rules before going live.
  • Enable Test Mode (general/test_mode=1) for the first 48 hours after launch to preview emails to your dev inbox before they reach real customers.

Performance baseline (warm cache, p95)

  • Frontend cart-save observer: < 0.5 ms (no DB write on the hot path — only an enqueue)
  • Cron tick processing 50 carts: < 1.5 s
  • 1-click restore controller: < 50 ms (HMAC verify + cart restore)
  • Tracking pixel response: < 20 ms

Versions
Version Stability QA Status Compatibility Released
1.0.4 stable Fail Magento 2.4.7-2.4.8 Details 2026-06-22 15:15:11
1.0.1 stable Not tested Not yet tested Details 2026-06-05 10:33:56

Requires 13

Package Constraint
magento/framework >=103.0.0
magento/module-backend >=102.0.0
magento/module-checkout >=100.0.0
magento/module-config >=101.0.0
magento/module-cron >=100.0.0
magento/module-customer >=103.0.0
magento/module-email >=101.0.0
magento/module-quote >=101.0.0
magento/module-sales >=103.0.0
magento/module-sales-rule >=101.0.0
magento/module-store >=101.0.0
magento/module-ui >=101.0.0
php ~8.1.0||~8.2.0||~8.3.0||~8.4.0

Suggests 2

Package Reason
magento/module-company Required only on Adobe Commerce B2B for company-level abandoned-cart tracking
magento/module-graph-ql Required only when exposing abandoned-cart data to headless / PWA storefronts

Compatibility

Each Magento release line is installed on its supported PHP versions, then the module is built (DI compilation + static-content deploy) and its unit and integration suites are run. The matrix shows the lines and PHP versions the module is confirmed to install and run on. Code-quality results further down (phpstan, phpcs, …) are reported separately and never affect compatibility.

Compatibility matrix (Magento × PHP)
Magento PHP 8.2 PHP 8.3 PHP 8.4 PHP 8.5
2.4.7 Pass Pass
2.4.8 Pass Pass
2.4.9 Pass not tested

Code Quality

Advisory checks against the module's source. Static analysis runs once across the whole module; PHPStan re-runs per Magento + PHP version because resolvable symbols differ between releases. These NEVER affect the Compatibility badge — a phpcs finding can't make a module incompatible.

Static analysis

Coding standards (phpcs), mess detection (phpmd), copy-pasted code (cpd), PHP cross-version compatibility, composer.json validity. Each runs once for the whole module.

Static analysis results
Tool Status Findings Summary
PHPCS Fail 378 32 errors, 346 warnings (ruleset: Magento2) — 146 auto-fixable with phpcbf
PHPMD Error 0 phpmd reported an analysis error: Unexpected token: [, line: 82, col: 19, file: tools/generate-license.php. #0 /opt/composer-global/vendor/pdepend/pdepend/src/main/php/PDepend/Source/Language/PHP/AbstractPHPParser.php(8056): PDepend\Source\Parser\UnexpectedTokenException->__construct(Object(PDepend\Source\Tokenizer\Token), Object(PDepend\Source\AST\ASTCompilationUnit)) #1 /opt/composer-global/vendor/pdepend/pdepend/src/main/php/PDepend/Source/Language/PHP/AbstractPHPParser.php(8041): PDepend\Source\Language\PHP\AbstractPHPParser->getUnexpectedTokenException(Object(PDepend\Source\Tokenizer\Token)) #2 /opt/composer-global/vendor/pdepend/pdepend/src/main/php/PDepend/Source/Language/PHP/AbstractPHPParser.php(8006): PDepend\Source\Language\PHP\AbstractPHPParser->getUnexpectedNextTokenException() #3 /opt/composer-global/vendor/pdepend/pdepend/src/main/php/PDepend/Source/Language/PHP/AbstractPHPParser.php(2495): PDepend\Source\Language\PHP\AbstractPHPParser->consumeToken(7) #4 /opt/composer-global/vendor/pdepend/pde
Cpd Warning 6 6 duplicated chunks spanning 233 total lines (min-lines=5, min-tokens=70)
Composer validate Info 13 valid; 13 advisory notes (composer validate --strict)

PHPStan

Type-checks the module's PHP against a real Magento install at the configured gate level. Re-runs per Magento and PHP version because resolvable symbols differ between releases. Cell → details modal.

PHPStan results by Magento and PHP version
Magento PHP 8.2 PHP 8.3 PHP 8.4 PHP 8.5
2.4.7 88 88
2.4.8 88 88
2.4.9 88 N/A

Tests

Unit and integration suites, run for each applicable Magento and PHP version. A test failure speaks to the module's behaviour, not its compatibility with a Magento line, so it is reported here separately and never reddens the compatibility matrix.

Unit tests

Unit tests results by Magento and PHP version
Magento PHP 8.2 PHP 8.3 PHP 8.4 PHP 8.5
2.4.7 N/A N/A
2.4.8 N/A N/A
2.4.9 N/A N/A

Integration tests

Integration tests results by Magento and PHP version
Magento PHP 8.2 PHP 8.3 PHP 8.4 PHP 8.5
2.4.7 N/A N/A
2.4.8 N/A N/A
2.4.9 N/A N/A

Security

Security checks run directly against the module: an audit of its declared dependencies for known vulnerabilities (composer audit) and a scan of its source for malware and web-shell signatures. Each runs once. A malware detection fails the version outright.

Security results
Tool Status Findings Summary
Composer audit Pass 0
Malware scan Pass 0
License
proprietary
Authors

More from etechflow

View vendor
Make it pay

Turn an existing module into recurring revenue.

If you already maintain a Magento 2 module on GitHub or GitLab, listing it on Packagento takes about five minutes. We mirror your tags, handle distribution signing, and route paid licenses through Stripe Connect, so you can keep shipping the way you already do.