International SEO - Magento SEO - On Page SEO - Performance Analysis - Tag Manager

How To: Do Dynamic Product Meta Data in Magento Using GTM

By on 13th April 2021

Reading Time: 14 minutes

  • LinkedIn
  • Twitter
VW Camper Van

I have been working with Heritage Parts Centre who are a global supplier of spare parts and accessories for classic VW and Porsche cars.  Their website stores operate in the UK, US, Australia, Germany, Spain, and Italy, as well as an EU store for all other European countries.  They have over 60,000 parts and accessories across over 40 models – resulting in an XML sitemap containing 250k pages.

In summary: It is a big site.

I came on board following a migration (following a rebrand) from Magento 1 to Magento 2 where traffic had been lost.  Following the initial audit, the priority was to resolve all the redirects from the old site to ensure that they used 301 redirects, and that accurate mappings were in place across 57k old URLs, matching up product IDs, categories, and regions.

Following this, several opportunities were identified to enhance on page optimisation across the site – one of which being product page optimisation.

It is possible to set up title tag and meta description templates within M2 admin for product meta data such as adding suffixes and prefixes, but any truly bespoke formatting requires developer implementation.  This in turn tends to take some time to get implemented as a ticket is raised, placed in a queue and you then you just wait.  Very often, developers have much bigger tasks to get stuck into functionality wise than tweaking meta data. 

Whilst not a criticism of developers, this is a common frustration for SEOs, and it is not a particularly agile way to go about meta data optimisation, because you may want to test/tweak/refine your meta data following regular analysis, and implementation via the database across 250k pages can be a bit on the server intensive side of things.

For me, this is where Google Tag Manager comes into its own – it makes it very easy to amend meta data at scale and quickly.   Using custom variables, triggers, tags, and custom HTML & JavaScript, it is possible to make every product URL’s meta data on the site unique and, more importantly in this case, fully translated.

With that in mind, we set about optimising all the product pages across all regions.

How To Implement Alternate Language Tags in Magento

Whilst this can, in some instances, be carried out via GTM in this case it wasn’t necessary as the site uses the Alternate Language Tags plugin by Magmodules – and very good it is too:

Alternate Language Tags plugin by Magmodules

The Pre-Optimisation Meta Data

The following examples of titles and descriptions are for a product not on special offer, and one which is.  Default regional suffixes had already been set up for each region, but as with many ecommerce stores, the default meta description was unoptimized and in some cases included HTML due to being pulled in from the page content.

Product Not On Offer – Fuel Tank

https://www.heritagepartscentre.com/uk/170201075j-fuel-tank.html

RegionTitleDescription
AUFuel Tank | Heritage Parts Centre AUFuel tank<br>
DEKraftstofftank | Heritage Parts Centre DEWir haben unsere Marke umbenannt, liefern aber immer noch eine große Auswahl an Teilen und Zubehör für klassische VW- und Porsche-Modelle
ESDeposito de combustible | Heritage Parts Centre ESHemos cambiado de marca, pero aún almacenamos y suministramos una amplia gama de piezas y accesorios para los modelos clásicos de VW y Porsche.
EUFuel Tank | Heritage Parts Centre EUFuel tank<br>
ITSerbatoio carburante | Heritage Parts Centre ITAbbiamo rinominato ma ancora immagazziniamo e forniamo una vasta gamma di parti e accessori per i modelli classici VW e Porsche
UKFuel Tank | Heritage Parts Centre UKFuel tank<br>
USFuel Tank | Heritage Parts Center USFuel tank<br>

Product On offer – Door Hinge Kit for Left or Right

https://www.heritagepartscentre.com/uk/90153103120-door-hinge-kit-for-left-or-right.html

RegionTitleDescription
AUDoor Hinge Kit for Left or Right | Heritage Parts Centre AU<p>Door hinge kit for left or right.</p><p><br>Set includes both hinges for one door, does not include mounting bolts.</p>
DETürscharnier-Set, ohne Schrauben/Bolzen, pro Tür | Heritage Parts Centre DETürscharnierset zur Montage an der linken oder rechten Tür.
Der Satz enthält alle Scharniere mit Ausnahme der Bolzen zum Aufhängen der Tür.</div>
ESKit bisagra puerta. Para 1 puerta | Heritage Parts Centre ES<p>Kit bisagra puerta para lado derecho o izquierdo.</p><p><br></p><p>El kit incluye todas los herrajes excepto los tornillos para colgar la puerta.<br></p><p><br></p><p><br></p>
EUDoor Hinge Kit for Left or Right | Heritage Parts Centre EU<p>Door hinge kit for left or right. Set includes both hinges for one door, does not include mounting bolts.</p>
ITKit cerniere porta per guida a dx | Heritage Parts Centre ITAbbiamo rinominato ma ancora immagazziniamo e forniamo una vasta gamma di parti e accessori per i modelli classici VW e Porsche
UKDoor Hinge Kit for Left or Right | Heritage Parts Centre UK<p>Door hinge kit for left or right. Set includes both hinges for one door, does not include mounting bolts.</p>
USDoor Hinge Kit Excluding bolts to Hang One Door | Heritage Parts Center US<p>Door hinge kit to fit the left or right door.<br>Set includes all hinges excluding bolts to hang one door.</P>

Product Meta Data Requirements

After reviewing existing product pages, the following list of requirements was drawn up.

  • Title tags to be unique across all regions
  • Meta data to include the original and a formatted version of the product SKU as users tend to search both with and without hyphens and slashes
  • Descriptions to be bespoke in terms of:
    • Fully translated, including differing sentence structure per language
    • Specify whether the product is on offer or not
    • Include the relevant USP for each region

Using Custom Variables to Populate Data

From this, it was determined we would need the following variables to construct the meta data:

  • Store region
  • Product name
  • Product SKU
  • Formatted product SKU
  • Current price
  • Old & new price if on offer
  • USP unique to store region

These were then set as follows:

How To Configure Store Region

Whilst the regions are already in the title tags, as we are creating new titles, and for other purposes, we wanted to set a custom variable that captured the region.  As each store is within a subfolder named for that region – e.g. /uk/ – we can do this by extracting it from the URL.

To do this we configure a URL of type “Custom JavaScript” that gets the current URL and splits it into an array via the slashes – and we know the region will always be in the 3rd array element:

Custom JavaScript variable

So on this URL:

https://www.heritagepartscentre.com/uk/170201075j-fuel-tank.html

the region is set as follows:

Store Region

Whilst we could just use a JavaScript function to convert this to uppercase, we used a lookup table based up the variable to set the region, as this will give us greater flexibility further down the line if we wish to amend the region name in the title tag – e.g. USA instead of US

VLOOKUP Title Tag Region

Which is then set as follows on the above URL:

Title Tag Region

This can now be used in our tags and triggers by referring to {{Title Tag Region}}

How To Configure Product Name

All the product data we need is within the page content, so we can use CSS selectors to pull in each variable:

page title wrapper

So in this case, we grab the contents of .page-title .base

DOM Element variable config

Which we can refer to using {{Product Name}}:

Product Name

How To Configure Product SKU

Like above, the SKU is also in a uniquely named div:

Product SKU HTML

So, the variable is set as follows:

Product SKU Variable

Which we can refer to using {{Product SKU}}

Product SKU

How To Configure A Formatted Product SKU

By default, the SKU contains / and – for example:

170-201-075/J

Some users will search with these characters, some without – so we wanted to include both.  By using a custom JavaScript variable, we can pass the SKU then remove the / and – and return the formatted SKU.

I apologise for what looks like horribly inefficient code, but the replace function wasn’t working how I anticipated, so I just hacked this together to remove up to 4 instances of each character:

As you can see, it passes in the previously captured SKU, works its “magic”, then sends back a nicely formatted SKU:

Code To Format Product SKU

Again, sorry about that code, but anyway, we can now refer to this using {{Product SKU Formatted}}

Formatted Product SKU

How To Configure Current Price

If the product is not on offer, the price can be found here:

Product Price HTML

Again, we use a CSS selector to grab this value:

Product Price Variable

And this is called using {{Product Price}}

Product Price

How To Check If On Offer And Configure Old & New Price

If a product is on offer, the prices appear as follows:

Product On Offer

These appear in the classes .old-price and .special-price

Product Offer HTML

So, we set them accordingly:

Product Old Price
Product New Price

As the .special-price only appears on product pages which are on offer, we can set a variable called “Product On Offer” of type “Element Visibility” which is set to true or false depending on if this element is on the page:

Product On Offer Variable

We then have 3 more potential variables we can use:

{{Product On Offer}}
{{Product Old Price}}
{{Product New Price}}

If the product is not on offer, we see:

Product Not On Offer

Whereas if it is, these are populated accordingly:

Product On Offer

(I am not sure why they appear as “null” and “false”, when they should be “false” and “true” – I must look into this)

How To Configure USP Unique To Store Region

We want to include a USP within the meta to encourage the click through from the SERPs.  The delivery price is different in each region whilst DE, IT and ES need to be translated.  As we already have the region as a variable, the USP can be set via a look up table taking {{Store Region}} as the input:

Product USP Variable

This is called using {{Product USP}}

Product USP

Summary Of Configured Variables

For each product we now have a set of variables we can use to create our unique meta data:

https://www.heritagepartscentre.com/uk/170201075j-fuel-tank.html

Fuel Tank Variables

https://www.heritagepartscentre.com/es/90153103120-kit-bisagra-puerta-para-1-puerta.html

Door Variables

How To Create A Product Page Trigger

Before we create our custom tag, we need a trigger that will allow us to identify if we are on a product page, or not.

There are several variables available to us, so we chose {{Product SKU}} – if this is not null, we know we are on a product page, so set up the trigger accordingly:

Product Page Trigger

How To Create Custom HTML Tag For Dynamic Meta Data

Finally, on to the good stuff.  

For this we use a custom HTML tag that will contain JavaScript and utilise jQuery to manipulate the key elements within the page.

First, we need to create the variables we will use and set these according to the custom variables set up previously:

var p_name = "{{Product Name}}";
var p_sku = "{{Product SKU}}";
var p_sku_formatted = "{{Product SKU Formatted}}";
var p_region = "{{Title Tag Region}}";
var p_on_offer = "{{Product On Offer}}";
var p_price = "{{Product Price}}";
var p_old_price = "{{Product Old Price}}";
var p_new_price = "{{Product New Price}}";
var p_product_usp = "{{Product USP}}"; 

To set the title tag, we want to append the product name, formatted SKU and insert the brand followed by the region:

var p_title = p_name + ": " + p_sku_formatted + " | Heritage Parts Centre " + p_region;

We then use jquery to remove the existing title tag, and create a new one populated with the text above:

jQuery('title').remove();
var p_title_tag = document.createElement('title');
p_title_tag.text = p_title;
jQuery('head').append(p_title_tag);

Whilst I prefer the syntax of JQuery, the following more efficient code wil also work and supports sites that don’t utilise JQeuery:

document.title = p_title;

For the meta description, we have differing formats depending on whether the product is on offer, and then different languages depending on the region.   We will translate for DE, IT and ES, whilst AU, US, EU and UK will all use the same text.

The format we decided on in English was:

Buy the product_name (product_SKU) online for product_price.  Product_usp

e.g.

Buy the Fuel Tank (170-201-075/J) online for £236.95.  Free delivery on orders over £50, express next day delivery available.

If the product is on offer, the wording is as follows:

Buy the product_name (product_SKU) online.  Was old_price, now new_price.  Product_usp

e.g.

Buy the Door Hinge Kit for Left or Right (901-531-031-20) online. Was £102.95, now £92.95.  Free delivery on orders over £50, express next day delivery available.

We also have the flexibility to change the structure of the sentences depending on the language.

To do this, we used the following code which utilises and if statement to determine if the product is on offer, and then switch statements to set to description according to the region – DE, ES and IT, or default English for AU, EU, UK and US – if we want to have specific descritpions for any English regions at any point, we just add in a further case:

if (p_on_offer == "null")
{
	switch(p_region) 
	{
		case "DE":
			var p_desc = "Bestellen Sie " + p_name + " (" + p_sku + ") auf unserer Webseite für " + p_price + ".  " + p_product_usp;
			break;
		
		case "ES":
			var p_desc = p_name + " (" + p_sku + ") disponible en línea por " + p_price + ".  " + p_product_usp;
			break;
		
		case "IT":
			var p_desc = "Acquista " + p_name + " (" + p_sku + ") online per " + p_price + ".  " + p_product_usp;
			break;
		
		default:
			var p_desc = "Buy the " + p_name + " (" + p_sku + ") online for " + p_price + ".  " + p_product_usp;
	}
}
else
{
	switch(p_region) 
	{
		case "DE":
			var p_desc = "Bestellen Sie " + p_name + " (" + p_sku + ") auf unserer Webseite.  Regulärer Preis " + p_old_price + " - Sonderpreis " + p_new_price + ".  " + p_product_usp;
			break;
		
		case "ES":
			var p_desc = p_name + " (" + p_sku + ") disponible en línea.  Precio inicial " + p_old_price + " - Precio rebajado " + p_new_price + ".  " + p_product_usp;
			break;
		
		case "IT":
			var p_desc = "Acquista " + p_name + " (" + p_sku + ") online.  Prezzo originale " + p_old_price + " - Prezzo scontato " + p_new_price + ".  " + p_product_usp;
			break;
		
		default:
			var p_desc = "Buy the " + p_name + " (" + p_sku + ") online.  Was " + p_old_price + " - Now " + p_new_price + ".  " + p_product_usp;
	}
}

And add this to the page as follows:

jQuery('meta[name="description"]').remove();
var p_meta_desc = document.createElement('meta');
p_meta_desc.name = 'description';
p_meta_desc.content = p_desc;
jQuery('head').append(p_meta_desc);

Or, again, without JQuery go with:

document.getElementsByTagName('meta')["description"].content = p_desc;

And that is it – the Custom HTML tag is set up containing the code above to be fired by the product page trigger:

Dynamic Product Meta Data Tag

And the good news is, the dynamically generated code is crawled, parsed and indexed by Google.  Bing doesn’t.  But so what.

We can see this using the site query operator to look for the SKU:

Site Operator: Door
Site Operator: Fuel Tank

How To Analyse Product Page Performance

The amends had a significant impact on the organic visibility and traffic generated by the product pages on the site.

It’s easy to just say that, but, in the name of a comprehensive case study, I’m going to prove it.

Whilst one of my favourite SEO tools, the performance data in Google Search Console is limited to 1000 pages at a time, however, there are ways of getting a more definitive overview of your site’s search data.

For those with budget, I highly recommend Ryte which has a comprehensive Search Success module which allows you to see ALL your site’s URL search data within any given time frame:

ryte screenshot

Or, if on a budget and you want the same thing for free, Alyeda Solis has created a Google Data Studio Dashboard that basically does the same thing, that being, the ability to download all your search data.

Once we had this data month by month, we then used Screaming Frog SEO Spider and it’s custom extraction tool to crawl the URLs and identify which were products via the SKU code being in place on the page.

To do this, right click on the SKU in the web page and select “Inspect”:

inspect tool

Then, from within the code, select the element containing the text you want to extract and right click then select “Copy -> Copy Selector” to get the CSS path:

inspect html

Which gives you the following:

#maincontent > div.columns > div > div.full-width.top.wrapper > div.product-info-main > div.product.attribute.sku > div

Within Screaming Frog, we can then paste in all the URLs into list mode after we’ve set “Configuration -> Custom -> Extraction” and set this to your CSS path:

custom extraction

This will then crawl all your URLs and where the SKU is in place, this will be flagged in the custom extractor field:

extracted data

If Screaming Frog isn’t your thing, you can also use Sitebulb for website content extraction.

Either way, export the data, put the original search console export data in one excel tab, your crawl data in another, use a VLOOKUP to match and flag the product URLs with an SKU in place, which you then filter to obtain just product page data:

GSC Data

Optimisation work began on the site on October covering fundmental tech SEO actions such as crawl rate optimisation and breadcrumb schema optimisation – this had a positive impact, but more so on the category landing pages across the site. The product meta optimisation described above was implemented in December, and as you can see, it did good in terms of unique product pages and keyword generating impressions, clicks and click through rate:

OCTNOVDECJANFEBMAR
Unique Pages14,44815,41416,03321,75032,99634,113
Unique Keywords34,89839,00835,96935,07350,42849,572
Total Impressions224,703239,396241,611218,841324,858354,877
Total Clicks2,5802,9762,7683,0283,5855,150
Click Through Rate1.15%1.24%1.14%1.38%1.10%1.45%

The same data, but in a graph:

Month On Month Product Page Performance

Whilst Ryte allows us to see new keywords this year to date which includes a lot of product part IDs due to them now being in the title tag and meta description:

product ID data

The End Result

Enhanced Visibilty = More Long Tail Organic Traffic = More Reveune = Happy Client

But don’t just take my word for it:


“Heritage Parts Centre started working with Dave at Organic Digital mid-2020, presenting to him a number of challenges following a website migration earlier in the year. What Dave provided saw a number of quick wins (that quickly and drastically stabilised our organic traffic), and subsequently worked through some more strategic technical SEO optimisations that has seen a tremendous improvement in our SEO performance. It has been refreshing to work with Dave who have been genuinely excited by the unique challenges that our market presents, and look forward to continue our work with him. His direct, professional, pragmatic and creative problem solving and optimisation methods continue to make a positive difference to our business, and I recommend him highly.”

Rob Tickner Rob Tickner
Head of Technology


“Have been working with Dave for 6 months now and very impressed with the technical SEO work that he has carried out particularly around GTM. His reports and roadmap are clear and concise and the work is returning good results.”

Barney Dines Barney Dines
Managing Director

Get In Touch

Fill in the form below if you want to enhance your website's organic visibility