Magento – Magento 2 : How to add additional fields to newsletter

magento2newsletter

I need to display newsletter subscribe form on my CMS page.

Default form has only email field but I need to display with additional fields.

Additional fields like : Gender, First-name, and Last-name.

How I can add these fields in the table, display it on the form, save values in the table.

Best Answer

The below worked fine for me. There is plenty of room for improvement. The form needs styling help and this adds additional first/last name fields to the admin grid rather than merging them with the existing customer name columns. Add this to your CMS page to include the form with the additional fields {{block class="Magento\Newsletter\Block\Subscribe" template="Vendor_Module::subscribe.phtml"}}

Vendor/Module/etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
  <type name="Magento\Newsletter\Model\Subscriber">
    <plugin name="vendor_module_newsletter_model_subscriber" type="Vendor\Module\Plugin\Newsletter\Subscriber"/>
  </type>
</config>

Vendor/Module/etc/module.xml

<?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="Vendor_Module" setup_version="0.0.1">
    <sequence>
      <module name="Magento_Newsletter" />
    </sequence>
  </module>
</config>

Vendor/Module/Plugin/Newsletter/Subscriber.php

<?php

namespace Vendor\Module\Plugin\Newsletter;

use Magento\Framework\App\Request\Http;

class Subscriber {
  protected $request;

  public function __construct(
    Http $request
  ) {
    $this->request = $request;
  }

  public function aroundSubscribe($subject, \Closure $proceed, $email) {
    $result = $proceed($email);
    if ($this->request->isPost() && $this->request->getPost('firstname')) {
      $firstname = $this->request->getPost('firstname');
      $lastname = $this->request->getPost('lastname');
      $gender = $this->request->getPost('gender');

      $subject->setCFirstname($firstname);
      $subject->setCLastname($lastname);
      $subject->setGender($gender);

      try {
        $subject->save();
      }catch (\Exception $e) {
        throw new \Exception($e->getMessage());
      }
    }

    return $result;
  }
}

Vendor/Module/Setup/InstallSchema.php

<?php

namespace Vendor\Module\Setup;

use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\DB\Ddl\Table;

class InstallSchema implements InstallSchemaInterface
{
  public function install(SchemaSetupInterface $setup, ModuleContextInterface $context) {
    $setup->startSetup();

    $table = $setup->getTable('newsletter_subscriber');

    $setup->getConnection()->addColumn(
      $table,
      'c_firstname',
      [
        'type' => Table::TYPE_TEXT,
        'nullable' => true,
        'comment' => 'First Name'
      ]
    );
    $setup->getConnection()->addColumn(
      $table,
      'c_lastname',
      [
        'type' => Table::TYPE_TEXT,
        'nullable' => true,
        'comment' => 'Last Name'
      ]
    );
    $setup->getConnection()->addColumn(
      $table,
      'gender',
      [
        'type' => Table::TYPE_INTEGER,
        'nullable' => true,
        'comment' => 'Gender'
      ]
    );

    $setup->endSetup();
  }
}

If you are using Magento ˆ2.3 you should use this db_schema.xml below instead of InstallSchema.php above.

Vendor/Module/etc/db_schema.xml

<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="newsletter_subscriber" resource="default" engine="innodb" comment="Newsletter Subscriber">
        <column xsi:type="int" name="gender" unsigned="false" nullable="false" comment="Gender"/>
        <column xsi:type="varchar" name="c_firstname" nullable="false" comment="First Name"/>
        <column xsi:type="varchar" name="c_lastname" nullable="false" comment="Last Name"/>
    </table>
</schema>

Vendor/Module/view/adminhtml/layout/newsletter_subscriber_block.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
  <body>
    <referenceBlock name="adminhtml.newslettrer.subscriber.grid.columnSet">
      <block class="Magento\Backend\Block\Widget\Grid\Column" as="custom_firstname">
        <arguments>
          <argument name="header" xsi:type="string" translate="true">First Name</argument>
          <argument name="index" xsi:type="string">c_firstname</argument>
          <argument name="header_css_class" xsi:type="string">col-firstname</argument>
          <argument name="column_css_class" xsi:type="string">ccol-firstname</argument>
        </arguments>
      </block>
      <block class="Magento\Backend\Block\Widget\Grid\Column" as="custom_lastname">
        <arguments>
          <argument name="header" xsi:type="string" translate="true">Last Name</argument>
          <argument name="index" xsi:type="string">c_lastname</argument>
          <argument name="header_css_class" xsi:type="string">col-lastname</argument>
          <argument name="column_css_class" xsi:type="string">ccol-lastname</argument>
        </arguments>
      </block>
      <block class="Magento\Backend\Block\Widget\Grid\Column">
        <arguments>
          <argument name="header" xsi:type="string" translate="true">Gender</argument>
          <argument name="index" xsi:type="string">gender</argument>
          <argument name="type" xsi:type="string">options</argument>
          <argument name="options" xsi:type="array">
            <item name="gender_male" xsi:type="array">
              <item name="value" xsi:type="string">1</item>
              <item name="label" xsi:type="string" translate="true">Male</item>
            </item>
            <item name="gender_female" xsi:type="array">
              <item name="value" xsi:type="string">2</item>
              <item name="label" xsi:type="string" translate="true">Female</item>
            </item>
            <item name="gender_not_specified" xsi:type="array">
              <item name="value" xsi:type="string">3</item>
              <item name="label" xsi:type="string" translate="true">Not Specified</item>
            </item>
          </argument>
          <argument name="header_css_class" xsi:type="string">col-gender</argument>
          <argument name="column_css_class" xsi:type="string">ccol-gender</argument>
        </arguments>
      </block>
    </referenceBlock>
  </body>
</page>

Vendor/Module/view/frontend/templates/subscribe.phtml

<?php
/**
 * Copyright © 2016 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */

// @codingStandardsIgnoreFile

/** @var \Magento\Newsletter\Block\Subscribe $block */

?>
<div class="block newsletter">
  <div class="title"><strong><?php /* @escapeNotVerified */ echo __('Newsletter') ?></strong></div>
  <div class="content">
    <form class="form subscribe"
          novalidate
          action="<?php echo $block->escapeUrl($block->getFormActionUrl()) ?>"
          method="post"
          data-mage-init='{"validation": {"errorClass": "mage-error"}}'
          id="newsletter-validate-detail">
      <div class="field firstname">
        <label class="label" for="firstname"><span><?php echo $block->escapeHtml(__('First Name')) ?></span></label>
        <div class="control">
          <input name="firstname" type="text" id="firstname"
                 placeholder="<?php echo $block->escapeHtmlAttr(__('First Name')) ?>"
                 data-validate="{required:true}"/>
        </div>
      </div>
      <div class="field lastname">
        <label class="label" for="lastname"><span><?php echo $block->escapeHtml(__('Last Name')) ?></span></label>
        <div class="control">
          <input name="lastname" type="text" id="lastname"
                 placeholder="<?php echo $block->escapeHtmlAttr(__('Last Name')) ?>"
                 data-validate="{required:true}"/>
        </div>
      </div>
      <?php $_gender = $block->getLayout()->createBlock('Magento\Customer\Block\Widget\Gender') ?>
      <?php echo $_gender->toHtml() ?>
      <div class="field newsletter">
        <label class="label" for="newsletter"><span><?php echo $block->escapeHtml(__('Sign Up for Our Newsletter:')) ?></span></label>
        <div class="control">
          <input name="email" type="email" id="newsletter"
                 placeholder="<?php echo $block->escapeHtmlAttr(__('Enter your email address')) ?>"
                 data-validate="{required:true, 'validate-email':true}"/>
        </div>
      </div>
      <div class="actions">
        <button class="action subscribe primary" title="<?php echo $block->escapeHtmlAttr(__('Subscribe')) ?>" type="submit">
          <span><?php echo $block->escapeHtml(__('Subscribe')) ?></span>
        </button>
      </div>
    </form>
  </div>
</div>

Vendor/Module/registration.php please make proper file all

<?php

\Magento\Framework\Component\ComponentRegistrar::register(
  \Magento\Framework\Component\ComponentRegistrar::MODULE,
  'Vendor_Module',
  __DIR__
);
Related Topic