commercekings / module-notification
Notification subscriptions (opt-out on their own, consent-based with commercekings/module-consent-notification) and shared email delivery for CommerceKings modules in Magento 2: one subscribe endpoint, guest contacts, one message queue consumer, optional recipient cooldown, store-emulated sending an
Package info
github.com/commercekings/module-notification
Type:magento2-module
pkg:composer/commercekings/module-notification
Requires
- php: ~8.1.0||~8.2.0||~8.3.0||~8.4.0||~8.5.0
- commercekings/module-core: ^0.1
- magento/framework: ^103.0.4
- magento/module-backend: ^102.0
- magento/module-config: ^101.2
- magento/module-customer: ^103.0
- magento/module-message-queue: ^100.4
- magento/module-store: ^101.1
- magento/module-webapi: ^100.4
Requires (Dev)
None
Suggests
- commercekings/module-consent-notification: Require a consent (commercekings/module-consent) for every subscription
- commercekings/module-rate-limit: Rate limits for the guest subscribe endpoint in the admin (Magento 2.4.7+); a web server or CDN rule works too
- magento/module-mysql-mq: Use Magento's native database queue transport when RabbitMQ is unavailable.
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-20 21:56:38 UTC
README
Works with Magento 2.4.4+ · Luma and Hyvä · PHP 8.1–8.5 · RabbitMQ or MySQL queue
Thousands of notifications a minute or a handful a day – your store never slows down.
- Fast storefront. Every notification is sent in the background by a queue consumer, never during a page view. Optional shopper subscriptions are one quick write.
- Marketing and service messages. Reminders shoppers opt into, or order and staff messages that need no subscription.
- Email, SMS, WhatsApp, Viber. Email built in; a provider module adds a messaging service. Phone numbers, consent for a number (a checkbox, stored as evidence), STOP replies and quiet hours are part of Notification.
- Inbox-ready at volume. Optional RFC 8058 one-click unsubscribe, as Gmail and Yahoo require from bulk senders.
- Do not contact. One click in a marketing email (or a STOP reply) stops all marketing to that address on that channel (a STOP to the SMS number doesn't stop email), whoever signs them up again; order messages still arrive.
- Quiet hours. Marketing is held at night (on by default for texts, 20:00–08:00) and sent after – in the store's time zone, or the recipient's.
- Scales with you. Add consumers when traffic grows; RabbitMQ or Magento's MySQL queue.
- Private by default. Cooldown, stops and consents keep keyed hashes, never addresses; unused contacts are removed.
A feature (e.g. abandoned cart) says what and when; Notification handles who and how.
Provider modules: Twilio, Infobip · Features: Abandoned Cart (+ SMS)
The model
- A notification type is one kind of message, registered by a feature. It decides when to send and builds the content.
- A subscription is a shopper's sign-up for a type, e.g. reminders for one cart. Marketing types need one; service messages don't. Its address is a contact (one per website, channel and address) or, on email types, a customer's account email.
- A permission decides who may subscribe: everyone (opt-out), only with consent (opt-in, with the privacy bundle), or – per type – an address consent: a checkbox for one number. The subscriber provides the unsubscribe link.
- The queue carries
<type>|<reference>. One consumer sends every type, so nothing is sent during a page view. - The delivery state keeps each feature's send history per type and reference, e.g. per cart and reminder type (sent, queued, retries), so a new sign-up does not send twice.
- The sender checks a delivery against Do not contact, quiet hours and the cooldown, builds its content in the store's language, then hands it to a provider.
- A channel is where a delivery goes: email, SMS, WhatsApp, Viber, or a code a provider module brings. A normalizer gives each channel one recipient form; SMS, WhatsApp and Viber numbers are E.164.
- A provider delivers on one channel, chosen in the admin when there are several. Magento email is built in. Install one provider module per channel: recipient time zones and opt-in confirmations are per module.
Installation
Usually a feature brings it. On its own:
composer require commercekings/module-notification:^0.1 bin/magento setup:upgrade
Alone it runs opt-out: a subscription stays until it is removed, and features show their notice. Add
commercekings/privacy-bundle for opt-in: a subscription then needs a consent for the feature's purpose,
withdrawing it removes the subscription, and notices are off by default. Text messages are always opt-in: a type with an
address consent needs the number's checkbox in either setup.
Settings
Stores > Configuration > CommerceKings > Notifications:
| Group | Fields (default) |
|---|---|
| Delivery | Provider per channel (Magento email); Cooldown in days (7, global, 0 = off); One-click unsubscribe (No) |
| Do not contact | "Stop these emails" link (Yes; always on in opt-out mode); Lifts after days without attempts (90) |
| Quiet hours | Enabled (Yes); From – To (20:00 – 08:00, may cross midnight); Channels (all but email) |
| Consent for an address | Checkbox text for text messages, WhatsApp and Viber, per store view; Keep withdrawn consents (1825 days) |
Before going live
- Run the consumer
commerceKingsNotificationSendwith--max-messages=1000and restart it after each deployment. - Recommended: rate-limit the anonymous routes
POST /rest/<store>/V1/ck-notification/subscriptionsand…/address-consentsper IP (e.g. 10 a minute) in your web server, proxy or CDN, and optionally with commercekings/module-rate-limit. Without one, a script can make the shop message any address – a paid text to any number – up to the feature's hourly cap.
Details: operations.
Extending
Types work with or without subscriptions: with them for messages shoppers sign up for, without for service
messages and staff alerts. The public API (@api):
| For | Use |
|---|---|
| A notification type | Api\NotificationTypeInterface (Model\TypePool "types"), Api\QueueInterface, Api\SenderInterface with Data\Delivery |
| Its send history | Api\DeliveryStateInterface |
| Sign-ups | Api\SubscriptionTypeInterface (Model\SubscriptionTypePool "types"), Api\SubscriptionManagementInterface and its commercekings_notification_subscription_saved event, Api\SubscriptionRepositoryInterface, Api\SubscriptionGuardInterface, Api\SubscriptionRemovalInterface |
| Who may subscribe | Api\SubscriptionPermissionInterface, Api\SubscriberInterface; per type Model\TypePermission, Model\TypeSubscriber, Model\AddressConsent (virtual types) |
| A checkbox consent | Api\AddressConsentManagementInterface, address-consent.phtml with ViewModel\AddressConsent |
| A channel or service | Api\ProviderInterface (Model\ProviderPool "providers"), Api\RecipientNormalizerInterface (Model\RecipientNormalizerPool "normalizers"), Model\Config\Source\Provider (virtual type "channel"), Model\KeyedHash |
| Replies and timing | Api\StopListInterface, Api\QuietHoursInterface, Api\QuietHoursZoneInterface (Model\QuietHours "zones"), Api\CooldownInterface |
| Housekeeping and UI | Api\ContactReferenceInterface (Model\ContactReferencePool "references"), Api\OptOutNoticeInterface |
How to use them, including messaging for provider modules: for module authors.
Limitations
- A failed send is not retried by Notification; the feature decides (abandoned cart queues the cart again).
- Quiet hours have one window per store view for all selected channels.
- Stops, stop links, consents and the cooldown are keyed with Magento's encryption key. After
encryption:key:changenothing needs to be run while the old key stays inenv.php; the cooldown restarts (details).
Tested (as of 0.1.0)
- Automated tests: 252 unit, 31 integration and 16 JavaScript tests (unit and JavaScript tests run on every push).
- Line coverage: 93.8% with unit and integration tests combined.
- End to end on Magento 2.4.9: email reminders through Magento's mail (caught by a test mail server), with RabbitMQ and with the MySQL queue; SMS and WhatsApp against a simulated Twilio API – opt-in confirmation, STOP and START, quiet hours, provider errors and timeouts.
- Load: 100,000 abandoned carts through the sender, about 3 messages a second per worker, growing linearly, none sent twice; 300 of 300 texts delivered to a simulated provider.
- Install: a fresh install of every CommerceKings package from GitHub on an empty Magento database, verified.
- Not tested: a STOP reply from a real phone (STOP is tested with the providers' webhook formats).
More
How it works · For module authors · Operations · Stop list · Compatibility · Changes
Disclaimer
These modules help you ask for, record and respect your shoppers' choices – they don't make your store compliant on their own. You are responsible for your store's privacy: what you collect, the wording you show, your privacy policy and whether your setup meets the laws that apply to you (e.g. GDPR, ePrivacy, email and SMS marketing rules). Get legal advice if you are unsure.
Need it installed, set up or customized? Get in touch →