Hello Friends, in this blog, we will learn how can we add extra or custom content or media to Configurable Products’ Fotorama media gallery at the front end in visual and text swatches case.
For dropdown swatch type, check our blog Add Custom Content in Configurable Product Media Gallery – Magento 2
In Magento 2, on the configurable product page, for rendering the swatch attributes, <magento-root-dir.>/vendor/magento/module-swatches/view/base/web/js/swatch-renderer.js file is responsible.
So, to add extra content in the configurable product’s media gallery(in text and visual swatch case), we need to override a few methods of the swatch-renderer js file.
For example, updateBaseImage, _onGalleryLoaded and _loadMedia functions are responsible for updating the media gallery after swatch rendering and swatch selection.
So, to add the custom content I have overridden the required functions and added some required files which are required to achieve our goal.
First of all, we will create a demo module. Here, I have created the Webkul_ExtraContentInFotorama module. Further, follow the below steps:
1. Create a di.xml file inside the <magento-root-dir>/app/code/Webkul/ExtraContentInFotorama/etc/ directory.
<?xml version="1.0"?> <!-- /** * Webkul Software. * * @category Webkul * @package Webkul_ExtraContentInFotorama * @author Webkul Software Private Limited * @copyright Webkul Software Private Limited ( * @license */ --> <config xmlns:xsi=" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <!--Add Extra Configuration Data In JsonConfig--> <type name="Magento\ConfigurableProduct\Block\Product\View\Type\Configurable"> <plugin name="Wk_afterGetJsonConfig" type="Webkul\ExtraContentInFotorama\Plugin\ConfigurableProduct\Block\ConfigurableAfterGetJsonConfigPlugin" sortOrder="50" /> </type> </config>
2. Create ConfigurableAfterGetJsonConfigPlugin.php file inside the <magento-root-dir>/app/code/Webkul/ExtraContentInFotorama/Plugin/ConfigurableProduct/Block/ directory.
<?php /** * Webkul Software. * * @category Webkul * @package Webkul_ExtraContentInFotorama * @author Webkul Software Private Limited * @copyright Webkul Software Private Limited ( * @license */ namespace Webkul\ExtraContentInFotorama\Plugin\ConfigurableProduct\Block; class ConfigurableAfterGetJsonConfigPlugin /** * @var \Magento\Framework\App\RequestInterface */ protected $request; /** * @var \Magento\Framework\Json\Helper\Data */ protected $jsonHelper; /** * Initialize dependencies * * @param \Magento\Framework\Json\Helper\Data $jsonHelper * @param \Magento\Framework\App\RequestInterface $request * @return void */ public function __construct( \Magento\Framework\Json\Helper\Data $jsonHelper, \Magento\Framework\App\RequestInterface $request ) $this->request = $request; $this->jsonHelper = $jsonHelper; /** * Composes configuration for js * * @param \Magento\ConfigurableProduct\Block\Product\View\Type\Configurable $subject * @param string $resultJson * @return string */ public function afterGetJsonConfig( \Magento\ConfigurableProduct\Block\Product\View\Type\Configurable $subject, $resultJson ) //Check if request is made from product page// if (strtolower($this->request->getFullActionName()) == "catalog_product_view") $result = $this->jsonHelper->jsonDecode($resultJson); /////Set Extra Configuration Data///// $customConfig = []; $customConfig["linkUrl"] = " $customConfig["thumbnailImage"] = "Provide a thumbnail Image URL"; $customConfig["linkContent"] = "Design Patterns in Magento 2"; //set super attribute id, on which selection you want to change the content// $customConfig["defaultVariantAttribute"] = 138; $result["customConfig"] = $customConfig; $resultJson = $this->jsonHelper->jsonEncode($result); ///////// return $resultJson;
3. Create a requires-config.js file to mention the mixin file for the swatch-renderer.js file inside the <magento-root-dir.>/app/code/Webkul/ExtraContentInFotorama/view/frontend/ directory.
/** * Webkul Software. * * @category Webkul * @package Webkul_ExtraContentInFotorama * @author Webkul Software Private Limited * @copyright Webkul Software Private Limited ( * @license */ var config = config: mixins: 'Magento_Swatches/js/swatch-renderer' : 'Webkul_ExtraContentInFotorama/js/swatch-renderer':true ;
4. Create a swatch-renderer.js file inside the <magento-root-dir.>/app/code/Webkul/ExtraContentInFotorama/view/frontend/web/js/ directory.
/** * Webkul Software. * * @category Webkul * @package Webkul_ExtraContentInFotorama * @author Webkul Software Private Limited * @copyright Webkul Software Private Limited ( * @license */ define([ 'jquery', 'underscore', 'mage/translate' ], function ($, _, $t) { 'use strict'; return function (SwatchRenderer) { $.widget('mage.SwatchRenderer', SwatchRenderer, { /** * Update [gallery-placeholder] or [product-image-photo] * @param Array images * @param jQuery context * @param Boolean isInProductView */ updateBaseImage: function (images, context, isInProductView) , /** * Callback which fired after gallery gets initialized. * * @param HTMLElement element - DOM element associated with a gallery. */ _onGalleryLoaded: function (element) var galleryObject = element.data('gallery'); //////////// var currImgs = galleryObject.returnCurrentImages(); //Load Extra Content// this._loadExtraContent(); //Push Extra Content in images gallery var self = this.options.jsonConfig.customConfig; var modelThumbnailImg = self.thumbnailImage; this._pushExtraContent(currImgs, modelThumbnailImg); ////////////////// this.options.mediaGalleryInitial = currImgs; ///Update Current Images in Media Gallery/// galleryObject.updateData(currImgs); , /** * Load media gallery using ajax or json config. * * @private */ _loadMedia: function () var self = this.options.jsonConfig.customConfig; //Get Custom Config. var $main = this.inProductList ? this.element.parents('.product-item-info') : this.element.parents('.column.main'), images; if (this.options.useAjax) this._debouncedLoadProductMedia(); else images = this.options.jsonConfig.images[this.getProduct()]; if (!images) images = this.options.mediaGalleryInitial; ////////////Load Extra Content///// this._loadExtraContent(); //Remove Extra Content from image array images = this._removeExtraContentfromArray(images); var self = this.options.jsonConfig.customConfig; var modelThumbnailImg = self.thumbnailImage; //Push Extra Content from image array this._pushExtraContent(images, modelThumbnailImg); ////////////////// this.updateBaseImage(this._sortImages(images), $main, !this.inProductList); , /** * Delete Additional Extra Content from array * * @param Array imagesArray * @returns Array * @private */ _removeExtraContentfromArray: function(imagesArray) imagesArray = imagesArray.filter(element => element.type !== "ExtraContent"); return imagesArray; , /** * Push Extra Content in array * * @param Array fotoramaContentArray * @param string modelThumbnailImg * @private */ _pushExtraContent: function(fotoramaContentArray, modelThumbnailImg) , /** * Get Selected Variant Value * * @return string * @private */ _getSelectedVariantValue: function() { var self = this.options.jsonConfig.customConfig; var optionTextVal = ""; var optionTextArr = []; var selectedText = ""; var selectedVal = ""; var selectedSwatchAttrId = 0; var defaultVariantAttribute = self.defaultVariantAttribute; if ($('.product-options-wrapper select[id^="attribute"]').find().length) selectedText = $('.product-options-wrapper select[id^="attribute"] option:selected').text(); else { if ($('.swatch-attribute-options .swatch-option[aria-checked="true"]').length) var swatchId = ""; var idParts = []; $('.swatch-attribute-options .swatch-option[aria-checked="true"]').each(function() swatchId = $(this).attr("id"); idParts = swatchId.split('-'); for (let index=0; index<idParts.length; index++) if ($.isNumeric(idParts[index])) selectedSwatchAttrId = idParts[index]; break; if (parseInt(defaultVariantAttribute) == selectedSwatchAttrId) selectedText = $(this).attr("data-option-label"); ); } /////Get Selected Variant Value///// selectedVal = $('.product-options-wrapper select[id^="attribute"] option:selected').val(); if (selectedVal == "" && $('.product-options-wrapper select[id^="attribute"]').find().length) selectedText = $('.product-options-wrapper select[id^="attribute"] option:eq(1)').text(); else selectedVal = selectedText; ///// if ($('.product-options-wrapper select[id^="attribute"]').find().length) if (selectedText.indexOf('+') == -1) optionTextVal = selectedText; else optionTextArr = selectedText.split('+'); optionTextVal = $.trim(optionTextArr[0]); else optionTextVal = selectedVal; return optionTextVal; }, /** * Event for swatch options * * @param Object $this * @param Object $widget * @private */ _OnClick: function ($this, $widget) var self = this.options.jsonConfig.customConfig; var wkExtraContentDiv = $("#wkExtraContent"); var mainVariantAttributeId = self.defaultVariantAttribute; var swatchId = $this.attr("id"); var idParts = swatchId.split('-'); var selectedSwatchAttrId = 0; for (let index=0; index<idParts.length; index++) if ($.isNumeric(idParts[index])) selectedSwatchAttrId = idParts[index]; break; if (typeof wkExtraContentDiv == "object" && selectedSwatchAttrId == parseInt(mainVariantAttributeId)) var label = $this.attr("data-option-label"); var bgColor = "#86FA50"; switch (label) case 'Gold': bgColor = "#DFD906"; break; case 'Diamond': bgColor = "#AFF3F2"; break; setTimeout(function() $("#wkExtraContent").css("background-color", bgColor); , 300); this._super($this, $widget); , /** * Load Extra Content * * @private */ _loadExtraContent: function() var thisJs = this; var self = this.options.jsonConfig.customConfig; var divFotorama = $('div.gallery-placeholder > div.fotorama'); if (self.linkUrl == "") return; var variantText = "None"; //Get Selected Variant Value variantText = thisJs._getSelectedVariantValue(); divFotorama.on('fotorama:load', function fotorama_onLoad(e, fotorama, extra) if (extra.frame.type === 'ExtraContent' && extra.frame.src != "") var extraContentHtml = ''; extraContentHtml += '<div id="wkExtraContent" style="background-color:#86FA50">'; extraContentHtml += '<h1 style="margin-top:250px">'+'Extra Content'+'</h1>'; ///Show Variant Text/// if (variantText != '') extraContentHtml += '<p style="font-size:20px">Selected Variant:</p>'; extraContentHtml += '<p style="font-size:18px">'+variantText+'</p><br/>'; ///////////////// extraContentHtml += '<a href="'+self.linkUrl+'" style="font-size:18px">' extraContentHtml += self.linkContent+'</a>'; extraContentHtml += '</div>'; extra.frame.$stageFrame.html(extraContentHtml); ); }); return $.mage.SwatchRenderer; }; });
5. After adding the above code to your module. Deploy the code and see the result in the text swatch case. Refer to the below images for the result.

6. See the result in the visual swatch case. Refer to the below images for the result.


Note: Remember to add <sequence> in the module.xml file to load the Magento_Swatches module before your custom module.
You may also check the Magento 2 Advanced Media Manager extension to edit the images present in the media gallery and add watermarks, filter, rotate, resize, and more.