zerofront / module-zero-personalize
Zero for Magento Open Source: product recommendations from Amazon Personalize in batch mode: similar products on the product page and picks for every signed-in customer, learned weekly from the store's orders, carts and wishlists, for a few dollars a month on your own AWS account.
Package info
github.com/zerofrontdev/module-zero-personalize
Type:magento2-module
pkg:composer/zerofront/module-zero-personalize
Requires
- php: ~8.2.0||~8.3.0||~8.4.0
- magento/framework: 103.0.*
- magento/module-backend: *
- magento/module-catalog: *
- magento/module-config: *
- magento/module-cron: *
- magento/module-customer: *
- magento/module-eav: *
- magento/module-quote: *
- magento/module-sales: *
- magento/module-store: *
- magento/module-wishlist: *
- zerofront/module-zero-core: ^1.3.8
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
- fixstacks/module-zero-personalize: 1.3.8
README
Amazon Personalize learns from the store's orders, carts and wishlists and recommends:
- similar products on the product page ("You may also like"),
- picks for a signed-in customer on the home page, the cart and My Account ("Picked for you").
Configured in Stores > Configuration > Zero > Recommendations. Replaces the old Fixstacks_AwsPack (its settings are removed on install).
Install
Requires Magento Open Source 2.4.7–2.4.9 and PHP 8.2–8.4 with the GD extension built with WebP (php -r 'var_dump(function_exists("imagewebp"));' says true; Magento's own PHP requirements cover the rest). Without WebP in GD, Zero skips its WebP image copies and serves the originals.
composer require zerofront/module-zero-personalize bin/magento setup:upgrade bin/magento setup:di:compile # production mode bin/magento setup:static-content:deploy # production mode bin/magento cache:flush
Composer installs zerofront/module-zero-core with it.
Part of zerofront/zero, which installs the Zero theme and every Zero module at once.
Batch mode: what it costs
Personalize can answer in real time, from a campaign or recommender that runs all the time and is billed by the hour whether anyone visits or not (about $144 a month per model at the minimum, $270 for a ready-made e-commerce recommender). This module doesn't use that. Once a week, at night, it:
- exports the store's interactions and products to S3,
- has Personalize train a new version of two solutions,
aws-similar-itemsandaws-user-personalization-v2(automatic training is switched off, so Personalize never trains on its own), - runs one batch inference job per solution: recommendations for every product and for every customer with a history, written to S3,
- loads the results into
zero_personalize_similarandzero_personalize_userand cleans the pages that show them. A product's similar ones from its own department (the first level of its most specific category: Men, Women, Gear) come first, in the model's order: the model learns from every order, mixed carts and test orders included, and a men's hoodie shouldn't open on women's tees.
AWS bills three things: the data uploaded ($0.05 per GB, cents), the
training (the recipes aws-user-personalization-v2 bills $0.002 per 1,000
interactions, aws-similar-items $0.24 per training hour) and the batch
recommendations ($0.067 per 1,000 requested). The batch part grows with the
store: a run asks for 12 recommendations for every product and for every
customer with a history, so it costs about $0.0008 per row, a row being
one product or one customer. Nothing runs between runs.
| Store | Rows (products + customers) | One run (batch + training) | A month, weekly |
|---|---|---|---|
| Small: 500 products, 1,000 customers | 1,500 | about $2 | about $8 |
| Medium: 5,000 products, 20,000 customers | 25,000 | about $20-25 | about $90-110 |
| Large: 100,000 products, 300,000 customers | 400,000 | about $320+ | about $1,400+ |
Three settings in Stores > Configuration > Zero > Recommendations > Training lower the batch part (each is a billed row or recommendation):
- Picks for Customers Active in the Last (days): a customer gets picks only after an order or a cart in this period (0: the whole Learn From period). 90 days instead of 365 usually drops a large share of the rows.
- Most Customers per Run: a cap (0: none); the most recently active come first.
- Recommendations per Product and Customer (1-12, default 12): what the batch asks for. The storefront shows 8 by default; keep a few spare, since similar products are filtered by department and stock.
Customers left out see no "Picked for you" until they are active again; product pages keep their similar products.
The small row matches a real run on the demo (1,257 rows, 2.3 training hours: about $1.50). The medium and large rows are the batch price times the rows plus a guess for training, not measured runs. Past roughly 40,000 rows a weekly run costs more than the always-on campaign ($144 a month): then train less often (the schedule is in the configuration) or keep to the small shop's size. Prices are AWS's list prices for US regions on 2026-11-07; check https://aws.amazon.com/personalize/pricing/ before you plan. The storefront reads only the store's own tables: a product page never waits for AWS and stays in the page cache (Varnish, CloudFront). The recommendations are a week old at most.
What it learns from
No tracking script: the store already knows.
| Interaction | From | User |
|---|---|---|
Purchase |
order lines (not cancelled orders) | c<customer id>, or g<keyed hash of the email> for a guest (HMAC with the install's crypt key) |
AddToCart |
quote lines, abandoned carts included | c<customer id>, or q<quote id> for a guest |
Wishlist |
wishlist items | c<customer id> |
Of the last 365 days (Learn From the Last), for enabled products visible in the catalog or search. Products go with their price and top-level category names. Personalize trains from 1000 interactions and 25 shoppers with two or more; until then a run says so and costs nothing.
Demo shoppers (--demo-data, or Train Now With Demo Shoppers) add 150
made-up shoppers who each keep to one top category, the same ones every
run, for a demo store whose orders are test orders. They are d users:
they shape the similar products and never get picks of their own. A store
that trained with them keeps them in its weekly runs; train once without
them to stop.
Setting up AWS
One S3 bucket and one IAM role, made once (by hand or with your own Terraform), then:
- S3 Bucket and IAM Role for Personalize in the configuration (or
pinned in
app/etc/config.php); - the store's own AWS identity (the EC2 instance role, or Access Key ID and Secret Access Key for a store outside AWS, kept out of config.php) needs:
[
{"Effect": "Allow", "Action": "personalize:*", "Resource": "arn:aws:personalize:*:<account>:*"},
{"Effect": "Allow", "Action": ["personalize:DescribeRecipe", "personalize:ListRecipes"], "Resource": "*"},
{"Effect": "Allow", "Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject", "s3:ListBucket"],
"Resource": ["arn:aws:s3:::<bucket>", "arn:aws:s3:::<bucket>/*"]},
{"Effect": "Allow", "Action": "iam:PassRole", "Resource": "<role arn>",
"Condition": {"StringEquals": {"iam:PassedToService": "personalize.amazonaws.com"}}}
]
The role is trusted by personalize.amazonaws.com and may read and write
the bucket; the bucket policy allows personalize.amazonaws.com the same
(Personalize checks both). Block public access on the bucket and turn on
encryption; the files are rebuilt on every run, so a lifecycle rule that
expires old exports is safe.
Every resource is named after the prefix (default zero- and the
store's host name), so one account and one bucket serve several stores and
a development copy.
Running it
- Train Now on the configuration page (a POST with the form key; a
plain GET of its URL answers 404), or
bin/magento zero:personalize:train [--demo-data] [--wait]: exports and starts;--waitfollows the run to the end (one to three hours). - One step at a time: the cron, the CLI and Train Now share a lock
(
zero_personalize_pipeline). The cron skips while another step runs; Train Now and the CLI say "A training step is running right now". - The cron
zero_personalize_advance(every five minutes) takes a run in progress further;zero_personalize_schedulestarts the weekly run on its day (Train Every; Never: by hand only). bin/magento zero:personalize:train --reload: the last run's results read again from S3 (kept 30 days), no training.bin/magento zero:personalize:status: the step, the last run (how much data, how many products and customers got recommendations, training hours), the resources.bin/magento zero:personalize:teardown --yes: this store's Personalize resources and S3 files deleted, the recommendations emptied.
A failed step stops the run with AWS's own reason on the configuration page
and in status. Once the cause is fixed (a permission, a quota),
zero:personalize:train --resume takes the run up again from that step;
a new run starts over.
Storefront
- Product page: in
content.aside, before the up-sells, the theme's up-sell look. Shown products' cache tags andzero_personalizeon the block: a run cleans the pages, a product's change cleans its row. - Cart and My Account: the customer's picks, rendered with the page (those pages aren't cached).
- Home page: an empty slot that loads
zeropersonalize/foryou(HTMX) after the page; the home page stays cached for everyone.
Products that aren't for sale in the store view (disabled, out of stock, not visible) are left out; with nothing to show, nothing is rendered.
Where it shows: Enabled (Recommendations) can be set per website and store view: off hides both blocks there, on shows them even where the Default is off. Each block also has its own switch (Storefront > Similar Products, Picks). The weekly training and the exports follow the Default value of Enabled only, so switching a store view off doesn't stop them.
Install
composer require zerofront/module-zero-personalize
bin/magento setup:upgrade
Magento Open Source 2.4.7–2.4.9, PHP 8.2–8.4, aws/aws-sdk-php 3. Unit
tests: Test/Unit/Model/ (the export, the batch output, a whole run against
the SDK's mock handler, Enabled per scope).
What changed in each release: CHANGELOG.md.
License
OSL-3.0 or AFL-3.0, your choice: see NOTICE.md.
Zero is made by Fixstacks. Documentation: https://zerofront.dev/docs. Demo store: https://demo.zerofront.dev.