Magento, Events and who determines what's possible
We were recently working with one of our clients who are launching a brand new US ecommerce site to complement their UK based one. They had a number of requirements based around customer usability, which at first glance looked fairly simple to achieve, if that were the case though I wouldn't be writing this.
When using a CMS like Magento we try wherever possible to use standard functionality or well used and reviewed modules/plugins, however in some cases this just isn't possible.
One of the main requirements for this project was automatically directing users to the relevant site based on their location but still allow the customer to go to the other site should they want to.
This seemed like a fairly simple proposition with a number of plugins available to achieve this, although it was further complicated by the fact we were using a separate website with Magento rather than just a new store view (pricing is different across the stores which necessitated this), still a plugin was chosen, purchased and installed. All seemed fine we tested on a development site and everything worked.
When we launched, however, the auto redirect didn't work correctly (it was intermittently not working), a hole was quickly found in our testing process and when we re-tested on the development site we quickly re-created the problem.
Under certain situations, Magento can be slow (in fact very slow), as such to get any sort of decent customer experience you need to install or run a cache to speed it up. We have a Full Page Cache installed on our clients install on both the development and live sites, it's just turned off on development due to the rapidly changing nature of the development site.
Magento itself is event driven, this means that when the PHP code within Magento is run at certain key points an event is triggered or dispatched, other code is then configured to "listen" for those events and to run when they are triggered, lots of CMS' run in this way and its IMHO a very good way of allowing a CMS to be extended without hacking the internal code.
The FPC actually listens to a number of those events and stores a cache of the page and then sends it back to the browser, the problem comes in that it also does this right at the beginning of the process and thus prevents a large number of events from triggering (hence the speed up that a cache provides). In this case the FPC was always triggering prior to the GeoIP redirect module so the GeoIP redirect would only ever trigger if the cache was being re-built.
Our first port of call was the support team for the purchased GeoIP module, I had noticed in the module some code for the Enterprise Magento FPC and thought that maybe they would have a solution for the Community Edition with our cache, basically the answer from them was that it wasn't possible.
Then we did a bit more research and found that the company producing the FPC actually had a GeoIP redirect module, our first thoughts there were that surely they would interact properly. So we purchased the module installed and nope it didn't work, the same problem. Again they had code for the EE FPC so again we contacted their support, they did come up with a solution, however, their solution was to change a setting in the FPC to turn off the cache for on session initialization. This in effect means that when a customer first hits the site they do not get a cached version (ie very slow), our client was not happy with this solution so back to the support team only to be told, no that's not possible.
After lots of digging through code and trying front end based ideas (that didn't work), and looking at solutions that just were not customer friendly (at one point it looked like we may have to go for the pop-up box that asks the customer to select their location), we went back to the drawing board.
To start with I did some more research, I went and dug into Google and Magento events and found out a few things. Then I added some debug code to our development install of Magento to see exactly which events were being triggered both with and without the cache enabled. In both of the support team's answers they had told us they were listening for the earliest possible event and in fact, this was correct. However the research I conducted told me how, once Magento dispatched or triggered an event, the order in which subsequent plugins/modules were fired.
Magento fires off all globally registered listeners first, then frontend ones (in the case of a customer visiting, there is an equivalent admin section as well). Within Magento, code is organised into code repositories (core, local and community) and within the event sections listeners are run in that order (so it sends global - core first then global local etc., then frontend - core etc.), within each of those sections its sent in the order in which Magento loads the modules registration file (which is alphabetical based on the file name). The FPC listens to a global event, both of the GeoIP plugins listened only to frontend events.
So we wrote our own plugin, most of the plugin was around letting our client configure it themselves and to allow it to be expandable, so in the event they add another location they can quickly edit the settings, The actual GeoIP redirect is very simple (and quick). This also allowed us to fix up a few of the irritating issues around configuring the other plugins for our specific use. The plugin listened to the same event as the others except in a global setting, crucially we named the plugin module file AAISM_GeoIP.xml meaning it got loaded well before anything else.
Guess what? It all works well, we followed KISS principles so there are no fancy pop-up boxes to force the site to move (just click a standard Magento generated store URL), the configuration is easy (simply enable for a specific Magento Website and select the country(s) that is/are relevant to that website, configure user agents to ignore (so Google bots etc do not get redirected).
Never let someone else tell you what is or isn't possible, especially if you are sure that something can be done.
At the end of the day, our client is happy and the plugin authors have lost out as both plugins were sent back for a refund.