8

How can I redirect an SEO URL Key of a Simple product of which the visibility is set to "Not Individually Visible" to the parent Configurable Product SEO URL Key?

There are two important conditions that need to be met:

  • the options on the Configurable Product page should be correctly preselected to display the attributes of the Simple product.

  • the price for the Single Product also needs to be displayed correctly.

Example

Configurable Product P1 has two attributes. Each attribute has two options:

Attribute A1 has options O1 and O2

Attribute A2 has options O3 and O4

So Configurable Product P1 has 4 Configurations represented by 4 Simple Products with each a different price:

P2: O1 and O3 -> EUR 1

P3: O1 and O4 -> EUR 2

P4: O2 and O3 -> EUR 3

P5: O2 and O4 -> EUR 4

The problem that needs to be solved is that for each Configuration the parent Configurable Product URL Key is sent to Google Merchant Shopping as an XML feed.

But when Google is verifying the prices of the Configurations on the parent Configurable Product URL page the prices won't match for P3, P4, and P5 as by default the lowest price is shown by Magento. And this in turn will result in the following warning in Google Merchant:

"Insufficient match of microdata price information". In the above example 75% of the data isn't matching.

I already took a look at How redirect simple products of Configurable product but it is referring to an event which to my understanding does not exist in Magento 2: controller_action_predispatch_catalog_product_view.

I also tried the suggestions at Magento2 Event Observer Redirect Simple Product to Configurable Product but it seems that the Plugin can only work if the product visibility is not set to "Not Individually Visible".

So I suspect that the canShow method defined in Magento/Catalog/Helper/Product.php is called before the Magento/Catalog/Controller/Product/View is executed but I have a hard time figuring out where this happens.

How does Magento determine that an URL key is representing a product?

And where are the product id, category id, and options parameters derived from the URL key to be passed on to the execute method in Magento/Catalog/Controller/Product/View.php?

Any help would be much appreciated.

4 Answers 4

3

You can use a plugin to achieve that. In your module's etc/di.xml file write the plugin declaration

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Catalog\Model\Product\Url">
        <plugin name="My_Extension_Product_Redirect" type="Vendor\Module\Plugins\Url" />
    </type>
</config>

And then in the Vendor/Module/Plugins/Url.php file you can use a before plugin like so

<?php

namespace Vendor\Module\Plugins;
use Magento\Catalog\Model\ProductRepository;
use \Magento\ConfigurableProduct\Model\Product\Type\Configurable;

class Url{

    protected $_configurableProductInstance;
    protected $_productRepository;

    function __construct(
        Configurable $configurable,
        ProductRepository $productRepository,
    )
    {
        $this->_configurableProductInstance = $configurable;
        $this->_productRepository = $productRepository;
    }

    public function beforegetProductUrl(\Magento\Catalog\Model\Product\Url $subject, \Magento\Catalog\Model\Product $product, $useSid)
    {
        $parentId = $this->_configurableProductInstance->getParentIdsByChild($product->getId());
        if(count($parentId)){
            return [$this->_productRepository->getById($parentId[0]), $useSid];
        }
        return null;
    }
}
4
  • "How does Magento determine that an URL key is representing a product?" This link may be helpful to understand URL rewrites in Magento
    – Jay Ghosh
    Sep 12, 2017 at 5:26
  • 1
    I believe plugin method name should be beforeGetProductUrl, not beforegetProductUrl (G letter needs to be Capitalised)
    – Macas
    Feb 1, 2018 at 9:33
  • 1
    @Macas At the time of answering this, both beforegetProductUrl and beforeGetProductUrl seemed to work. But in Magento 2.2.2, it seems only beforeGetProductUrl would work
    – Jay Ghosh
    Feb 2, 2018 at 9:45
  • 1
    You will not be happy with that solution... Cause Google will reject your products because the price in source code will not match with the price in your feed.
    – roman204
    Feb 14, 2018 at 10:20
2

Came across this question and see you haven't accepted an answer yet. I wrote a tutorial on this a while back: https://daan.dev/how-to/redirect-simple-products-configurable-parent-attributes-pre-selected/

I'm not going to copy-paste the entire tutorial here, but basically you can take care of it using only an observer:

<?php
namespace DaanvdB\RedirectSimpleProducts\Observer;

use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;

class Predispatch implements ObserverInterface {

    protected $_redirect;

    protected $_productTypeConfigurable;

    protected $_productRepository;

    protected $_storeManager;

    public function __construct (
        \Magento\Framework\App\Response\Http $redirect,
        \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable $productTypeConfigurable,
        \Magento\Catalog\Model\ProductRepository $productRepository,
        \Magento\Store\Model\StoreManagerInterface $storeManager
    ) {
        $this->_redirect = $redirect;
        $this->_productTypeConfigurable = $productTypeConfigurable;
        $this->_productRepository = $productRepository;
        $this->_storeManager = $storeManager;
    }

    public function execute(Observer $observer)
    {
        $pathInfo = $observer->getEvent()->getRequest()->getPathInfo();
        /** If it's not a product view we don't need to do anything. */
        if (strpos($pathInfo, 'product') === false) {
            return;
        }
        $request = $observer->getEvent()->getRequest();
        $simpleProductId = $request->getParam('id');
        if (!$simpleProductId) {
            return;
        }
        $simpleProduct = $this->_productRepository->getById($simpleProductId, false, $this->_storeManager->getStore()->getId());
        if (!$simpleProduct || $simpleProduct->getTypeId() != \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE) {
            return;
        }
        $configProductId = $this->_productTypeConfigurable->getParentIdsByChild($simpleProductId);
        if (isset($configProductId[0])) {
            $configProduct = $this->_productRepository->getById($configProductId[0], false, $this->_storeManager->getStore()->getId());
            $configType = $configProduct->getTypeInstance();
            $attributes = $configType->getConfigurableAttributesAsArray($configProduct);
            $options = [];
            foreach ($attributes as $attribute) {
                $id = $attribute['attribute_id'];
                $value = $simpleProduct->getData($attribute['attribute_code']);
                $options[$id] = $value;
            }
            $options = http_build_query($options);
            $hash = $options ? '#' . $options : '';
            $configProductUrl = $configProduct->getUrlModel()
                    ->getUrl($configProduct) . $hash;
            $this->_redirect->setRedirect($configProductUrl, 301);
        }
    }
}

Hope it'll help you or anyone out.

1
  • still working on magento 2.4.2 May 16, 2022 at 21:34
1

To preselect a simple product in a configurable product, the address of a simple product should look like this for example:

/mona-pullover-hoodlie.html#143=167&93=53

where

/mona-pullover-hoodlie.html - configurable product URL,

143, 93 - attributes IDs,

167, 53 - option IDs.

In order to change the URL of simple products, you can create a Plugin (Interceptor) for Magento\Catalog\Model\Product::getProductUrl(), where to generate the URL as in the example above.


I made VCT Simple Product URL module on Magento Marketplace that solves this problem.

0

I believe the root cause is: URL rewrite didn't generate URL rewrite for Not visible products. Thus Magento redirected to 404 because it got nothing mapped to the request URL.

  • Potential solution is creating a route and validating the is that request belong to an Product and redirect it to the configurable instead of 404 page.

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.