Magento – Magento2: Re-direct to custom URL from observer

event-observergeoipmagento2redirect-url

My requirement is that if a customer visits website from country India they should be redirected to indian website www.example.com/in/ . In all other cases it should be default website only.

I'm using geoip PHP library. I've used frontend event controller_action_predispatch and here is my observer code:

namespace Amit\Geoip\Observer;
require_once 'lib/geoip.inc';
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Controller\ResultFactory;
use Magento\Store\Model\StoreManager;

class ControllerActionPredispatch implements  ObserverInterface {

    protected $resultRedirectFactory;

    public function __construct(
        ResultFactory $resultFactory,
        StoreManager $storeManager
    )  {
        $this->resultFactory = $resultFactory;
        $this->storeManager = $storeManager;
    }

    public function execute(\Magento\Framework\Event\Observer $observer) {
        $baseUrl = $this->storeManager->getStore()->getBaseUrl();
        $gi = geoip_open(getcwd()."/app/code/Amit/Geoip/Observer/lib/GeoIP.dat",GEOIP_STANDARD);
        $ip = $_SERVER['REMOTE_ADDR'];

        $country_code = geoip_country_code_by_addr($gi, $ip);

        if((strtoupper($country_code) == "IN")){
            $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
            $resultRedirect->setUrl($baseUrl . '/in/' . $_SERVER['REQUEST_URI']);
        }
    }
}

Problems:

  1. My observer function is being executed and I'm getting customers
    country from their IP but it is not re-directing to website
    www.example.com/in/*. What is the proper way to re-direct to my
    custom url?
  2. I think event controller_action_predispatch will call observer
    function on every page customer visits. Which event I should use so
    that it will be executed only for the first time customer visits the
    website?
  3. I see one of the possible options is setting cookie for it but I'm
    not sure where I should set cookie in my module (events? which
    event?) and which process I should follow to re-direct them.

Best Answer

There are multiple approaches how you can do this without editing magento code (webserver level, for example). These approaches might be more efficient.

But if you want to do it with magento, your $resultRedirect should be returned to App\Http. Your observer does not return $resultRedirect, so it is not processed by \Magento\Framework\App\Http::launch and redirect does not happen. Since you want your redirect logic to happen as early as possible, but only in storefront (is that right?) instead of observer you should put an around-plugin on \Magento\Framework\App\FrontControllerInterface::dispatch because it's the first method that gets called in \Magento\Framework\App\Http::launch after area is defined and returns ResultInterface. From that plugin you will be able to return your $resultRedirect object:

namespace My\Module\App\FrontController;

class Plugin
{
    // Constructor and dependencies here

    public function aroundDispatch(
        FrontControllerInterface $subject,
        callable $proceed,
        RequestInterface $request
    ) {
            $baseUrl = $this->storeManager->getStore()->getBaseUrl();
            $gi = geoip_open(getcwd()."/app/code/Amit/Geoip/Observer/lib/GeoIP.dat",GEOIP_STANDARD);
            $ip = $_SERVER['REMOTE_ADDR'];

            $country_code = geoip_country_code_by_addr($gi, $ip);

            if((strtoupper($country_code) == "IN")){
                $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
                $resultRedirect->setUrl($baseUrl . '/in/' . $_SERVER['REQUEST_URI']);
                return $resultRedirect;
            } else {
                return $proceed($request);
            }
    }
}

As for doing it only for first customer, cookie presence check looks like a viable option.

Related Topic