2

I would like to create a new field for category pages which I can use to override the default H1 on front-end.

Currently if have a category called 'Stuff', my breadcrumb is 'Stuff' and my H1 is 'Stuff'.

What I want is a category called 'Stuff', breadcrumb 'Stuff', and H1 'Magnificent Stuff at Great Prices!'.

So I believe I need a way to do the following:

  1. Create new 'Custom H1' field on Category pages in back-end
  2. If 'Custom H1' field not empty, replace default H1 with 'Custom H1'

I found this article, but it's for Magento 1. I need a M2 solution of this: https://www.designhaven.co.uk/2014/06/create-custom-category-attribute-to-override-category-h1-in-magento/

1 Answer 1

1

This is one way to add custom H1 and an optional H2.

Tested with Magento 2.3.

Note: Replace HeavyDots with your own vendor name if you'd like.

Create new module

Create module under app\code\HeavyDots\SeoAddHeadingsToCategory

Registration

Create app\code\HeavyDots\SeoAddHeadingsToCategory\registration.php with the following:

<?php \Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'HeavyDots_SeoAddHeadingsToCategory',
    __DIR__
);

Create module.xml

Create app\code\HeavyDots\SeoAddHeadingsToCategory\etc\module.xml with:

<?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="HeavyDots_SeoAddHeadingsToCategory" setup_version="1.0.0">
        <sequence></sequence>
    </module>
</config>

Create the script that will add the new fields to DB

Create app\code\HeavyDots\SeoAddHeadingsToCategory\Setup\InstallData.php with:

<?php

// https://devdocs.magento.com/guides/v2.3/ui_comp_guide/howto/add_category_attribute.html

namespace HeavyDots\SeoAddHeadingsToCategory\Setup;

use Magento\Framework\Setup\{
    ModuleContextInterface,
    ModuleDataSetupInterface,
    InstallDataInterface
};

use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;

class InstallData implements InstallDataInterface
{
    private $eavSetupFactory;

    public function __construct(EavSetupFactory $eavSetupFactory) {
        $this->eavSetupFactory = $eavSetupFactory;
    }

    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
        $eavSetup->addAttribute(\Magento\Catalog\Model\Category::ENTITY, 'custom_heading_one', [
            'type' => 'varchar',
            'label' => 'Custom H1',
            'input' => 'text',
            'global' => 'store',
            'group' => 'Search Engine Optimization',
            'required' => false
        ]);
        $eavSetup->addAttribute(\Magento\Catalog\Model\Category::ENTITY, 'custom_heading_two', [
            'type' => 'varchar',
            'label' => 'Custom H2',
            'input' => 'text',
            'global' => 'store',
            'group' => 'Search Engine Optimization',
            'required' => false
        ]);
    }
}

Create xml config so fields will show up on category form

Create app\code\HeavyDots\SeoAddHeadingsToCategory\view\adminhtml\ui_component\category_form.xml with:

<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <fieldset name="search_engine_optimization">
        
        <field name="custom_heading_one" formElement="input">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="source" xsi:type="string">page</item>
                </item>
            </argument>
            <settings>
                <dataType>text</dataType>
                <label translate="true">Custom H1</label>
                <dataScope>custom_heading_one</dataScope>
            </settings>
        </field>
        <field name="custom_heading_two" formElement="input">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="source" xsi:type="string">page</item>
                </item>
            </argument>
            <settings>
                <dataType>text</dataType>
                <label translate="true">Custom H2</label>
                <dataScope>custom_heading_two</dataScope>
            </settings>
        </field>
        
    </fieldset>
</form>

Upload and enable the new module

Push your code to the server and run:

php bin/magento setup:upgrade

Now you should be able to see the fields in category form under

Go to Catalog > Categories > Select and edit one, and open the Search Engine Optimization section.

magento 2 custom category h1 and h2

Now to display it on the frontend category page..

Override the default page title html view

Create app\code\HeavyDots\SeoAddHeadingsToCategory\view\frontend\templates\title.phtml with:

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

$catalogHelperData = $this->helper('Magento\Catalog\Helper\Data');
$categoryObject = $catalogHelperData->getCategory();

if ($categoryObject) {
  $categoryCustomHeadingOne = trim($categoryObject->getCustomHeadingOne());
  $categoryCustomHeadingTwo = trim($categoryObject->getCustomHeadingTwo());
}

/**
 * @var $block \Magento\Theme\Block\Html\Title
 */
$cssClass = $block->getCssClass() ? ' ' . $block->getCssClass() : '';
$titleHtml = '';
$pageHeading=trim($block->getPageHeading());
if (isset($categoryCustomHeadingOne) && !empty($categoryCustomHeadingOne)) {
  $pageHeading = $categoryCustomHeadingOne;
}
if ($pageHeading) {
    $titleHtml = '<span class="base" data-ui-id="page-title-wrapper" '
        . $block->getAddBaseAttribute()
        . '>'
        . $block->escapeHtml($pageHeading)
        . '</span>';
}
?>
<?php if ($titleHtml) : ?>
<div class="page-title-wrapper<?= $block->escapeHtmlAttr($cssClass) ?>">
    <h1 class="page-title"
        <?php if ($block->getId()) : ?> id="<?= $block->escapeHtmlAttr($block->getId()) ?>" <?php endif; ?>
        <?php if ($block->getAddBaseAttributeAria()) : ?>
            aria-labelledby="<?= $block->escapeHtmlAttr($block->getAddBaseAttributeAria()) ?>"
        <?php endif; ?>>
        <?= /* @noEscape */ $titleHtml ?>
    </h1>
    <?php if (isset($categoryCustomHeadingTwo) && !empty($categoryCustomHeadingTwo)): ?>
    <h2 class="page-subtitle">
      <?php echo $block->escapeHtml($categoryCustomHeadingTwo); ?>
    </h2>
    <?php endif; ?>
    <?= $block->getChildHtml() ?>
</div>
<?php endif; ?>

Note: This file has been copied from: vendor\magento\module-theme\view\frontend\templates\html\title.phtml and then modified.

You might want to copy it from there fresh and adapt it, in case your Magento version had changes.

Tell your category page to use the new title view

You must locate the catalog_category_view.xml in your theme file, and if you don't have it, create one.

In my case I had this file already:

app\design\frontend\bs_rubix\bs_rubix1\Magento_Catalog\layout\catalog_category_view.xml

Then edit the file and add the <referenceBlock name="page.main.title"> with the setTemplate to make the block use the template file from your module:

<?xml version="1.0"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
      <!-- title block override start -->
        <referenceBlock name="page.main.title">
            <action method="setTemplate">
                <argument name="template" xsi:type="string">HeavyDots_SeoAddHeadingsToCategory::title.phtml</argument>
            </action>
        </referenceBlock>
      <!-- title block override end -->
    </body>
</page>

Final thoughts

This is one way to accomplish it. Probably there could be better ways if you have more in depth knowledge of Magento customization.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.