In this post we will check how to add newsletter subscriber at checkout page in Magento2.
Create folder inside app/code/Magelearn/NewsletterSubscribeAtCheckout
<?php \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'Magelearn_NewsletterSubscribeAtCheckout', __DIR__ );
Add composer.json file in it:
{ "name": "magelearn/magento2-newsletter-subscribe-at-checkout", "description": "This module allows to enable a newsletter subscription checkbox on the checkout page. Customers can subscribe to your newsletter list in Marketing > Communications > Newsletter Subscribers during checkout.", "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\\NewsletterSubscribeAtCheckout\\": "" } } }
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_NewsletterSubscribeAtCheckout" setup_version="1.0.0"> <sequence> <module name="Magento_Checkout"/> <module name="Magento_Newsletter"/> </sequence> </module> </config>
Now, we will add database setup script.
Create db_schema.xml file in etc folder.
this script will add new column `newsletter_subscribe` in `quote` table.
<?xml version="1.0"?> <schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd"> <table name="quote" resource="checkout" engine="innodb" comment="Newsletter Subscribe At Checkout"> <column xsi:type="int" name="newsletter_subscribe" padding="5" unsigned="true" nullable="false" identity="false" default="0" comment="Newsletter Subscribe"/> </table> </schema>
To validate this db_schema.xml file we will first run below command:
php bin/magento setup:db-declaration:generate-whitelist --module-name=Magelearn_NewsletterSubscribeAtCheckout
This command will automatically generate db_schema_whitelist.json file inside etc folder.
<?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> <section id="checkout" translate="label" type="text" sortOrder="305" showInDefault="1" showInWebsite="1" showInStore="1"> <class>separator-top</class> <label>Checkout</label> <tab>sales</tab> <resource>Magento_Checkout::checkout</resource> <group id="magelearn_newslettersubscribeatcheckout" translate="label" sortOrder="120" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Newsletter Subscribe At Checkout</label> <field id="enabled" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Enabled</label> <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> </field> <field id="checked" translate="label" type="select" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Checked</label> <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> <comment>This will pre-tick the newsletter checkbox.</comment> <depends> <field id="enabled">1</field> </depends> </field> <field id="label" translate="label" type="text" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Label</label> <validate>validate-no-empty</validate> <comment>E.g: Subscribe for Newsletter</comment> <depends> <field id="enabled">1</field> </depends> </field> <field id="note_enabled" translate="label" type="select" sortOrder="40" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Enable Note</label> <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> <comment>Enable a note right below the newsletter subscription.</comment> <depends> <field id="enabled">1</field> </depends> </field> <field id="note" translate="label" type="textarea" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Text for Note</label> <comment>E.g: Subscribe now and receive great discount codes monthly. HTML is supported.</comment> <depends> <field id="enabled">1</field> <field id="note_enabled">1</field> </depends> </field> </group> </section> </system> </config>
Now, we will provide some pre-selected configuration values in etc/config.xml file.
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd"> <default> <checkout> <magelearn_newslettersubscribeatcheckout> <enabled>0</enabled> <checked>0</checked> <label>Subscribe for Newsletter</label> <note_enabled>0</note_enabled> </magelearn_newslettersubscribeatcheckout> </checkout> </default> </config>
We will add this newsletter subscriber field by adding UI Component (Magento\Checkout\Block\Onepage\layoutProcessors) and modifying layout file (checkout_index_index.xml).
Add app/code/Magelearn/NewsletterSubscribeAtCheckout/view/frontend/layout/checkout_index_index.xml file.
<?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="checkout" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <referenceBlock name="checkout.root"> <arguments> <argument name="jsLayout" xsi:type="array"> <item name="components" xsi:type="array"> <item name="checkout" xsi:type="array"> <item name="children" xsi:type="array"> <item name="steps" xsi:type="array"> <item name="children" xsi:type="array"> <item name="shipping-step" xsi:type="array"> <item name="children" xsi:type="array"> <item name="shippingAddress" xsi:type="array"> <item name="children" xsi:type="array"> <item name="customer-email" xsi:type="array"> <item name="config" xsi:type="array"> <item name="template" xsi:type="string">Magelearn_NewsletterSubscribeAtCheckout/form/element/email</item> </item> <item name="children" xsi:type="array"> <item name="newsletter_subscribe" xsi:type="array"> <item name="component" xsi:type="string">Magento_Ui/js/form/form</item> <item name="displayArea" xsi:type="string">newsletter_subscribe</item> <item name="config" xsi:type="array"> <item name="template" xsi:type="string">Magelearn_NewsletterSubscribeAtCheckout/form/element/newsletter_subscribe</item> </item> </item> </item> </item> </item> </item> </item> </item> <item name="billing-step" xsi:type="array"> <item name="children" xsi:type="array"> <item name="payment" xsi:type="array"> <item name="children" xsi:type="array"> <item name="customer-email" xsi:type="array"> <item name="config" xsi:type="array"> <item name="template" xsi:type="string">Magelearn_NewsletterSubscribeAtCheckout/form/element/email</item> </item> <item name="children" xsi:type="array"> <item name="newsletter_subscribe" xsi:type="array"> <item name="component" xsi:type="string">Magento_Ui/js/form/form</item> <item name="displayArea" xsi:type="string">newsletter_subscribe</item> <item name="config" xsi:type="array"> <item name="template" xsi:type="string">Magelearn_NewsletterSubscribeAtCheckout/form/element/newsletter_subscribe</item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </argument> </arguments> </referenceBlock> </body> </page>
As per defined in checkout_index_index.xml file, first we will modify app/code/Magelearn/NewsletterSubscribeAtCheckout/view/frontend/web/template/form/element/email.html file.
We will override vendor/magento/module-checkout/view/frontend/web/template/form/element/email.html and add `newsletter_subscribe` region in that.
Add app/code/Magelearn/NewsletterSubscribeAtCheckout/view/frontend/web/template/form/element/email.html
<!-- ko ifnot: isCustomerLoggedIn() --> <!-- ko foreach: getRegion('before-login-form') --> <!-- ko template: getTemplate() --><!-- /ko --> <!-- /ko --> <form class="form form-login" data-role="email-with-possible-login" data-bind="submit:login" method="post"> <fieldset id="customer-email-fieldset" class="fieldset" data-bind="blockLoader: isLoading"> <div class="field required"> <label class="label" for="customer-email"><span data-bind="i18n: 'Email Address'"></span></label> <div class="control _with-tooltip"> <input class="input-text" type="email" data-bind=" textInput: email, hasFocus: emailFocused, afterRender: emailHasChanged, mageInit: {'mage/trim-input':{}}" name="username" data-validate="{required:true, 'validate-email':true}" id="customer-email" /> <!-- ko template: 'ui/form/element/helper/tooltip' --><!-- /ko --> <span class="note" data-bind="fadeVisible: isPasswordVisible() == false"><!-- ko i18n: 'You can create an account after checkout.'--><!-- /ko --></span> </div> </div> <!-- ko foreach: getRegion('newsletter_subscribe') --> <!-- ko template: getTemplate() --><!-- /ko --> <!--/ko--> <!--Hidden fields --> <fieldset class="fieldset hidden-fields" data-bind="fadeVisible: isPasswordVisible"> <div class="field"> <label class="label" for="customer-password"><span data-bind="i18n: 'Password'"></span></label> <div class="control"> <input class="input-text" data-bind=" attr: { placeholder: $t('Password'), }" type="password" name="password" id="customer-password" data-validate="{required:true}" autocomplete="off"/> <span class="note" data-bind="i18n: 'You already have an account with us. Sign in or continue as guest.'"></span> </div> </div> <!-- ko foreach: getRegion('additional-login-form-fields') --> <!-- ko template: getTemplate() --><!-- /ko --> <!-- /ko --> <div class="actions-toolbar"> <input name="context" type="hidden" value="checkout" /> <div class="primary"> <button type="submit" class="action login primary" data-action="checkout-method-login"><span data-bind="i18n: 'Login'"></span></button> </div> <div class="secondary"> <a class="action remind" data-bind="attr: { href: forgotPasswordUrl }"> <span data-bind="i18n: 'Forgot Your Password?'"></span> </a> </div> </div> </fieldset> <!--Hidden fields --> </fieldset> </form> <!-- /ko --> <!-- ko if: isCustomerLoggedIn() --> <form class="form form-login" data-role="email-with-possible-login" data-bind="submit:login" method="post"> <fieldset id="customer-email-fieldset" class="fieldset" data-bind="blockLoader: isLoading"> <div class="field required"> <label class="label" for="customer-email"> <span data-bind="i18n: 'Email Address'"></span> </label> <div class="control _with-tooltip"> <input class="input-text" type="email" data-bind=" textInput: email, hasFocus: emailFocused" name="username" data-validate="{required:true, 'validate-email':true}" id="customer-email" /> <!-- ko template: 'ui/form/element/helper/tooltip' --><!-- /ko --> <span class="note" data-bind="fadeVisible: isPasswordVisible() == false"><!-- ko i18n: 'You can create an account after checkout.'--><!-- /ko --></span> </div> </div> <!-- ko foreach: getRegion('newsletter_subscribe') --> <!-- ko template: getTemplate() --><!-- /ko --> <!--/ko--> </fieldset> </form> <!-- /ko -->Now we will add app/code/Magelearn/NewsletterSubscribeAtCheckout/view/frontend/web/template/form/element/newsletter_subscribe.html file.
<!-- ko if: enabled --> <div class="field"> <div class="control"> <input class="input-text" type="checkbox" data-bind="textInput: 1, checked: checked" name="newsletter_subscribe" id="newsletter_subscribe" checked="checked" /> <label class="label" for="newsletter_subscribe"> <span data-bind="i18n: label"></span> </label> </div> <!-- ko if: note_enabled --> <span class="note" data-bind="html: note"></span> <!-- /ko --> </div> <!-- /ko -->
Now we will add app/code/Magelearn/NewsletterSubscribeAtCheckout/etc/frontend/di.xml file and modify Magento\Checkout\Block\Onepage\layoutProcessors to define display area for newsletter_subscribe with UI Component fields.
Add app/code/Magelearn/NewsletterSubscribeAtCheckout/etc/frontend/di.xml
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <type name="Magento\Checkout\Block\Onepage"> <arguments> <argument name="layoutProcessors" xsi:type="array"> <item name="newsletterSubscribeConfig" xsi:type="object">Magelearn\NewsletterSubscribeAtCheckout\Model\Config\Source\NewsletterSubscribeLayoutProcessor</item> </argument> </arguments> </type> </config>
Now as per defined in di.xml file add app/code/Magelearn/NewsletterSubscribeAtCheckout/Model/Config/Source/NewsletterSubscribeLayoutProcessor.php file.
<?php namespace Magelearn\NewsletterSubscribeAtCheckout\Model\Config\Source; use Magelearn\NewsletterSubscribeAtCheckout\Helper\Data as Helper; /** * Class NewsletterSubscribeLayoutProcessor * @package Magelearn\NewsletterSubscribeAtCheckout\Model\Config\Source */ class NewsletterSubscribeLayoutProcessor { /** * @var Helper */ private $helper; /** * NewsletterSubscribeLayoutProcessor constructor. * @param Helper $helper */ public function __construct( Helper $helper ) { $this->helper = $helper; } /** * {@inheritdoc} */ public function process($jsLayout) { $enabled = ($this->helper->getConfig('enabled')) ? 1 : 0; $checked = ($this->helper->getConfig('checked')) ? 1 : 0; $label = $this->helper->getConfig('label'); $note_enabled = ($this->helper->getConfig('note_enabled')) ? 1 : 0; $note = $this->helper->getConfig('note'); $config = [ 'customer-email' => [ 'children' => [ 'newsletter_subscribe' => [ 'config' => [ 'enabled' => $enabled, 'checked' => $checked, 'label' => $label, 'note_enabled' => $note_enabled, 'note' => $note ] ] ] ] ]; $updateLayout = [ 'components' => [ 'checkout' => [ 'children' => [ 'steps' => [ 'children' => [ 'billing-step' => [ 'children' => [ 'payment' => [ 'children' => $config ] ] ], 'shipping-step' => [ 'children' => [ 'shippingAddress' => [ 'children' => $config ] ] ] ] ] ] ] ] ]; // Merge updated layout with existing one return array_merge_recursive($jsLayout, $updateLayout); } }
Now we will add our helper file at app/code/Magelearn/NewsletterSubscribeAtCheckout/Helper/Data.php
<?php namespace Magelearn\NewsletterSubscribeAtCheckout\Helper; /** * Class Data * @package Magelearn\NewsletterSubscribeAtCheckout\Helper */ class Data extends \Magento\Framework\App\Helper\AbstractHelper { /** * @var string */ private $tab = 'checkout'; /** * Get module configuration values from core_config_data * * @param $setting * @return mixed */ public function getConfig($setting) { return $this->scopeConfig->getValue( $this->tab . '/magelearn_newslettersubscribeatcheckout/' . $setting, \Magento\Store\Model\ScopeInterface::SCOPE_STORE ); } }
Now we will pass this newsletter_subscribe checkbox value in `extension_attributes` array by overriding vendor/magento/module-checkout/view/frontend/web/js/model/shipping-save-processor/payload-extender.js
For that add app/code/Magelearn/NewsletterSubscribeAtCheckout/view/frontend/requirejs-config.js
var config = { config: { mixins: { 'Magento_Checkout/js/model/shipping-save-processor/payload-extender': { 'Magelearn_NewsletterSubscribeAtCheckout/js/model/shipping-save-processor/payload-extender-mixin': true } } } };
Now add app/code/Magelearn/NewsletterSubscribeAtCheckout/view/frontend/web/js/model/shipping-save-processor/payload-extender-mixin.js
define([ 'jquery', 'underscore', 'mage/utils/wrapper' ], function ( $, _, wrapper ) { 'use strict'; return function (payloadExtender) { return wrapper.wrap(payloadExtender, function (originalPayloadExtender, payload) { var newsletter = $('[name="newsletter_subscribe"]').prop("checked") == true ? 1 : 0; payload = originalPayloadExtender(payload); _.extend(payload.addressInformation,{ extension_attributes: { 'newsletter_subscribe': newsletter } }); return payload }); }; });
Now we will add etc/di.xml file and add plugin for Magento\Checkout\Model\ShippingInformationManagement to save newsletter_subscribe in quote object.
Before that we will add extension_attributes.xml file and define this new field.
Add app/code/Magelearn/NewsletterSubscribeAtCheckout/etc/extension_attributes.xml
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd"> <extension_attributes for="Magento\Checkout\Api\Data\ShippingInformationInterface"> <attribute code="newsletter_subscribe" type="integer"/> </extension_attributes> </config>
Now add app/code/Magelearn/NewsletterSubscribeAtCheckout/etc/di.xml
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <type name="Magento\Checkout\Model\ShippingInformationManagement"> <plugin name="magelearn_newslettersubscriptionatcheckout_shippinginformationmanagement" type="Magelearn\NewsletterSubscribeAtCheckout\Model\Plugin\Checkout\ShippingInformationManagement" sortOrder="10"/> </type> </config>
Now add our Plugin file at app/code/Magelearn/NewsletterSubscribeAtCheckout/Model/Plugin/Checkout/ShippingInformationManagement.php
<?php namespace Magelearn\NewsletterSubscribeAtCheckout\Model\Plugin\Checkout; use Magento\Quote\Model\QuoteRepository as QuoteRepository; use Magento\Checkout\Api\Data\ShippingInformationInterface as ShippingInformationInterface; use Magelearn\NewsletterSubscribeAtCheckout\Helper\Data as Helper; /** * Class ShippingInformationManagement * @package Magelearn\NewsletterSubscribeAtCheckout\Model\Plugin\Checkout */ class ShippingInformationManagement { /** * @var QuoteRepository */ private $quoteRepository; /** * @var ShippingInformationInterface */ private $extensionFactory; /** * @var Helper */ private $helper; /** * ShippingInformationManagement constructor. * @param QuoteRepository $quoteRepository * @param Helper $helper * @param ShippingInformationInterface $extensionFactory */ public function __construct( QuoteRepository $quoteRepository, Helper $helper, ShippingInformationInterface $extensionFactory ) { $this->quoteRepository = $quoteRepository; $this->helper = $helper; $this->extensionFactory = $extensionFactory; } /** * @param \Magento\Checkout\Model\ShippingInformationManagement $subject * @param $cartId * @param \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation */ public function beforeSaveAddressInformation( \Magento\Checkout\Model\ShippingInformationManagement $subject, $cartId, \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation ) { // Check if feature is enabled if ($this->helper->getConfig('enabled')) { $extAttributes = $addressInformation->getExtensionAttributes(); $newsletterSubscribe = $extAttributes->getNewsletterSubscribe() ? 1 : 0; $quote = $this->quoteRepository->getActive($cartId); $quote->setNewsletterSubscribe($newsletterSubscribe); } } }
At last we called event `sales_model_service_quote_submit_success` to successfully add customer email address to newsletter subscriber.
Add app/code/Magelearn/NewsletterSubscribeAtCheckout/etc/events.xml
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd"> <event name="sales_model_service_quote_submit_success"> <observer name="magelearn_newslettersubscribeatcheckout_sales_model_service_quote_submit_success" instance="Magelearn\NewsletterSubscribeAtCheckout\Observer\EventSalesModelServiceQuoteSubmitSuccess" /> </event> </config>
Now add our observer file at app/code/Magelearn/NewsletterSubscribeAtCheckout/Observer/EventSalesModelServiceQuoteSubmitSuccess.php
<?php namespace Magelearn\NewsletterSubscribeAtCheckout\Observer; use Magento\Framework\Event\ObserverInterface; use Magento\Newsletter\Model\Subscriber as Subscriber; use Magelearn\NewsletterSubscribeAtCheckout\Helper\Data as Helper; /** * Class EventSalesModelServiceQuoteSubmitSuccess * @package Magelearn\NewsletterSubscribeAtCheckout\Observer */ class EventSalesModelServiceQuoteSubmitSuccess implements ObserverInterface { /** * @var Subscriber */ private $subscriber; /** * @var Helper */ private $helper; /** * @var \Psr\Log\LoggerInterface */ private $logger; /** * EventSalesModelServiceQuoteSubmitSuccess constructor. * @param Subscriber $subscriber * @param Helper $helper * @param \Psr\Log\LoggerInterface $logger */ public function __construct( Subscriber $subscriber, Helper $helper, \Psr\Log\LoggerInterface $logger ) { $this->subscriber = $subscriber; $this->helper = $helper; $this->logger = $logger; } /** * Subscribe to newsletters if customer checked the checkbox * * @param \Magento\Framework\Event\Observer $observer * @return boolean|$this */ public function execute(\Magento\Framework\Event\Observer $observer) { // Check if feature is disabled if (!$this->helper->getConfig('enabled')) { return; } $quote = $observer->getQuote(); // Get newsletter subscription flag from quote if ($quote->getNewsletterSubscribe()) { try { $email = $quote->getCustomerEmail(); $this->subscriber->subscribe($email); } catch (\Exception $e) { $this->logger->error($e->getMessage()); } } return $this; } }
0 Comments On "Add Newsletter Subscriber at checkout page Magento2"