Search code examples
javascriptiifeevent-tracking

JS IIFE breaks YouTube Tracking


I'm confused as to why putting my YouTube tracking code into an IIFE stops it working.

My understanding was that IIFEs run instantly, so why is there a difference between including a script with just bare js vs an IFEE?

Here's my plain JS, which works correctlly:

if ( 0 < ga_options.youtube.length ) {
    var tag = document.createElement( 'script' );
    tag.src = '//www.youtube.com/iframe_api';
    var firstScriptTag = document.getElementsByTagName( 'script' )[0];
    firstScriptTag.parentNode.insertBefore( tag, firstScriptTag );

    function onYouTubeIframeAPIReady() {
        scroll_events.register_youtube_videos();
    }
}

However, when I wrap it in an IIFE, like below, it no longer works (no tracking events are fired). I am trying to use an IIFE as part of a restructuring of existing code into self-contained units.

Please could someone explain what I am doing wrong? I have considered scope and tried using var tag and var firstScriptTag outside of the IIFE, but still no success.

gaEventsVideoTracking = (function(){

    window.console.log( "why no youtube tracking?" );
        if ( 0 < ga_options.youtube.length ) {
            tag = document.createElement( 'script' );
            tag.src = '//www.youtube.com/iframe_api';
            firstScriptTag = document.getElementsByTagName( 'script' )[0];
            firstScriptTag.parentNode.insertBefore( tag, firstScriptTag );

            function onYouTubeIframeAPIReady() {
                scroll_events.register_youtube_videos();
            }
        }
})();

Solution

  • The function onYouTubeIframeAPIReady gets called by the script loaded from YouTube's servers.

    Since you are using a function declaration to define it, it is locally scoped to the IIFE. This means it is not a global and thus not available for YouTube's script to call.

    You can explicitly make it a global.

    Add var onYouTubeIframeAPIReady; at line one (outside the IIFE) and then put onYouTubeIframeAPIReady = in front of the function declaration to make it a function expression and assign it to the global variable.