0

I want to redirect user to a specific store based on IP address. I am using front controller dispatch method. i have overridden this method through plugin and using before dispatch method.

I am also using controller_action_predispatch event in observer as well. First user is getting redirect to correct store but next user is getting cached page. controller_action_predispatch event is not firing.

How to redirect second user to a correct store and how to prevent cached page getting served to second user onwards.

Here is my switcher plugin,

<type name="Magento\Framework\App\FrontControllerInterface">
    <plugin name="custom_store_switcher"
            type="Companyname\Customredirect\Plugin\Switcher"
    />
</type>

class Switcher
{
    /**
     * @var \Companyname\Customredirect\Helper\Customer
     */
    private $geoIpHelperCustomer;

    /**
     * @var \Companyname\Customredirect\Model\Switcher
     */
    private $modelSwitcher;

    /**
     * @var \Magento\Framework\App\Response\Http
     */
    private $response;

    /**
     * @var \Magento\Store\Api\StoreRepositoryInterface
     */
    private $storeRepository;

    /**
     * Switcher constructor.
     *
     * @param \Companyname\Customredirect\Helper\Customer $geoIpHelperCustomer
     * @param \Companyname\Customredirect\Model\Switcher $modelSwitcher
     * @param \Magento\Framework\App\Response\Http $response
     * @param \Magento\Store\Api\StoreRepositoryInterface $storeRepository
     */
    public function __construct(
        \Companyname\Customredirect\Helper\Customer $geoIpHelperCustomer,
        \Companyname\Customredirect\Model\Switcher $modelSwitcher,
        \Magento\Framework\App\Response\Http $response,
        \Magento\Store\Api\StoreRepositoryInterface $storeRepository
    ) {
        $this->geoIpHelperCustomer = $geoIpHelperCustomer;
        $this->modelSwitcher       = $modelSwitcher;
        $this->response            = $response;
        $this->storeRepository     = $storeRepository;
    }

    /**
     * @param \Magento\Framework\App\FrontControllerInterface $subject
     * @param \Magento\Framework\App\RequestInterface $request
     *
     * @return void
     *
     * @throws \Magento\Framework\Exception\InputException
     * @throws \Magento\Framework\Stdlib\Cookie\CookieSizeLimitReachedException
     * @throws \Magento\Framework\Stdlib\Cookie\FailureToSendException
     */
    public function beforeDispatch(
        \Magento\Framework\App\FrontControllerInterface $subject,
        \Magento\Framework\App\RequestInterface $request
    ) {


        if (!$this->modelSwitcher->isAllowed($request)) {
            return;
        }

        $customerStoreCode = $this->modelSwitcher->getCustomerStoreCode();
        if (!$customerStoreCode) {
            return;
        }

        $storeCookie = $this->geoIpHelperCustomer->getCookie('geoip_store_code');

        if (!$storeCookie || $request->getParam('geoip_country', false)) {
            try {
                /** @var \Magento\Store\Model\Store $store */
                $store = $this->storeRepository->get($customerStoreCode);
            } catch (NoSuchEntityException $e) {
                return;
            }
            setcookie('geoip_store_code', $customerStoreCode, time() + $this->geoIpHelperCustomer->getCookieLifetime());
            setcookie('geoip_test_0', '3', time() + 100);
            setcookie('store', $customerStoreCode, time() + 86400);
            $params = $request->getParams();

            if (empty($params)) {
                $params['_query'] = ['___store' => $customerStoreCode];
            } else {
                $params['_query']['___store'] = $customerStoreCode;
            }

            $this->response->setRedirect($store->getUrl('', $params));

            return;
        } elseif ($request->getParam('___store', false)) {
            $requestStore = $request->getParam('___store', false);
            setcookie('geoip_store_code', $requestStore, time() + $this->geoIpHelperCustomer->getCookieLifetime());
            setcookie('geoip_test_0', '4', time() + 100);
            setcookie('store', $requestStore, time() + 86400);


        return;
    }
}

Observer:

<event name="controller_action_predispatch">
    <observer name="custom_storeswitcher_observer_autoswitcher"
              instance="Companyname\Customredirect\Model\Observer\Autoswitcher"
    />
</event>

Observer Class:


class Autoswitcher implements \Magento\Framework\Event\ObserverInterface
{
    /**
     * @var \Companyname\Customredirect\Helper\Customer
     */
    protected $geoipHelperCustomer;

    /**
     * @var \Companyname\Customredirect\Model\Switcher
     */
    protected $modelSwitcher;

    /**
     * @var \Magento\Framework\App\RequestInterface
     */
    protected $request;

    protected $design;


    /**
     * Store manager
     *
     * @var \Magento\Store\Model\StoreManagerInterface
     */
    protected $storeManager;

    /**
     * @param \Companyname\Customredirect\Helper\Customer $geoipHelperCustomer
     * @param \Companyname\Customredirect\Model\Switcher $modelSwitcher
     * @param \Magento\Framework\App\RequestInterface $request
     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
     */
    public function __construct(
        \Companyname\Customredirect\Helper\Customer $geoipHelperCustomer,
        \Companyname\Customredirect\Model\Switcher $modelSwitcher,
        \Magento\Framework\App\RequestInterface $request,
        \Magento\Framework\View\DesignInterface $design,
        \Magento\Store\Model\StoreManagerInterface $storeManager
    ) {

        $this->geoipHelperCustomer = $geoipHelperCustomer;
        $this->request = $request;
        $this->design = $design;
        $this->modelSwitcher = $modelSwitcher;
        $this->storeManager = $storeManager;
    }

    /**
     * Automatically switches store according to customer's location
     *
     * @param \Magento\Framework\Event\Observer $observer
     * @return \Companyname\Customredirect\Model\Observer
     */
    public function execute(\Magento\Framework\Event\Observer $observer)
    {

        if (!$this->modelSwitcher->isAllowed()) {
            return $this;
        }

        $customerStoreCode = $this->modelSwitcher->getCustomerStoreCode();
        if (!$customerStoreCode) {
            return $this;
        }

        $storeCookie = $this->geoipHelperCustomer->getCookie('geoip_store_code');
        if (!$storeCookie || $this->request->getParam('geoip_country', false)) {

            return $this->doRedirect($observer, $customerStoreCode, true);
        } elseif ($requestStore = $this->request->getParam('___store', false)) {
            setcookie('geoip_store_code', $requestStore, time() + ($this->geoipHelperCustomer->getCookieLifetime()));
            setcookie('geoip_test_0', '1', time() + 100);
            setcookie('store', $requestStore, time() + ($this->geoipHelperCustomer->getCookieLifetime()));

        }

        return $this;
    }


    public function doRedirect($observer, $customerStoreCode, $changeCookie = false)
    {

        $request = $this->request;

        $this->setDesignTheme($customerStoreCode);

        setcookie('store', $customerStoreCode, time() + 86400);
        if ($changeCookie) {
            setcookie('geoip_test_0', '2', time() + 100);
            $this->geoipHelperCustomer->setCookie('geoip_store_code', $customerStoreCode);
        }

        if ($request->getFullActionName() != 'cms_index_index') {
            $this->storeManager->setCurrentStore($customerStoreCode);
        }

        $redirectUrl = $this->modelSwitcher->getRedirectUrl($customerStoreCode);

        if ($redirectUrl) {
            return $observer->getControllerAction()
                            ->getResponse()
                            ->setRedirect($redirectUrl);
        }

        return true;
    }

 }
1

Use following event which work when FPC enabled:

controller_front_send_response_before

or you can go with JS implementation.

3
  • Will it work with controller FrontControllerInterface beforeDispatch() method? – vishal Dec 19 '19 at 13:54
  • 1
    no, all are cached. After clear cache will call one time. – Sohel Rana Dec 19 '19 at 14:58
  • Event controller_front_send_response_before worked for me. – vishal Dec 27 '19 at 14:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.