Create Custom Event and Observer Programmatically Using events.xml

Create Custom Event and Observer Programmatically Using events.xml
Magento 2 offers a powerful event-driven architecture that lets developers hook into core functionality without changing the core code. In this guide, you’ll learn how to:
- Create and dispatch a custom event
- Declare it in events.xml
- Handle it using an Observer class
Updated for Magento 2.4.7 (2025), this tutorial is production-ready and includes helpful tips and best practices.
Table Of Content
Deep Dive: Magento 2 Events and the Observer Pattern
Magento 2 events are a critical part of the Event-Observer Design Pattern, which allows developers to execute custom logic without changing the core code. It makes the system highly extensible, modular, and maintainable.
Events are dispatched by Magento at strategic execution points
(like after a product is saved, an order is placed, etc.), and developers can attach custom functionality using observers.
What Is a Magento Event?
An event is simply a trigger or signal that Magento dispatches during the execution of specific actions. These can be system events (like sales_order_place_after
) or custom events created by developers. Observers are classes that respond to these events and execute your code.
Events are defined and dispatched through Magento's event manager.
When Are Events Used?
Events are typically used in scenarios such as:
- Logging actions (e.g., product save, customer login)
- Custom notifications (e.g., on order success)
- API integrations (triggering external service calls)
- Auto-assigning values or flags to entities
- Extending third-party modules without overriding
Syntax to Dispatch a Custom Event
To trigger your own event, use Magento's Event Manager. Here's how:
$this->_eventManager->dispatch(
'your_custom_event_name',
[ 'key1' => $value1, 'key2' => $value2 ]
);
If you're using dependency injection, inject \Magento\Framework\Event\ManagerInterface
into your constructor.
Dispatch Method Breakdown
Method Signature:
public function dispatch($eventName, array $data = []);
Parameters Explained:
Parameter | Description |
---|---|
$eventName |
A string identifier for your custom event (e.g., custom_event_trigger ) |
$data |
An associative array of key-value pairs passed to the observer |
Key Differences: Magento Events vs Plugin Interception
Feature | Magento Events | Plugin Interception |
---|---|---|
Flexibility | Can attach logic without affecting method flow | Can change input/output of specific methods |
Multiple Listeners | Yes | One plugin chain per method |
Use Cases | Side effects, async hooks, third-party triggers | Method overrides and pre/post logic |
Performance Impact | Lightweight | May impact performance if overused |
Best Practices for Dispatching Events
- Use namespaced event names to avoid conflicts (vendor_module_custom_event).
- Always dispatch with contextual and minimal data.
- Ensure events are only dispatched in relevant execution paths.
- Document custom events well so they’re reusable across the codebase.
Use Cases of Custom Events
Scenario | Example |
---|---|
Trigger webhook | Notify third-party service when a customer signs up |
Auto assign customer group | On registration, assign to "Wholesale" if email matches domain |
Send transactional emails | Send a custom email when wishlist is shared |
Track user activity | Log time and IP of last login |
Queue a background process | Dispatch a job to process export or data sync |
Debugging and Monitoring Events
- Enable developer mode to log dispatched events.
- Use Xdebug to step into
dispatch()
and track registered observers. - You can also temporarily log inside your observer to confirm execution.
Defining events.xml in Magento 2.4.x
Magento 2 uses the Observer Design Pattern to allow developers to hook into system processes without directly modifying core code. The events.xml file is the configuration file where custom event observers are defined.
You must declare this file in the correct area-specific directory depending on where your observer should respond.
Where to Place events.xml Based on Execution Area
Area | Folder Path | Description |
---|---|---|
Global | etc/ | Executes for both frontend and backend requests. Use this for events that are not area-specific (e.g., model save, order placement). |
Frontend | etc/frontend/ | Used for customer-side events like login, add to cart, checkout, etc. |
Adminhtml | etc/adminhtml/ | Applies only in the admin panel. Useful for events triggered from admin grids, forms, etc. |
Web API (REST) | etc/webapi_rest/ | Events related specifically to REST API requests. |
Web API (SOAP) | etc/webapi_soap/ | Events triggered via SOAP API requests. |
Recommended Use Cases per Area
Area | Example Use Case | Example Event |
---|---|---|
Global | Log after order is placed | sales_order_place_after |
Frontend | Track product views | catalog_controller_product_view |
Adminhtml | Send alert on admin login | admin_user_authenticate_after |
Web API (REST) | Trigger sync after customer update | customer_save_after_data_object |
Web API (SOAP) | Validate product import via SOAP | catalog_product_save_after |
Observer Class Placement and Structure
After defining your event in events.xml
, you must create an Observer class that implements \Magento\Framework\Event\ObserverInterface
.
Location Example:
app/code/Vendor/Module/Observer/CustomObserver.php
Key Elements:
- Namespace must match module
- Class must implement ObserverInterface
- The
execute()
method must receive an instance of\Magento\Framework\Event\Observer
Sample events.xml Entry
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
<event name="customer_login">
<observer name="custom_login_logger" instance="Vendor\Module\Observer\LoginObserver" />
</event>
</config>
Best Practices for Managing events.xml
- Keep event names unique across modules to avoid conflicts.
- Do not attach heavy logic directly in observers—offload to services or queues when possible.
- Use area-specific folders to limit unnecessary event dispatching.
- Use
di.xml
to inject dependencies inside your observer class constructor. - Avoid creating multiple observers for the same task—consolidate logic where applicable.
Step-by-Step Guide to Create and Dispatch a Custom Event in Magento 2
In this tutorial, we will walk you through creating a custom event in Magento 2. The module we’ll build is called Emmo_CustomEvent.
Step 1: Dispatching an Event in a Controller
To start, you need to dispatch your custom event from a controller action. Here's how to do it
File: app/code/Emmo/CustomEvent/Controller/Index/Index.php
<?php
namespace Emmo\CustomEvent\Controller\Index;
use Magento\Framework\DataObject;
use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
class Index extends Action
{
public function __construct(Context $context)
{
parent::__construct($context);
}
public function execute()
{
// Custom data to pass to the observer
$customData = new DataObject([
'record_id' => 10001,
'name' => 'record_name'
]);
// Dispatching the custom event
$this->_eventManager->dispatch('jesadiya_custom_event_observer', [
'record' => $customData
]);
}
}
Action Explanation:
- In the
execute()
method, we create aDataObject
with custom data (record_id
and name). - The _eventManager->dispatch() method is used to trigger the custom event jesadiya_custom_event_observer.
Step 2: Define the Event in events.xml
Next, you need to define the custom event and associate it with an observer. This is done in the events.xml
file.
File:app/code/Emmo/CustomEvent/etc/events.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
<event name="jesadiya_custom_event_observer">
<observer name="handle_custom_event"
instance="Jesadiya\CustomEvent\Observer\GetRecord"/>
</event>
</config>
Event Explanation:
- The event name
emmo_custom_event_observer
is linked to the observer classEmmo\CustomEvent\Observer\GetRecord
.
Step 3: Create the Observer Class
The observer listens for the event and processes the data passed with the event. Below is an example of an observer class.
File: app/code/Emmo/CustomEvent/Observer/GetRecord.php
namespace Emmo\CustomEvent\Observer;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
class GetRecord implements ObserverInterface
{
public function execute(Observer $observer)
{
// Get the custom data passed with the event
$record = $observer->getEvent()->getRecord();
$recordId = $record->getRecordId();
$name = $record->getName();
// Perform actions with the data
// Example: logging the data or using it for further operations
// $this->logger->info("Record ID: $recordId, Name: $name");
return $this;
}
}
Observer Explanation:
- The
execute()
method gets the data (record_id
andname
) that was passed during the event dispatch. - You can process the data inside this method, such as logging, sending notifications, or updating records.
Bonus: Dispatching a Custom Event Using Plugin
If you prefer to dispatch a custom event within a plugin instead of a controller, here's how to do it:
use Magento\Framework\Event\ManagerInterface as EventManager;
private $_eventManager;
public function __construct(EventManager $eventManager)
{
$this->_eventManager = $eventManager;
}
public function aroundExecute($subject, callable $proceed)
{
// Custom data to dispatch with the event
$customData = new \Magento\Framework\DataObject([
'record_id' => 9999,
'name' => 'via_plugin'
]);
// Dispatching the event
$this->_eventManager->dispatch('jesadiya_custom_event_observer', [
'record' => $customData
]);
// Proceed with the original method
return $proceed();
}
Plugin Explanation:
- In the
aroundExecute()
method
, we create custom data (record_id
andname
). - We dispatch the event
emmo_custom_event_observer
with this custom data before proceeding with the original method logic.
Key Takeaways
- Custom events in Magento allow you to decouple different pieces of logic in your application.
- Observers listen to these events and execute actions when an event is triggered.
- Plugins can also be used to dispatch events, providing more flexibility in how and where you trigger custom logic.
Practical Use Cases of Custom Events in Magento 2.4.7
Magento’s event-driven architecture allows developers to execute logic without altering core functionality. Custom events are especially powerful in complex business scenarios, helping to keep your code modular, flexible, and upgrade-safe.
Why Use Custom Events?
Custom events are best when you want to:
- Extend core behavior without overriding classes.
- Decouple features into reusable modules.
- Trigger external services (e.g., CRMs, APIs).
- Collect analytics or track specific behavior.
- Customize notification flows or automate user segmentation.
Common Business Scenarios for Custom Events
Here’s a detailed table showing practical use cases, the event naming convention, and what the observer typically handles.
Use Case | Custom Event Name | Observer Responsibility |
---|---|---|
Logging custom activity | custom_activity_log |
Collect user or system actions and write them to logs or custom tables for auditing |
Triggering email workflows | custom_email_trigger |
Send transactional or marketing emails when certain triggers occur |
Third-party API synchronization | custom_thirdparty_sync |
Push or pull data from third-party systems like CRMs, ERPs, or external apps |
Assigning customer segments | auto_customer_segment_event |
Automatically assign users to specific customer groups based on custom rules |
Inventory alert or restock logic | custom_stock_notification |
Notify users or trigger workflows when inventory thresholds are hit |
Custom cache clear on condition | conditional_cache_clear |
Flush or refresh cache sections programmatically based on user actions |
Generating admin alerts | custom_admin_alert |
Send alerts to admin users when thresholds or business rules are violated |
Activity tracking for analytics | custom_user_analytics |
Record login, search, wishlist, or order history for analytics tools |
Loyalty program integration | loyalty_points_trigger |
Add loyalty points or rewards based on order or action triggers |
Background job queuing | background_task_dispatch |
Dispatch a task to be handled later using Magento’s message queue system |
Scheduled data export | custom_export_trigger |
Launch an export of customer, order, or product data when specific events are triggered |
Custom pricing adjustments | dynamic_price_event |
Adjust prices dynamically based on rules, customer group, or time-based logic |
Custom validation during checkout | checkout_validation_event |
Add custom logic to validate user data before order placement |
Event Naming Best Practices
When defining custom events, follow clear and meaningful naming conventions:
- Use lowercase with underscores (
snake_case
) - Prefix your event name with your module or company name to avoid collisions (e.g.,
mycompany_order_validate
) - Keep it action-oriented and descriptive (e.g.,
customer_profile_updated
,custom_export_trigger
)
When Should You Use Events Instead of Plugins?
Criteria | Use Custom Event | Use Plugin |
---|---|---|
Decoupled logic | Yes | Limited |
Multiple logic handlers | Supports multiple observers | Only one plugin chain per method |
Modifying input/output | Not ideal | Ideal |
Intercepting specific methods | Only reacts to global events | Works best on class methods |
System-wide action triggers | Excellent for global or async hooks | Not recommended for global events |
Custom events in Magento 2 are essential for building scalable, modular, and flexible code. Whether you’re logging activities, triggering APIs, or dispatching emails, events let you hook into Magento’s processes without risking conflicts or upgrade issues.
If you're working with Magento 2.4.7 or newer, always register your events in the appropriate events.xml file based on the desired area (etc, etc/frontend, etc/adminhtml, etc.), and consider asynchronous handling via message queues for large-scale integrations.
Tip
To enhance your eCommerce store’s performance with Magento, focus on optimizing site speed by utilizing Emmo themes and extensions. These tools are designed for efficiency, ensuring your website loads quickly and provides a smooth user experience. Start leveraging Emmo's powerful solutions today to boost customer satisfaction and drive sales!
Conclusion
Custom events and observers are essential tools in a Magento developer’s toolbox—allowing you to build robust, modular, and scalable solutions without altering the core code. With Magento 2.4.7, these features remain critical to extending native functionality, integrating third-party systems, and automating business logic at key interaction points.
By understanding how to properly dispatch events, configure events.xml
, and implement observer classes, you unlock the full potential of Magento's event-driven system. Whether you're logging user activity, syncing with external APIs, or triggering custom workflows—this pattern empowers your store to respond intelligently to user and system actions.
Always follow Magento’s best practices:
- Keep logic out of observers when possible
- Use services for complex processes
- Scope your events correctly (frontend, adminhtml, REST, etc.)
In a rapidly evolving eCommerce world, the ability to listen and respond is everything. Mastering custom events is how you keep Magento responsive, powerful, and future-proof.
FAQs
What is a custom event in Magento 2?
A custom event in Magento 2 is a developer-defined trigger used to execute additional logic by dispatching data through the event/observer system without changing core files.
How do I dispatch a custom event in Magento 2?
You can dispatch a custom event using the `$this->_eventManager->dispatch('event_name', ['data' => $data])` method in your controller, model, or plugin.
Where should I define events.xml for global event scope?
Define `events.xml` inside the `etc/` directory of your module for global (both frontend and adminhtml) event handling.
What is the purpose of the Observer class in Magento 2?
The Observer class is responsible for handling the dispatched event logic using the `execute()` method where data can be processed.
Which interface must an Observer implement?
An Observer class must implement the `\Magento\Framework\Event\ObserverInterface` to handle event logic.
Can I pass multiple data parameters in dispatch?
Yes, you can pass multiple key-value pairs in the second argument (array) of the `dispatch()` method.
How can I access data in the Observer class?
You can access the dispatched data using `$observer->getEvent()->getData('key')` or by getting the specific object directly if passed with a key.
What are the different areas for events.xml placement?
You can place `events.xml` in `etc/`, `etc/frontend/`, `etc/adminhtml/`, `etc/webapi_rest/`, and `etc/webapi_soap/` depending on the area where your event should trigger.
Is it possible to use custom events in Plugins?
Yes, you can dispatch custom events inside a plugin method using the `Magento\Framework\Event\ManagerInterface` instance.
Can I use custom events for REST or SOAP APIs?
Yes, define `events.xml` in `etc/webapi_rest/` or `etc/webapi_soap/` to handle custom events in respective API calls.
What command should I run after creating an observer?
Run `bin/magento cache:clean` and `bin/magento setup:upgrade` to register and activate new observers or event configurations.
Can I listen to native Magento events using the same approach?
Yes, simply subscribe to Magento's built-in events using your module’s `events.xml` and provide an appropriate observer class.
What’s the difference between Observer and Plugin?
Observers respond to dispatched events. Plugins modify the behavior of existing public methods using before/after/around logic.
Can I dispatch an event without sending data?
Yes, the data array in `dispatch()` is optional. If you don’t need to pass data, you can just provide the event name.
What are best practices for creating custom observers?
Keep observer logic clean and lightweight, offload heavy operations to services, avoid core overrides, and ensure your event is uniquely named to avoid conflicts.