Recently I met quite a challenge while building an extension for Magento. By default, the urls of simple child products whom belong to a configurable parent are answered with a 404. This behaviour can be easily overridden with a small extension.
Our client wanted to take it a step further. Today we will build an extension that redirects URLs of simple products to their configurable parents with options preselected.
If you’re looking for a tutorial on how to redirect requests to simple product pages to their configurable parent with swatches preselected in Magento 2, please continue reading here.
The XML Basics
Before we start, we need to create the basic files needed for any Magento extension.
Create app/etc/modules/DaanvandenBergh_RedirectSimpleProducts.xml
and add the following snippet into it:
<?xml version="1.0"?> | |
<config> | |
<modules> | |
<DaanvandenBergh_RedirectSimpleProducts> | |
<codePool>local</codePool> | |
<active>true</active> | |
<depends> | |
<Mage_Catalog /> | |
</depends> | |
</DaanvandenBergh_RedirectSimpleProducts> | |
</modules> | |
</config> |
Then create app/code/local/DaanvandenBergh/RedirectSimpleProducts/etc/config.xml
and paste the following code into it:
<?xml version="1.0"?> | |
<config> | |
<modules> | |
<DaanvandenBergh_RedirectSimpleProducts> | |
<version>1.0.0</version> | |
</DaanvandenBergh_RedirectSimpleProducts> | |
</modules> | |
<global> | |
<models> | |
<daanvandenbergh_redirectsimpleproducts> | |
<class>DaanvandenBergh_RedirectSimpleProducts_Model</class> | |
</daanvandenbergh_redirectsimpleproducts> | |
</models> | |
</global> | |
<frontend> | |
<events> | |
<controller_action_predispatch_catalog_product_view> | |
<observers> | |
<daanvandenbergh_redirectsimpleproducts> | |
<class>daanvandenbergh_redirectsimpleproducts/observer</class> | |
<method>redirectToConfigurable</method> | |
</daanvandenbergh_redirectsimpleproducts> | |
</observers> | |
</controller_action_predispatch_catalog_product_view> | |
</events> | |
</frontend> | |
</config> |
Now we have everything in place for our extension to be recognized by Magento as active. Also, we’ve told Magento which classes we will be using and when our methods should be fired.
We’ve added an observer to the event when a user opens a catalog product view and provided the class and method that should be executed.
So what does this mean in regular English? It means that this extension waits for a user to open a product page and then triggers the method we provided.
Now let’s move on to where the magic happens.
Redirect Simple Product to Configurable Parent
In config.xml
we specify when our extension should be triggered. In the class below we will specify what our extension should do.
Create /app/code/local/DaanvandenBergh/RedirectSimpleProducts/Model/Observer.php
and add the following code:
<?php | |
class DaanvandenBergh_RedirectSimpleProducts_Model_Observer { | |
public function redirectToConfigurable( $observer ) { | |
$id = Mage::app()->getRequest()->getParam( 'id' ); | |
$configurableParentIds = Mage::getResourceSingleton( 'catalog/product_type_configurable' )->getParentIdsByChild( $id ); | |
if ( isset( $configurableParentIds[0] ) ) { | |
$mainProduct = Mage::getModel( 'catalog/product' ) | |
->setStoreId( Mage::app()->getStore()->getId() ) | |
->load( $configurableParentIds[0] ); | |
$productAttributeOptions = $mainProduct->getTypeInstance( true )->getConfigurableAttributesAsArray( $mainProduct ); | |
$attributeOptions = array(); | |
foreach ( $productAttributeOptions as $productAttribute ) { | |
$simpleProduct = Mage::getModel( 'catalog/product' )->getCollection() | |
->addAttributeToFilter( 'entity_id', array( 'eq' => $id ) ) | |
->addAttributeToSelect( $productAttribute['attribute_code'] ) | |
->setPageSize( 1 ) | |
->getFirstItem(); | |
$attributeOptions[ $productAttribute['attribute_id'] ] = $simpleProduct->getData( $productAttribute['attribute_code'] ); | |
} | |
Mage::getSingleton( 'core/session' )->setSuperAttributes( $attributeOptions ); | |
Mage::app()->getResponse()->setRedirect( $mainProduct->getProductUrl(), 301 ); | |
Mage::app()->getResponse()->sendResponse(); | |
exit; | |
} | |
return $this; | |
} | |
} |
That’s it! Our method detects the product ID of the visited Simple Product URL and uses that to detect the ID of its configurable parent. Then it creates an array of all the available options, filters out the ones that are used by the Simple Child Product and sends it along with a 301-redirect.
The biggest upside of this approach is its SEO Friendliness. Since it uses the actual URL of the configurable parent, it doesn’t create any duplicate content. This makes this approach preferable over the approach of some premium plugins.
I hope this extension helps you. It redirects simple product URLs that are not visible in the catalog/search to their configurable parent with its options preselected. If you have any remarks or questions. Please, leave a comment!
Hi Thank you for your post. I would like to ask you how could I rewrite this module to make it work for Magento 2? Any advice would be appreciated, cheers.
I think code-wise you don’t have to change much. It’d mostly be the file structure that needs to be adjusted.
Interesting question, though. I’ll get back to it, ASAP!
Very interesting – as with the above poster, this is exactly what I’m looking for in Magento 2.
Perhaps, when I have more time, I’ll repost this for Magento 2. But, sadly, free time isn’t something I have much of these days. 🙁
Isn’t this bad for SEO? If the merchant doesn’t want people to visit the Simple Product page, then Spiders shouldn’t be able to index those pages either.
Sharp observation! However, it isn’t bad for SEO. It’s a much requested feature by merchants. Here’s how it works:
– The sitemap contains a list of all simple product URLs
– The Google bot crawls each of these URLs and essentially lands on the same page
– After this, you should rewrite your canonical URL to the simple product’s URL to tell the crawler to index the Simple Product’s URL instead of the configurable products’ URL. And for example, rewrite the meta title of the page “Purple T-shirt XXL”, instead of just “T-shirt”. But this is beyond the scope of this article. I can jump into it another time, perhaps.