Events with Magento checkout

The Magento e-commerce application makes use of events to allow third party extensions to hook into the Magento core-functionality. For instance, when a customer uses the one-page-checkout, multiple events are generated that allow other extensions to do their stuff. However, these events are not documented. While developing our own MageBridge extension, we needed to research on this ourselves - so here's the result.

About the Magento checkout

Magento uses two different types of checkout: The one-page-checkout and the multiple-page-checkout. By default, the one-page-checkout is enabled which means that all the required steps to order some products are compiled into one single page. This single page makes heavy use of JavaScript to send AJAX-calls back to Magento. Each of these AJAX-calls generates one or more events.

Events are there for other extensions to alter the regular behavior of the Magento core. They form the cleanest way of making changes. However, there are other ways to make changes as well: One of the most powerful features of Magento is the option to override classes anywhere in the system. This allows you to override anything, while the event-system is a bit more limited - this system only allows you to modify things at the time when an event is called.

Note that the integration of payment providers uses yet another mechanism: Instead of events or class-overriding it uses its own specific way of plugging in the data of various payment methods. But that's a bit off topic.

Our own reason to look into this

We (Yireo) have developed a bridge between Joomla! and Magento - this product is called MageBridge. While Joomla! acts primarily like a browser to fetch ready-to-go content from Magento, the bridge also makes use of events to send data between the two applications Joomla! and Magento. Actually, the event itself (with all it's parameters) is sent forth and back - that's why we call this event forwarding.

While ordering a product through Magento, we thought it would be nice to re-use the ordering information from Magento in the Joomla! CMS. More specifically, when a customer purchased a membership-product in the Magento shop, we wanted to add the corresponding Joomla! user to a specific membership-group. While the default setup of MageBridge allowed us to accomplish this, we ran into a little problem.

When an existing customer purchased the membership-product, the user was already created in Joomla! and could be added without a problem to the right membership-group. However, when the customer did not exist yet, at the time when the event was forwarded to Joomla!, there was no corresponding user-record yet. This specific problem was due to the ordering in which events occur. We needed to find out which event fitted best.

Events during the checkout

Debugging events in MageBridge was pretty easy, because most important events are already configured into the MageBridge-module in extension. If you want to debug things without using MageBridge, you'll need to setup your own module. This module should be configured to listen to all generated events and dump this information somewhere for you to debug.

Events are generated through the method Mage::dispatchEvent(). However, if you start searching the Magento codebase for this method, you will find only a limited number of events. The reason for this is that many Magento classes extend the class Mage_Core_Model_Abstract, which automatically adds events like "*_save_after" and "*_delete_after" to the object.

When we started debugging the checkout, we came quickly to the conclusion that two events were generated so often that they basically useless for our purpose:

  • sales_quote_save_after
  • checkout_allow_guest
The event sales_quote_save_after occurs after every step during the checkout. It is an automatically generated event that makes sure the checkout-information is saved, even when the customer suddenly leaves the page. The checkout_allow_guest also occurs after every step, but only when no customer is logged in.

Events when checking out as an existing customer

We first take a look at the checkout procedure when an existing customer is logged in. It's the easiest part because as long as the customer-data do not change, the checkout only has to deal with the checkout itself. During the checkout itself, the event sales_quote_save_after is fired multiple times, but the checkout_allow_guest event is not.

When the address-details are changed the event checkout_controller_onepage_save_shipping_method is fired. Finally if all the steps are finished, the order is saved one last time using sales_quote_save_after followed by a different event sales_order_place_after. That last event is only used once, so could be usefull if you want to reuse the quote-information.

After this two more event occur: checkout_type_onepage_save_order_after and checkout_onepage_controller_success_action, with the last one being generated on the intermediate post-checkout page. The total sums up to be (in the right order):

  • checkout_controller_onepage_save_shipping_method
  • sales_order_place_after
  • checkout_type_onepage_save_order_after
  • checkout_onepage_controller_success_action

Anonymous checkout

Basically the event-procedure described above doesn't change much when there is no one logged in yet. An additional event checkout_allow_guest is fired multiple times, to allow extensions to determine whether the current checkout by an unknown user is legal or not.

When doing an anonymous checkout, the event checkout_controller_onepage_save_shipping_method is still fired, it is just not connected to any customer.

  • checkout_controller_onepage_save_shipping_method
  • sales_order_place_after
  • checkout_type_onepage_save_order_after
  • checkout_onepage_controller_success_action
As you can see, the procedure didn't change at all compared to the procedure for existing customers.

Checkout as new customer

But when checking out as a new customer, a registration must also occur. We expected that this registration would occur by creating a new customer-record and saving it into the database - this would generate the event customer_save_after. However, it didn't. Instead the customers data are saved, by gathering all the information and just performing a login of the customer (the event customer_login).

  • checkout_controller_onepage_save_shipping_method
  • sales_order_place_after
  • checkout_type_onepage_save_order_after
  • customer_login
  • checkout_onepage_controller_success_action

Finally we had a match for our MageBridge information. We needed to dispatch an event to Joomla! so we could the stuff over there. But we needed to do this after a Joomla! user was created. With MageBridge an user-record is generated when the event customer_login is forwarded (and translated to the Joomla! event mageCustomerLogin) and if no customer exists yet. So our answer was that we needed to use the event checkout_onepage_controller_success_action to hook in our membership-mechanism.

Final notes

Note that this tutorial didn't cover the procedure with the one-page-checkout disabled. Also we didn't test the procedure extensively when a customer-address was changed or when the whole checkout was interrupted either by the customer or the server. Basically we got we wanted, so we stopped. Hopefully you get some tips from this tutorial if you need to base your own product on Magento events.