Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lazysizes doesn't work with native Google Tag Manager/Analytics video tracking #810

Closed
WidgetsBurritos opened this issue Jun 30, 2020 · 4 comments

Comments

@WidgetsBurritos
Copy link

WidgetsBurritos commented Jun 30, 2020

Describe the bug
The lazysizes library doesn't work with native Google Tag Manager/Analytics youtube video tracking.

See https://www.analyticsmania.com/post/youtube-tracking-google-tag-manager-solved/ for some more information about some of the requirements.

The issue essentially comes down to this:

To make sure that you’re dealing with this issue, you should inspect the video player, locate the iframe element and check whether the src attribute (see the screenshot below) contains the www.youtube.com URL.

If not, then the Youtube video tracking will not work.

The reason it doesnt work is due to this code:
https://github.com/aFarkas/lazysizes/blob/gh-pages/lazysizes.js#L443-L449

		var changeIframeSrc = function(elem, src){
			try {
				elem.contentWindow.location.replace(src);
			} catch(e){
				elem.src = src;
			}
		};

Whenever the try succeeds, which happens in most modern browsers, it changes the history destination of the iframe, but doesn't actually set the src attribute.

To Reproduce
I don't presently have a URL where you can preview the behavior, as it's a combination of lazysizes/GA/GTM.

Steps to reproduce the behavior:

  1. Install Google Tag Manager/Google Analytics
  2. Add the youtube iframe API: <script src="https://www.youtube.com/iframe_api">
  3. Install lazysizes
  4. Add a youtube video that loads without lazysizes
  5. Add another youtube video that loads with lazysizes
  6. Setup a tag in GTM that uses native video tracking
  7. Load GTM preview mode
  8. Start the video that doesn't use lazysizes (you should see a YouTube tag fire)
  9. Start the video that uses lazysizes (you don't see a YouTube tag fire)

What is the expected behavior
Google Analytics should be able to track videos through the default Google Tag Manager tags.

What happened instead
The tag never triggered because the src attribute was missing`.

In what environment (browser/device etc.) does this bug happen/not happen:
Any browser that uses elem.contentWindow.location.replace(src); as described above.

Specifically, I've seen it on Chrome 83 on MacOS.


I fixed it on my end by modifying changeIframeSrc to always use elem.src. However, this doesn't feel like the best long-term solution (especially since I'm essentially opting out of future library updates this way).

In my mind, it seems like it'd be helpful to let people opt-out of using elem.contentWindow.location.replace via some sort of configuration setting.


  • Updated 6/30/2020 to correct an incorrect statement. (i.e. s/history/destination/)
  • Updated 6/30/2020 added a couple extra items to the steps to reproduce, to avoid ambiguity.
@aFarkas
Copy link
Owner

aFarkas commented Jul 5, 2020

@WidgetsBurritos
The reason why I choose to do it like this is because using src attribute as you suggest will create a new history entry for Firefox users.

location.replace doesn't have this problem.

However having the possibility to configure this is a good idea. How would call this option? It would also make sense to change this option on an element basis using attribute modification.

Beside changing the src attribute you could also clone the iframe and replace the old iframe with that. This does change the src without adding a new history entry to the element.

Note: You can already now fully modify what lazysizes does without changing the source itself:

// example 1: use `data-iframe-src` instead of `data-src`
window.addEventListener('lazybeforeunveil', ({target}) => {
   if(target.dataset.iframeSrc) {
       target.src = target.dataset.iframeSrc;
   }
});

// or example 2: reimplement the wanted behavior and stop lazysizes from doing it
window.addEventListener('lazybeforeunveil', (e) => {
	let src;
	const target = {e};

	if (target.matches('iframe') && (src = target.dataset.src)) {
		e.preventDefault();

		target.src = src;
		target.classList.add('lazyloaded');
		target.classList.remove('lazyload');

	}
});

Another way would be to use the video plugin.

@WidgetsBurritos
Copy link
Author

WidgetsBurritos commented Jul 6, 2020

@aFarkas,

Thanks for the heads up on the event listeners. I'll evaluate those methods. Those seems a bit more desirable than what I'm doing now.

If you still are interested in making that feature configurable, I think maybe you could do something like iframeLoadMode, similar to how you do loadMode:

lazySizesConfig.iframeLoadMode (default: 0): The iframeLoadMode can be used to determine how iframes are lazyloaded. Possible values are 0 = Use location.replace(), 1 = Change src attribute. 0 is recommended for most users unless external dependencies require the presence of a src attribute (e.g. native video tracking in Google Tag Manager/Analytics).

@acmoles
Copy link

acmoles commented Mar 12, 2021

This was a useful change - thanks!

@levipadre
Copy link

Hi,
I does work now, BUT if the iframe has id it doesn't. GTM generates an id for the iframe when it's tracking and if you already define one, nothing happens.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants