Uncaught ReferenceError: toPushToDatalayer is not defined

Hi,

I’ve been working on trying to install Enhanced Ecommerce. I have a script (below) that gets an error Uncaught ReferenceError: toPushToDatalayer is not defined

Here is the script:

(function($){
	$(attachClickListener); // Attach the event listener when the page loads.

	function getProductIdFromListItem(listItem) {
		var parsableElements = $(listItem).find('img[id^="product-collection-image-"], span[id^="product-price-"]'); // Either of these should have a product ID in the ID attribute.
		
		var productId = $(parsableElements.get(0))
			.attr('id')
			.split('-')
			.pop();

		console.log("Determined product ID for listItem", listItem, 'is', productId);

		return productId;
	}

	function getProductDataById(productId) {
-- HERE IS WHERE THE ERROR HAPPENS -->		var productList = toPushToDatalayer['ecommerce']['impressions'];
		// ToDo: Put these in a keyed object so we don't have to loop through to find the product we want.
		for(var i=0; i<productList.length; i++) {
			var product = productList[i];
			if( product['magento_id'] == productId ) {
				return product;
			}
		}

		throw "Product with ID " + productId + " could not be found in the dataLayer data on this page.";
	}

	function pushDatalayerProductClick(productData, redirectUrl) {
		var dataLayerData = {
			'event': 'productClick',
			'ecommerce': {
				'click': {
					'actionField': {
						// ToDo: populate this field with the category name.
						'list': 'Search Results' // Optional list property.
					},
					'products': [productData]
				}
			}
		}

		if( redirectUrl ) {
			dataLayerData['eventCallback'] = function() {
				document.location = redirectUrl
			}
		}

		dataLayer.push(dataLayerData);
	}

	function onProductListItemClick(e){
		var listItem = $(this).closest('li');
		var productId = getProductIdFromListItem(listItem);

		var productData = getProductDataById(productId);

		var redirectUrl = $(this).attr('href');

		if( redirectUrl ) {
			if( e.ctrlKey || e.metaKey ) {
				redirectUrl = false; // This is a ctrl+click to open in a new tab. We don't want to change the current window location.
			} else {
				e.preventDefault(); // Must postpone the navigation and let Datalayer handle it.
			}
		}

		pushDatalayerProductClick(productData, redirectUrl);

		console.log("product Clickthrough data:", productData);
	}

	function attachClickListener(){
		if( document.documentElement.innerHTML.indexOf('www.googletagmanager.com') === -1 ) {
			return; // If there is no GTM on the page, don't do any of this stuff.
			// Unlike the rest of the GTM Datalayer code, this javascript will stop the product link click event!
		}
		
		$('.products-grid').on('click', 'li.item a', onProductListItemClick);	
	}
}(jQuery));

I think this error is stopping it from working. I’ve tried loading the script in different orders but nothing has worked.

Will someone have a look and see what is the matter?

Thanks!

Not sure but I would suggest trying to access toPushToDatalayer through window.toPushToDatalayer. Try console.log(window.toPushToDatalayer) and see if the console gives you anything.

Basically the wrapping bit of code :

(function($){
//code...
}(jQuery));

is creating its own scope therefore you probably lost the global scope and have to access it through window like I suggested above.

Cheers

I added window.toPushToDatalayer like this:

var productList = window.toPushToDatalayer[‘ecommerce’][‘impressions’];

When I hold down the ctrl key and click on a product I now get this error:

Uncaught TypeError: Cannot read property 'ecommerce' of undefined
    at getProductDataById (product_grid.js:18)
    at HTMLAnchorElement.onProductListItemClick (product_grid.js:57)
    at HTMLUListElement.dispatch (prototype.js:1)
    at HTMLUListElement.y.handle (prototype.js:1)

I tried removing:

(function($){
//code...
}(jQuery));

from the script and then I don’t get any errors at all but I don’t see the data layer in the page source.

Is it suppose to add the data layer to the page?

This was all that was on the page <script>dataLayer = [];</script> I changed it to <script>window.dataLayer=window.dataLayer||[];</script> after reading an article that it was better.

I’m not very good at using the console.

Thanks

How about adding window aswell to:

 dataLayer.push(dataLayerData);

I wouldn’t think you’d need this:

window.dataLayer=window.dataLayer||[];

okay, I’ll give it a try.

1 Like

I get this error:

Uncaught ReferenceError: dataLayerData is not defined

when I add that code with:

window.toPushToDatalayer

or

toPushToDatalayer

Hang on I might have messed up.

window.dataLayer.push(dataLayerData);

Okay it’s still a no-go : )

I’ve tried every possible combination I can think of.

It still says Uncaught TypeError: Cannot read property ‘ecommerce’ of undefined

okay sorry I got distracted with work :stuck_out_tongue: and might have overlooked something.

try just changing the following from your original code…
from:

dataLayer.push(dataLayerData);

to :

window.dataLayer.push(dataLayerData);

Leave everything else the same as your original code

No problem.

I now get the same error again. Uncaught ReferenceError: toPushToDatalayer is not defined

Here is how I tried:

(function($){
	$(attachClickListener); // Attach the event listener when the page loads.

	function getProductIdFromListItem(listItem) {
		var parsableElements = $(listItem).find('img[id^="product-collection-image-"], span[id^="product-price-"]'); // Either of these should have a product ID in the ID attribute.
		
		var productId = $(parsableElements.get(0))
			.attr('id')
			.split('-')
			.pop();

		console.log("Determined product ID for listItem", listItem, 'is', productId);

		return productId;
	}

	function getProductDataById(productId) {
		var productList = toPushToDatalayer['ecommerce']['impressions'];
		// ToDo: Put these in a keyed object so we don't have to loop through to find the product we want.
		for(var i=0; i<productList.length; i++) {
			var product = productList[i];
			if( product['magento_id'] == productId ) {
				return product;
			}
		}

		throw "Product with ID " + productId + " could not be found in the dataLayer data on this page.";
	}

	function pushDatalayerProductClick(productData, redirectUrl) {
		var dataLayerData = {
			'event': 'productClick',
			'ecommerce': {
				'click': {
					'actionField': {
						// ToDo: populate this field with the category name.
						'list': 'Search Results' // Optional list property.
					},
					'products': [productData]
				}
			}
		}

		if( redirectUrl ) {
			dataLayerData['eventCallback'] = function() {
				document.location = redirectUrl
			}
		}

		window.dataLayer.push(dataLayerData);
	}

	function onProductListItemClick(e){
		var listItem = $(this).closest('li');
		var productId = getProductIdFromListItem(listItem);

		var productData = getProductDataById(productId);

		var redirectUrl = $(this).attr('href');

		if( redirectUrl ) {
			if( e.ctrlKey || e.metaKey ) {
				redirectUrl = false; // This is a ctrl+click to open in a new tab. We don't want to change the current window location.
			} else {
				e.preventDefault(); // Must postpone the navigation and let Datalayer handle it.
			}
		}

		pushDatalayerProductClick(productData, redirectUrl);

		console.log("product Clickthrough data:", productData);
	}

	function attachClickListener(){
		if( document.documentElement.innerHTML.indexOf('www.googletagmanager.com') === -1 ) {
			return; // If there is no GTM on the page, don't do any of this stuff.
			// Unlike the rest of the GTM Datalayer code, this javascript will stop the product link click event!
		}
		
		$('.products-grid').on('click', 'li.item a', onProductListItemClick);	
	}
}(jQuery));

On the page I tried both ways like this:

<script>window.dataLayer = window.dataLayer || [];</script>

<script>dataLayer = [];</script>

both ways give the same error when I click ctrl while clicking on a product.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.