magendoo / module-customer-segment

magendoo/module-customer-segment

Magento 2 dynamic customer segmentation module — rule-based segments with admin UI, REST API, CLI, and Cart Price Rule integration.

magento2-module Compatibility: 2.4.7-2.4.9 Code Quality: Fail Tests: Fail Security: Pass MIT

Are you the maintainer of magendoo?

Packagento pulls magendoo's Composer packages from the public registry so buyers can find them here.

Claim the namespace to take ownership, publish new releases directly, and start charging for premium versions.

Claim this namespace →

Magendoo CustomerSegment for Magento 2

A comprehensive Customer Segmentation module for Magento 2 Community Edition that enables merchants to create dynamic customer segments based on various criteria including customer attributes, order history, shopping cart data, and behavior patterns.

Screenshots

Segment Grid — manage all your customer segments at a glance

[image: Customer Segments Grid]

Segment Editor — visual rule builder with conditions and customer matching

[image: Customer Segment Edit]

Documentation

Document Description
User Guide End-user documentation for managing segments
Developer Documentation Technical documentation for developers
API Documentation REST API reference and examples
Testing Guide Unit testing patterns and best practices
Changelog Version history and changes

Features

Customer Segmentation

  • Dynamic Segments: Automatically assign customers based on rules
  • Manual Segments: Static customer assignments
  • Real-time Updates: Refresh segments on customer events
  • Scheduled Updates: Cron-based segment refresh

Condition Types

Customer Attributes

  • Email, First Name, Last Name
  • Date of Birth, Gender
  • Tax/VAT Number
  • Website, Store View, Customer Group
  • Account Creation Date

Order History

  • Total Orders Count
  • Total Revenue / Average Order Value
  • First/Last Order Date
  • Total Items Purchased
  • Used Coupon Codes
  • Payment/Shipping Methods
  • Shipping Countries
  • Order Status

Shopping Cart

  • Cart Subtotal
  • Cart Items Count
  • Contains Products (by SKU)
  • Has Active Cart
  • Days Since Cart Activity

Product Interactions

  • Purchased Products (SKU)
  • Purchased from Categories
  • Wishlist Items Count

Viewed-categories (product-view) segmentation is on the roadmap and not yet available.

Admin Features

  • Grid view of all segments with customer counts
  • Create/Edit segments with visual rule builder
  • Preview matching customers before saving
  • "Matched Customers" tab on edit page shows assigned customers
  • Refresh button on edit page
  • Mass actions (Delete, Refresh)
  • Export segment customers (CSV/XML)

API & Integrations

  • REST API for segment management
  • CLI commands for segment operations
  • Integration with Cart Price Rules
  • Segment indexer with mview support

Installation

Via Composer (Recommended)

This package is not on Packagist yet, so register the repository first:

composer config repositories.magendoo-customer-segment vcs https://github.com/florinel-chis/magendoo-m2-customersegment
composer require magendoo/module-customer-segment
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento setup:static-content:deploy -f
bin/magento cache:flush

Manual Installation

  1. Extract files to app/code/Magendoo/CustomerSegment/
  2. Run the following commands:
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento setup:static-content:deploy -f
bin/magento cache:flush

Configuration

  • Segment grid (create/edit/refresh segments): Customers → Customer Segments
  • Module settings (enable/disable, default refresh mode, cron schedule):
    Stores → Configuration → Customers → Customer Segments

Usage

Creating a Segment

  1. Navigate to Customers → Customer Segments
  2. Click "Add New Segment"
  3. Fill in the general information:
    • Name (required)
    • Description (optional)
    • Status (Active/Inactive)
    • Refresh Mode (Manual/Cron/Real-time)
  4. Configure conditions in the Conditions tab
  5. Save the segment
  6. Click "Refresh Segment Data" to populate customers

Segment Refresh Modes

Mode Description
Manual Admin must click refresh button to update
Cron Updated automatically on cron schedule (default: */5 * * * *, every 5 minutes)
Real-time Updated on customer events (register, save, login, order, quote merge)

CLI Commands

# Refresh specific segment(s)
bin/magento magendoo:customer-segment:refresh 1
bin/magento magendoo:customer-segment:refresh 1 2 3

# Refresh all active segments
bin/magento magendoo:customer-segment:refresh --all

# Export segment customers
bin/magento magendoo:customer-segment:refresh 1 --export --format=csv

Using Segments in Cart Price Rules

  1. Go to Marketing → Cart Price Rules
  2. Create or edit a rule
  3. In the Conditions section, add condition:
    • Customer Segmentis[Select your segment]
  4. Save the rule

API Reference

REST API Endpoints

Method Endpoint Description
GET /V1/customer-segments List all segments
GET /V1/customer-segments/:segmentId Get segment by ID
POST /V1/customer-segments Create new segment
PUT /V1/customer-segments/:segmentId Update segment (partial updates merge onto the stored record)
DELETE /V1/customer-segments/:segmentId Delete segment
POST /V1/customer-segments/:segmentId/refresh Refresh a single segment; returns the assigned count
POST /V1/customer-segments/refresh-all Refresh all active segments
GET /V1/customers/:customerId/segments Get the customer's segments
GET /V1/customers/:customerId/segment-ids Get the customer's segment IDs
GET /V1/customers/:customerId/segments/:segmentId/check Check if a customer is in a segment
GET /V1/customer-segments/:segmentId/customers?format=csv|xml Export a segment's customers; format is required and returns a CSV or XML string

Example: Create Segment via API

curl -X POST "https://your-store.com/rest/V1/customer-segments" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d '{
    "segment": {
      "name": "VIP Customers",
      "description": "Customers with 10+ orders",
      "is_active": true,
      "refresh_mode": "cron",
      "conditions_serialized": "{...}"
    }
  }'

Database Structure

Tables

Table Description
magendoo_customer_segment Stores segment definitions
magendoo_customer_segment_customer Customer-segment relationships
magendoo_customer_segment_log Segment activity log (save/refresh actions)

Events

The module dispatches the following events:

Event Payload keys Description
magendoo_customersegment_segment_save_before segment Before a segment model is saved
magendoo_customersegment_segment_save_after segment After a segment model is saved
magendoo_customersegment_refresh_before segment, segment_id Before a segment refresh
magendoo_customersegment_refresh_after segment, segment_id, assigned_customers, assigned_count After a segment refresh
magendoo_customersegment_customer_assigned customer_id, segment_id Customer assigned to a segment
magendoo_customersegment_customer_removed customer_id, segment_id Customer removed from a segment
magendoo_customersegment_conditions additional Register custom condition types

Extension Points

Adding Custom Conditions

Create a plugin to add custom conditions:

class AddCustomConditionPlugin
{
    public function afterGetNewChildSelectOptions($subject, $result)
    {
        $result[] = [
            'label' => __('My Custom Condition'),
            'value' => 'Vendor\Module\Model\Condition\MyCondition'
        ];
        return $result;
    }
}

Troubleshooting

Segments not refreshing

  1. Check if the segment is Active
  2. Verify cron is running: bin/magento cron:run
  3. Check logs at var/log/system.log

Customers not matching

  1. Verify condition logic
  2. Check that customer data exists
  3. Test with CLI: bin/magento magendoo:customer-segment:refresh --all

Performance issues

  1. Prefer conditions that resolve set-based (a single query) over ones that fall back to per-customer validation
  2. Use Manual or Cron refresh mode for large segments rather than Real-time
  3. Schedule cron refresh during low-traffic hours

Testing

Running Tests

# Run all module tests
vendor/bin/phpunit --filter Magendoo app/code/Magendoo/CustomerSegment/Test/Unit

# Run specific test class
vendor/bin/phpunit --filter SegmentManagementTest app/code/Magendoo/CustomerSegment/Test/Unit/Model/SegmentManagementTest.php

# Run with coverage
vendor/bin/phpunit --filter Magendoo --coverage-html coverage app/code/Magendoo/CustomerSegment/Test/Unit

Test Coverage

The unit suite covers SegmentManagement and every condition type (Combine, Customer, Order,
Cart, Product) plus set-based matching. Tests target PHPUnit 12.

Security Tested

  • ✅ CSV export neutralizes leading formula characters (=, +, -, @, tab, CR) to prevent spreadsheet formula injection
  • ✅ Condition type allowlist prevents arbitrary class instantiation

See TESTING.md for detailed testing documentation.

Support

For support and questions:

License

This module is licensed under the MIT License. See LICENSE for details.

Credits

Developed by Magendoo (https://magendoo.com)


Version: 2.0.0
Compatibility: Magento 2.4.x
PHP Version: 8.1+

Changelog

All notable changes to the Magendoo CustomerSegment module will be documented in this file.

The format is based on Keep a Changelog.

[2.0.0] - 2026-07-20

A correctness-focused release that fixes the segmentation engine along its main axis. Several fixes
change stored data and behaviour, so this is a breaking release.

Upgrade step (required): run bin/magento setup:upgrade. It applies two patches:
a schema patch that removes stale duplicate indexes/foreign keys left by older installs, and a
data patch that rewrites any segment whose conditions were stored in the legacy numeric-key shape
into the canonical conditions tree. Re-run refresh on affected segments afterwards.

Fixed

  • CRITICAL: Admin-created segments ignored their conditions and matched every customer. Condition
    children were serialized under numeric position keys with no conditions key, so the rule tree
    loaded as an empty combine. Conditions now serialize under an ordered conditions list that
    round-trips through Magento's rule engine. Existing broken rows are migrated by setup:upgrade.
  • CRITICAL: Whole condition families matched nobody or inverted their meaning — order
    payment/status/coupon/country, product purchased-negation and purchased-categories, cart subtotal
    >/<, and cart/negation operators. These now evaluate correctly, with negation applied at the
    customer level and explicit zero-row (no orders / empty cart) handling.
  • CRITICAL: Partial REST updates (PUT) overwrote stored scalars with defaulted DTO values,
    resetting customer_count, is_active, refresh_mode, and wiping conditions_serialized.
    Updates now merge onto the loaded model.
  • MAJOR: Membership matching was O(customers x conditions), issuing one query per customer per
    leaf. Conditions that can express themselves as a single query now resolve set-based.
  • MAJOR: refresh <id> --export always crashed under strict_types; the CLI now casts the id
    and handles export correctly.
  • MAJOR: CSV export crashed on PHP 8.4 (fputcsv deprecation). Fixed, and export now neutralizes
    leading formula characters to prevent spreadsheet formula injection.
  • MAJOR: MView customer subscription refreshed the wrong segment (customer ids were treated as
    segment ids). The changelog/indexer wiring is now segment-scoped and no longer self-perpetuates.
  • MEDIUM: Staleness checks compared stored UTC timestamps against session-timezone NOW();
    comparisons are now UTC-consistent (UTC_TIMESTAMP() / UTC-aware parsing).
  • MEDIUM: Segment refresh is now atomic (remove-all + mass-assign wrapped in one transaction).

Added

  • Helper\Data::isEnabled() now actually gates the module: realtime observers, the cron dispatcher,
    and the CLI no-op when customersegment/general/enabled is off.
  • SegmentManagementInterface::updateCustomerMembership(int $customerId) — re-evaluates a single
    customer against active realtime segments (no full rescan). Realtime observers call only this.
  • Activity log is now live: magendoo_customer_segment_log receives real rows on save and refresh
    (Model\ResourceModel\Log::log()).
  • Setup\Patch\Schema\DropLegacyDuplicateIndexes and Setup\Patch\Data\MigrateConditionsSerialized.

Changed

  • Behavior: a segment with no conditions now matches no customers. Previously an empty (or
    admin-saved-but-broken) condition tree silently matched every customer. Define at least one
    condition to select customers.
  • License is MIT across the module (composer.json, headers, LICENSE).
  • db_schema_whitelist.json regenerated to match the explicit referenceIds in db_schema.xml
    (fixes duplicate indexes and foreign keys on clean installs).
  • System config enabled is now a global (default-scope-only) operational toggle.
  • Test suite migrated to PHPUnit 12 attributes.

Removed

  • Dead Model\SqlBuilder scaffold (replaced by real set-based matching).
  • Non-functional customer-grid segment column stub (see Roadmap).
  • viewed_categories product condition — it was a placeholder that always matched nobody (see Roadmap).

[1.1.0] - 2026-04-03

Added

  • Product Interactions condition type (viewed categories, purchased products, purchased categories, wishlist items count) with between operator
  • SqlBuilder for batch customer validation (N+1 performance fix)
  • Segment indexer with mview support (etc/indexer.xml, etc/mview.xml)
  • System configuration admin panel (etc/adminhtml/system.xml, etc/config.xml) for enable/disable, default refresh mode, cron schedule
  • RefreshButton on segment edit page
  • Matched Customers tab on segment edit page with pagination
  • MatchedCustomersDataProvider for matched customers grid
  • CustomerSegmentRelation model and ResourceModel for segment-customer relationships
  • Product::class added to condition type allowlists (SegmentManagement + NewConditionHtml)
  • Cart Price Rule integration now loads segment options from repository (was stub)
  • Functional test suite (Playwright) — API, CLI, Admin UI, Integration tests
  • Unit tests for Product condition and SqlBuilder

Fixed

  • CRITICAL: Segment model extended AbstractModel instead of AbstractExtensibleModel — getExtensionAttributes() crashed all REST API serialization
  • CRITICAL: SegmentSearchResultsInterface used short class name in @return docblock — Magento Web API reflection failed with "Class SegmentInterface does not exist" on getList endpoint
  • CRITICAL: Edit controller stored full Segment model object in DataPersistor (session) — non-serializable dependencies (FormFactory/ObjectManager/Closures) caused "Serialization of 'Closure' is not allowed" fatal error on every admin page load
  • Conditions blocks now load segment from DB via request param instead of DataPersistor
  • Removed DataPersistorInterface dependency from Conditions blocks

Changed

  • Segment model constructor now accepts ExtensionAttributesFactory and AttributeValueFactory (required by AbstractExtensibleModel)
  • Version bumped to 1.1.0

[1.0.1] - 2026-04-01

Added

  • Comprehensive Unit Test Suite - 106 tests with 198 assertions
    • SegmentManagement tests (31 tests) - CRUD, refresh, export, validation
    • Condition tests (75 tests) - Customer, Order, Cart, Combine conditions
    • Security-critical tests for CSV injection prevention
    • Condition type allowlist verification
    • Error handling and edge case coverage
  • Testing documentation:
    • TESTING.md - Testing patterns and best practices

Fixed

  • Security: CSV export now uses fputcsv() to prevent formula injection
  • Security: Condition instantiation uses allowlist to prevent arbitrary class loading
  • Table prefix support in database queries
  • Type mismatches in API methods
  • Deprecated class replacements (Zend_Db_Expr, Registry)

Technical

  • Reduced test code duplication by 30% through refactoring
  • Established testing patterns for future development
  • All production code issues resolved

[1.0.0] - 2026-04-01

Added

  • Initial release of Magendoo CustomerSegment module
  • Customer segmentation with dynamic rules engine
  • Three condition types: Customer Attributes, Order History, Shopping Cart
  • Admin grid for segment management with filtering and mass actions
  • Create, edit, delete, and refresh segments
  • Three refresh modes: Manual, Cron, Real-time
  • REST API for all segment operations
  • CLI command for segment refresh
  • Integration with Cart Price Rules
  • Event system for extensibility
  • Database schema with foreign key constraints
  • Multi-condition support with AND/OR logic
  • Customer count caching
  • Export segment customers (CSV/XML)
  • Full ACL support for permissions
  • Observer-based real-time updates
  • Comprehensive documentation

Features

  • Dynamic Segments: Automatically assign customers based on rules
  • Visual Rule Builder: Admin UI for building complex conditions
  • Batch Processing: Efficient customer matching in batches of 1000
  • Scheduled Updates: Cron-based segment refresh (default: daily at 2 AM)
  • Event-Driven: Real-time updates on customer events
  • API Access: Full REST API coverage
  • Extensible: Plugin and event support for custom conditions

Technical

  • Magento 2.4.x compatibility
  • PHP 8.1+ support
  • Service Contracts pattern
  • Dependency Injection throughout
  • Unit and integration test support
  • Playwright functional tests

Roadmap (not yet implemented)

  • Customer grid segment column / filtering
  • Viewed-categories (product-view) condition
  • GraphQL API support
  • Segment-based email templates and CMS content
  • Import/Export of segment definitions
Versions
Version Stability QA Status Compatibility Released
2.0.0 stable Fail Magento 2.4.7-2.4.9 Details 2026-07-20 14:40:05
1.1.0 stable Not tested Not yet tested Details 2026-04-13 13:29:10

Requires 9

Package Constraint
magento/framework >=103.0.0
magento/module-backend >=102.0.0
magento/module-catalog >=104.0.0
magento/module-customer >=103.0.0
magento/module-quote >=101.2.0
magento/module-rule >=100.4.0
magento/module-sales >=103.0.0
magento/module-ui >=101.2.0
php >=8.1

Requires-dev 2

Package Constraint
phpstan/phpstan ^1.10 || ^2.0
phpunit/phpunit ^10.5

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 Pass

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 Warning 55 55 warnings (ruleset: Magento2), 20 auto-fixable with phpcbf
PHPMD Warning 129 129 rule violations (UnusedPrivateField:129)
Cpd Warning 1 1 duplicated chunk spanning 54 total lines (min-lines=5, min-tokens=70)
Composer validate Info 9 valid; 9 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.

PHPStan results by Magento and PHP version
Magento PHP 8.2 PHP 8.3 PHP 8.4 PHP 8.5
2.4.7 35 35
2.4.8 35 35
2.4.9 35 35

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 1 1
2.4.8 2 2
2.4.9 Pass 23

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
MIT
Authors
  • Magendoo

More from magendoo

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.