Magento – Magento 2.1.9 : Change store based on country

geoipmagento2store-switcher

Important: I don't want to buy any GeoIP extension.
I have a Magento 2.1.9 website with multi-site and multi-store setup.
I have setup website for KSA, UAE, CHINA, EGYPT etc. and under each website are at least 2 Store views, e.g., for KSA I have Arabic and English store views.

I want to show the user the website according to his country as per IP Address.
e.g., for users accessing from KSA the ar_sa (Arabic – Saudi arabia store should be default) similarly for users from UAE (ar_uae or en_uae).

I have done the following coding so far and got the country from IP address successfully.

This is my etc/frontend/events.xml file:

<config xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:noNamespaceSchemaLocation='urn:magento:framework/Event/etc/events.xsd'>
    <event name='controller_action_predispatch'>
        <observer name='Asoft_GeoIP_Redirect' instance='Asoft\GeoIP\Observer\Redirect' />
    </event>
</config>

And this is my Observer/Redirect.php:

namespace Asoft\GeoIP\Observer;

class Redirect implements \Magento\Framework\Event\ObserverInterface
{

    protected $_objectManager;
    protected $_storeManager;
    protected $_curl;

    public function __construct(
        \Magento\Framework\ObjectManagerInterface $objectManager,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\HTTP\Client\Curl $curl
    ) {
        $this->_objectManager = $objectManager;
        $this->_storeManager = $storeManager;
        $this->_curl = $curl;

    }

    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        //echo 'You are browsing from : '.$this->getCountryName();
        switch ($this->getCountryName()){
            case 'UAE':
                $store_id = '11';
                break;
            default :
                $store_id = '7';
        }$this->_storeManager->setCurrentStore($store_id);
    }

    public function getCountryName()
    {
        $visitorIp = $this->getVisitorIp();
        $url = "freegeoip.net/json/".$visitorIp;
        $this->_curl->get($url);
        $response = json_decode($this->_curl->getBody(), true);
        //echo '<pre>';
        //print_r($response);
        $countryCode = $response['country_code'];
        $countryName = $response['country_name'];
        $stateName = $response['region_name'];
        return $countryCode;
    }

    function getVisitorIp()
    {
        $remoteAddress = $this->_objectManager->create('Magento\Framework\HTTP\PhpEnvironment\RemoteAddress');
        return $remoteAddress->getRemoteAddress();
    }
}

But this changes only the store name and not other things – like language / currency or layout.

Best Answer

I found by looking at the Magento default store switcher that it calls {{url}}?___store={{store_code}}. So you would have to redirect the user to the same url but adding the get parameter containing the store code , e.g https://www.my-store.com/sofas?__store=france

Note that this PHP detection of location and redirecting is never going to work if you are planing on using a caching technology like varnish which I think you should. If you do use varnish, then you can still use most of your code but it needs to be executed from an AJAX request after the page loads.

Related Topic