Magento2 | PWA | GraphQL

Display popup with promo text and coupon code and link to category or CMS pages in Magento2


In this post we will check how to display popup with promo text and coupon code and link to category or CMS pages in Magento2.

You can find complete module on Github at Magelearn_PopupPromo


Let's start it by creating custom module.



Add block with block id : pop-up-promo

Add Coupon code


Create folder inside app/code/Magelearn//PopupPromo

Add registration.php file in it:
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Magelearn_PopupPromo',
    __DIR__
);

Add composer.json file in it:

{
    "name": "magelearn/module-popup-promo",
    "description": "This module displays displays popup with promo text and coupon code.",
    "type": "magento2-module",
    "license": "proprietary",
    "version": "1.0.0",
    "authors": [
        {
            "name": "Vijay Rami",
            "email": "vijaymrami@gmail.com"
        }
    ],
    "minimum-stability": "dev",
    "require": {},
    "autoload": {
        "files": [
            "registration.php"
        ],
        "psr-4": {
            "Magelearn\\PopupPromo\\": ""
        }
    }
}

Add etc/module.xml file in it:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Magelearn_PopupPromo" setup_version="1.0.0">
        <sequence>
            <module name="Magento_Store"/>
            <module name="Magento_SalesRule"/>
            <module name="Magento_Cms"/>
        </sequence>
    </module>
</config>

Now we will add some system configuration settings to provide admin store configuration for :

-- Enable/disable popup.

-- Add some time delay for popup.

-- Advertising content by defining block_id

-- Display coupon code

-- Setings to choose a link for category or CMS page.

--- Provide settings to define custom css.

Add app/code/Magelearn//PopupPromo/etc/adminhtml/system.xml file.

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
    <system>
        <tab id="magelearn" translate="label" sortOrder="10">
            <label>Magelearn</label>
        </tab>
        <section id="magelearn_popuppromo" translate="label" sortOrder="140" showInDefault="1" showInWebsite="1" showInStore="1">
            <label>Popup Promo</label>
            <tab>magelearn</tab>
            <resource>Magelearn_PopupPromo::config_popup</resource>
            <group id="functional" translate="label" type="text" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1">
                <label>Functional Settings</label>
                <field id="enable" translate="label comment" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1">
                    <label>Enable Module</label>
                    <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
                </field>
                <field id="display_settings" translate="label comment" type="select" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1">
                    <label>Display settings</label>
                    <source_model>Magelearn\PopupPromo\Model\Config\Source\Display</source_model>
                    <depends>
                        <field id="magelearn_popuppromo/functional/enable">1</field>
                    </depends>
                </field>
                <field id="display_delay" translate="label comment" type="text" sortOrder="3" showInDefault="1" showInWebsite="1" showInStore="1">
                    <label>Delay</label>
                    <comment>In seconds</comment>
                    <depends>
                        <field id="magelearn_popuppromo/functional/display_settings">after_x_seconds</field>
                    </depends>
                    <validate>validate-number validate-not-negative-number</validate>
                </field>
            </group>
            <group id="content" translate="label" type="text" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1">
                <label>Content</label>
                <depends>
                    <field id="magelearn_popuppromo/functional/enable">1</field>
                </depends>
                <field id="block_id" translate="label comment" type="text" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1">
                    <label>Popup content*</label>
                    <comment>Block ID</comment>
                    <validate>required-entry</validate>
                </field>
                <field id="coupon_code" translate="label comment" type="text" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1">
                    <label>Coupon code*</label>
                    <validate>required-entry</validate>
                </field>
            </group>
            <group id="regulations" translate="label" type="text" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1">
                    <label>Regulations</label>
                    <depends>
                    	<field id="magelearn_popuppromo/functional/enable">1</field>
                	</depends>
                    <field id="text" translate="label comment" type="textarea" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1">
                        <label>Text</label>
                        <comment>It will be displayed below the coupon code</comment>
                    </field>
                    <field id="page" translate="label comment" type="select" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1">
                        <label>Linked page</label>
                        <source_model>Magelearn\PopupPromo\Model\Config\Source\Page</source_model>
                        <comment>It will be linked by "read more here"</comment>
                    </field>
                    <field id="category_page" translate="label comment" type="select" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1">
                    	<depends>
		                    <field id="magelearn_popuppromo/regulations/page">1</field>
		                </depends>
                        <label>Linked Category page</label>
                        <source_model>Magelearn\PopupPromo\Model\Config\Source\Categorylist</source_model>
                        <comment>It will be linked by "read more here"</comment>
                    </field>
            </group>
            <group id="design" translate="label" type="text" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1">
                <label>Design</label>
                <depends>
                    <field id="magelearn_popuppromo/functional/enable">1</field>
                </depends>
                <field id="custom_css" translate="label comment" type="textarea" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1">
                    <label>Custom CSS</label>
                </field>
            </group>
        </section>
    </system>
</config>

Now as per highlighted code above, we will add

app/code/Magelearn//PopupPromo/Model/Config/Source/Display.php file.

<?php

namespace Magelearn\PopupPromo\Model\Config\Source;

use Magento\Framework\Data\OptionSourceInterface;

class Display implements OptionSourceInterface
{
    /**
     * Return array of options as value-label pairs
     *
     * @return array Format: array(array('value' => '<value>', 'label' => '<label>'), ...)
     */
    public function toOptionArray()
    {
        return [
            ['value' => 'immediately', 'label' => 'Immediately'],
            ['value' => 'after_x_seconds', 'label' => 'After X seconds']
        ];
    }
}

app/code/Magelearn//PopupPromo/Model/Config/Source/Categorylist.php

<?php
namespace Magelearn\PopupPromo\Model\Config\Source;
 
use Magento\Framework\Option\ArrayInterface;
 
class Categorylist implements ArrayInterface
{
    protected $_categoryHelper;
 
    public function __construct(\Magento\Catalog\Helper\Category $catalogCategory)
    {
        $this->_categoryHelper = $catalogCategory;
    }
 	
	/**
     * Retrieve current store level 2 category
     *
     * @param bool|string $sorted (if true display collection sorted as name otherwise sorted as based on id asc)
     * @param bool $asCollection (if true display all category otherwise display second level category menu visible category for current store)
     * @param bool $toLoad
     */
    public function getStoreCategories($sorted = false, $asCollection = false, $toLoad = true)
    {
        return $this->_categoryHelper->getStoreCategories($sorted , $asCollection, $toLoad);
    }
 
    public function toOptionArray()
    {
 
        $arr = $this->toArray();
        $ret = [];
 
        foreach ($arr as $key => $value)
        {
 
            $ret[] = [
                'value' => $key,
                'label' => $value
            ];
        }
 
        return $ret;
    }
 
    public function toArray()
    {
 
        $categories = $this->getStoreCategories(true,true,true);
 
        $catagoryList = array();
        foreach ($categories as $category){
            $catagoryList[$category->getEntityId()] = __($category->getName());
        }
 
        return $catagoryList;
    }
 
}

app/code/Magelearn//PopupPromo/Model/Config/Source/Page.php

<?php

namespace Magelearn\PopupPromo\Model\Config\Source;

use Magento\Framework\Data\OptionSourceInterface;

class Page implements OptionSourceInterface
{
	/**
     * @var \Magento\Cms\Api\PageRepositoryInterface
     */
    protected $pageRepository;
    /**
    * @var \Magento\Framework\Api\SearchCriteriaBuilder
    */
    protected $searchCriteriaBuilder;
	
	public function __construct(
    	\Magento\Cms\Api\PageRepositoryInterface $pageRepository,
    	\Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder
	) {
	    $this->_cmsPage = $pageRepository;
	    $this->_search = $searchCriteriaBuilder;
	}

    /**
     * Return array of options as value-label pairs
     *
     * @return array Format: array(array('value' => '<value>', 'label' => '<label>'), ...)
     */
    public function toOptionArray() {
	    $pages = [];
	    foreach($this->_cmsPage->getList($this->_getSearchCriteria())->getItems() as $page) {
	        $pages[] = [
	            'value' => $page->getIdentifier(),
	            'label' => $page->getTitle()
	        ];
	    }
		array_push($pages, [
            'label' => __('Category Page'),
            'value' => 1
        ]);
	    return $pages;
	}

	protected function _getSearchCriteria() {
	    return $this->_search->addFilter('is_active', '1')->create();
	}
}

And will provide some default settings at app/code/Magelearn//PopupPromo/etc/config.xml file.

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
    <default>
        <magelearn_popuppromo>
            <functional>
                <enable>0</enable>
            </functional>
        </magelearn_popuppromo>
    </default>
</config>

Will also add app/code/Magelearn//PopupPromo/etc/acl.xml file.

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/acl.xsd">
    <acl>
        <resources>
            <resource id="Magento_Backend::admin">
                <resource id="Magento_Backend::stores">
                    <resource id="Magento_Backend::stores_settings">
                        <resource id="Magento_Config::config">
                            <resource id="Magelearn_PopupPromo::config_popup" title="Popup Promo Settings" />
                        </resource>
                    </resource>
                </resource>
            </resource>
        </resources>
    </acl>
</config>

Now first we will define our layout file at app/code/Magelearn//PopupPromo/view/frontend/layout/default.xml file.

<?xml version="1.0"?>
<page layout="3columns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="before.body.end">
            <block ifconfig="magelearn_popuppromo/functional/enable" class="Magelearn\PopupPromo\Block\Popup" name="magelearn.popup.promo" template="Magelearn_PopupPromo::popup.phtml" after="-"/>
        </referenceContainer>
    </body>
</page>

Now we will add our block file at app/code/Magelearn//PopupPromo/Block/Popup.php file.

<?php

namespace Magelearn\PopupPromo\Block;

use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\View\Element\Template;
use Magento\Framework\UrlInterface;
use Magelearn\PopupPromo\Helper\Data as DataHelper;

class Popup extends Template
{
    protected $dataHelper;
	protected $_storeManager;
    protected $categoryRepository;
	
    public function __construct(
        DataHelper $dataHelper,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Catalog\Model\CategoryRepository $categoryRepository,
        Template\Context $context,
        array $data = []
    ) {
        $this->dataHelper = $dataHelper;
		$this->_storeManager = $storeManager;
		$this->categoryRepository = $categoryRepository;
        parent::__construct($context, $data);
    }

    /**
     * Is module enabled/disabled
     *
     * @return bool
     */
    public function isModuleEnabled()
    {
        return (boolean) $this->dataHelper->getConfig('magelearn_popuppromo/functional/enable');
    }

    /**
     * Get display settings
     *
     * @return string
     */
    public function getDisplaySettings()
    {
        return $this->dataHelper->getConfig('magelearn_popuppromo/functional/display_settings');
    }

    /**
     * Get display settings
     *
     * @return integer
     */
    public function getDisplayDelay()
    {
        return (int)$this->dataHelper->getConfig('magelearn_popuppromo/functional/display_delay');
    }

    /**
     * Get block ID
     *
     * @return string|null
     */
    public function getBlockId()
    {
        return $this->dataHelper->getConfig('magelearn_popuppromo/content/block_id');
    }

    /**
     * Get coupon code
     *
     * @return string|null
     */
    public function getCouponCode()
    {
        return $this->dataHelper->getConfig('magelearn_popuppromo/content/coupon_code');
    }

    /**
     * Get regulations text
     *
     * @return string|null
     */
    public function getRequlationsText()
    {
        return $this->dataHelper->getConfig('magelearn_popuppromo/regulations/text');
    }

    /**
     * Get page URL
     *
     * @return string|null
     * @throws NoSuchEntityException
     */
    public function getPageUrl()
    {
    	if($this->dataHelper->getConfig('magelearn_popuppromo/regulations/page') == 1) {
    		$categoryId = $this->dataHelper->getConfig('magelearn_popuppromo/regulations/category_page');
			$category = $this->categoryRepository->get($categoryId, $this->_storeManager->getStore()->getId());
        	return $category->getUrl();
    	}
        return $this->_storeManager->getStore()->getBaseUrl(UrlInterface::URL_TYPE_WEB) . $this->dataHelper->getConfig('magelearn_popuppromo/regulations/page');
    }

    /**
     * Get custom CSS
     *
     * @return string|null
     */
    public function getCustomCss()
    {
        return $this->dataHelper->getConfig('magelearn_popuppromo/design/custom_css');
    }
}
As per code highlighted above, we will add our helper file at app/code/Magelearn//PopupPromo/Helper/Data.php
<?php

namespace Magelearn\PopupPromo\Helper;

use Magento\Framework\App\Helper\AbstractHelper;

class Data extends AbstractHelper
{
    /**
     * Get scope config
     *
     * @param $path
     * @return mixed
     */
    public function getConfig($path)
    {
        return $this->scopeConfig->getValue($path, \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
    }
}
And a template file at app/code/Magelearn//PopupPromo/view/frontend/templates/popup.phtml
<?php
/**
 * @var $block Magelearn\PopupPromo\Block\Popup
 */
?>

<?php if ($block->isModuleEnabled() && $block->getCouponCode()): ?>
    <div class="magelearn-promo-popup" id="magelearn-promo-popup">
        <span class="close">X</span>
        <div class="promo-content">
            <div class="promo-block">
                <?= $this->getLayout()->createBlock('Magento\Cms\Block\Block')->setBlockId($block->getBlockId())->toHtml(); ?>
            </div>

            <div class="coupon">
                <input type="text" value="<?= $block->getCouponCode() ?>">
                <button class="action primary" data-copied="<?= __('Copied') ?>"><?= __('Copy') ?></button>
            </div>

            <br class="clear" />

            <?php if ($block->getRequlationsText()): ?>
                <div class="regulations">
                    <?= $block->getRequlationsText() ?>
                    <br />
                    <?= __('Ream more') ?> <a href="<?= $block->getPageUrl() ?>"><?= __('here') ?></a>.
                </div>
            <?php endif ?>
        </div>
    </div>

    <?php if ($block->getCustomCss()): ?>
        <style>
            <?= $block->getCustomCss() ?>
        </style>
    <?php endif ?>

    <script type="text/x-magento-init">
        {
            "#magelearn-promo-popup": {
                "popupPromo": {
                    "container": "#magelearn-promo-popup",
                    "button": "#magelearn-promo-popup button",
                    "code": "#magelearn-promo-popup input",
                    "close": "#magelearn-promo-popup .close",
                    "displaySettings": "<?= $block->getDisplaySettings() ?>",
                    "displayDelay": "<?= $block->getDisplayDelay() ?>"
                }
            }
        }
    </script>
<?php endif ?>

Now we will add our JS file. For that first we will define our JS file path at app/code/Magelearn//PopupPromo/view/frontend/requirejs-config.js

var config = {
    "map": {
        "*": {
            popupPromo: 'Magelearn_PopupPromo/js/popup'
        }
    }
};

Now we will add our JS widget at app/code/Magelearn//PopupPromo/view/frontend/web/js/popup.js

define([
    'jquery',
    'jquery/jquery.cookie'
], function ($) {
    'use strict';

    $.widget('magelearn.popupPromo', {
        cookieName: 'magelearn_popup_promo',

        cookie: function() {
            var now = new Date().getTime(),
                expiryDate = now + (10 * 60 * 1000);
            $.cookie(this.cookieName, 1, {path: '/', expires: expiryDate});
        },

        _create: function () {
            var options = this.options;

            /** Close popup */
            $(options.close).click(function () {
                $(options.container).fadeOut();
            });

            /** Copy promo code */
            $(options.button).click(function () {
                var $temp = $('<input>');
                $('body').append($temp);
                $temp.val($(options.code).val()).select();
                document.execCommand("copy");
                $temp.remove();
                $(options.button).text($(options.button).data('copied'));
            });

            /** Display */
            var obj = this;
            if ($.cookie(this.cookieName) != 1) {
                if (options.displaySettings == 'after_x_seconds') {
                    setTimeout(function () {
                        $(options.container).fadeIn();
                        obj.cookie();
                    }, parseInt(options.displayDelay) * 1000);
                } else if (options.displaySettings == 'immediately') {
                    $(options.container).fadeIn();
                    obj.cookie();
                }
            }
        }
    });

    return $.magelearn.popupPromo;

});

To display this popup content properly, I have added css file at app/code/Magelearn//PopupPromo/view/frontend/web/css/source/_module.less

0 Comments On "Display popup with promo text and coupon code and link to category or CMS pages in Magento2"

Back To Top