55

I work with an advertising company, where we tag certain pages to track activity. A client of mine wants to fire off a javascript tag to track activity AFTER the page has finished loading entirely (to prevent the page content from loading slowly due to slow tag load times).

An example tag that should load AFTER the page has fully loaded is:

<script>document.write('<s'+'cript language="JavaScript" src="http://jact.atdmt.com/jaction/JavaScriptTest"></s'+'cript>')</script>

I was looking at some stackoverflow threads and I came across the below implementation which I think will work:

window.onload = function(){
  <script language="JavaScript" src="http://jact.atdmt.com/jaction/JavaScriptTest"></script>
};

I tested this on my own webpage and I did get the tag to fire off, but I'm wondering if there are any alternate or more robust methods, ideally using jquery of some kind.

Below is a sample implementation that the client tried, but it seems to break their page:

<script>
jQuery(window).load(function () {$('<script language="JavaScript" src="http://jact.atdmt.com/jaction/JavaScriptTest"></script>').insertAfter('#div_name');});
</script>

I haven't done JQuery in a while and was hoping I could get some input from other members here. Is there any other way I can call the above script after page load using JQuery?

Thanks,

Kamui
  • 719
  • 1
  • 9
  • 16
  • If you're using jQuery you can just do `$.getScript("urlHere")` - but if you're doing ads I'd reconsider jQuery - it's 80kb of code which is _a lot_ for an ad. – Benjamin Gruenbaum Nov 01 '13 at 23:27
  • It's more like a 1x1 pixel which may call additional scripts. $.getScript will call the URL after all of the content on the page loads? – Kamui Nov 01 '13 at 23:32
  • You can also add your script at the end of the page. – Sylhare Feb 07 '20 at 15:33
  • Note that namespaced functions will not work. For example, `&callback=ns.init_gm` or `&callback=ns%2Einit_gm` will trigger an invalid function error. `&callback=google_maps_callback_cannot_use_namespaced_function` will not trigger an error. – OXiGEN Feb 20 '23 at 07:02

8 Answers8

109

So, there's no way that this works:

window.onload = function(){
  <script language="JavaScript" src="http://jact.atdmt.com/jaction/JavaScriptTest"></script>
};

You can't freely drop HTML into the middle of javascript.


If you have jQuery, you can just use:

$.getScript("http://jact.atdmt.com/jaction/JavaScriptTest")

whenever you want. If you want to make sure the document has finished loading, you can do this:

$(document).ready(function() {
    $.getScript("http://jact.atdmt.com/jaction/JavaScriptTest");
});

In plain javascript, you can load a script dynamically at any time you want to like this:

var tag = document.createElement("script");
tag.src = "http://jact.atdmt.com/jaction/JavaScriptTest";
document.getElementsByTagName("head")[0].appendChild(tag);
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • 10
    If you want to call a function in the asynchronously-loaded script as soon as it's loaded, you can do this: `$.getScript('async.js', function() { my_function(); });` – Noel Whitemore Feb 20 '16 at 15:48
  • 3
    getScript will not use Browser cache .This will reload the file and will take time – Iññoceñt Ùšmâñ Sep 13 '17 at 03:41
  • Is there a way to do something after the script has loaded? Doing it straight after this means the script hasn't been loaded yet. (Using plain js, not jquery.) – mcv Nov 22 '17 at 17:08
  • @mcv - Means what script hasn't been loaded yet? Your question is not specified enough and probably belongs in its own question if it's at all different from the original question here. You can put an `onload` event handler on the ` – jfriend00 Nov 22 '17 at 18:01
  • You're right. My issue is handled in this question: https://stackoverflow.com/questions/14644558/call-javascript-function-after-script-is-loaded . Although that didn't quite fix it, because I'm loading the Youtube API, which apparently isn't entirely initialised yet when that callback fires, so it provides its own hard-coded callback to `onYouTubeIframeAPIReady()`. – mcv Nov 24 '17 at 09:27
  • @mcv - Yes, that absolutely fits in the mix. If the library itself does stuff after loading that you have to wait for (like it might be dynamically loading components too), then you have to use it's onload API (whatever that is) after the script itself is loaded. – jfriend00 Nov 24 '17 at 09:49
  • @mcv according to [`$.getScript()`](https://api.jquery.com/jquery.getscript/) you can use `.done()`/`.fail()` functions attached to it if the script is loaded or not, respectively... That should be easier for you. – CPHPython Jun 05 '18 at 08:30
  • What is the benefit of your last example regarding the question? It just shows the loading at any time because it is in `head`. – Timo Jul 30 '22 at 09:34
13

For a Progressive Web App I wrote a script to easily load javascript files async on demand. Scripts are only loaded once. So you can call loadScript as often as you want for the same file. It wouldn't be loaded twice. This script requires JQuery to work.

For example:

loadScript("js/myscript.js").then(function(){
    // Do whatever you want to do after script load
});

or when used in an async function:

await loadScript("js/myscript.js");
// Do whatever you want to do after script load

In your case you may execute this after document ready:

$(document).ready(async function() {
    await loadScript("js/myscript.js");
    // Do whatever you want to do after script is ready
});

Function for loadScript:

function loadScript(src) {
  return new Promise(function (resolve, reject) {
    if ($("script[src='" + src + "']").length === 0) {
        var script = document.createElement('script');
        script.onload = function () {
            resolve();
        };
        script.onerror = function () {
            reject();
        };
        script.src = src;
        document.body.appendChild(script);
    } else {
        resolve();
    }
});
}

Benefit of this way:

  • It uses browser cache
  • You can load the script file when a user performs an action which needs the script instead loading it always.
awpross
  • 141
  • 1
  • 4
  • 2
    Nice! However, wouldn't it be better to do pure JavaScript here? Why are you using jQuery here? Like replace if() with document.querySelector("script[src='" + src + "']") === null – user706420 Aug 11 '22 at 13:41
11

The second approach is right to execute JavaScript code after the page has finished loading - but you don't actually execute JavaScript code there, you inserted plain HTML.
The first thing works, but loads the JavaScript immediately and clears the page (so your tag will be there - but nothing else).
(Plus: language="javascript" has been deprecated for years, use type="text/javascript" instead!)

To get that working, you have to use the DOM manipulating methods included in JavaScript. Basically you'll need something like this:

var scriptElement=document.createElement('script');
scriptElement.type = 'text/javascript';
scriptElement.src = filename;
document.head.appendChild(scriptElement);
Nicolas Bouvrette
  • 4,295
  • 1
  • 39
  • 53
Johannes H.
  • 5,875
  • 1
  • 20
  • 40
  • If you use `document.write()` after the document has been loaded, it will clear the current document and start a new one which is certainly not what the OP wants. – jfriend00 Nov 01 '13 at 23:35
  • Oh, YOu're right of course! I'll edit my answer to reflect that. – Johannes H. Nov 01 '13 at 23:38
6

Focusing on one of the accepted answer's jQuery solutions, $.getScript() is an .ajax() request in disguise. It allows to execute other function on success by adding a second parameter:

$.getScript(url, function() {console.log('loaded script!')})

Or on the request's handlers themselves, i.e. success (.done() - script was loaded) or failure (.fail()):

$.getScript(
    "https://code.jquery.com/color/jquery.color.js",
    () => console.log('loaded script!')
  ).done((script,textStatus ) => {
    console.log( textStatus );
    $(".block").animate({backgroundColor: "green"}, 1000);
  }).fail(( jqxhr, settings, exception ) => {
    console.log(exception + ': ' + jqxhr.status);
  }
);
.block {background-color: blue;width: 50vw;height: 50vh;margin: 1rem;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="block"></div>
CPHPython
  • 12,379
  • 5
  • 59
  • 71
  • 1
    Heads-up: By default, `$.getScript()` does not leverage the browser cache and always loads the full script from the server. – Philipp Apr 07 '21 at 21:27
6

To easily "delay" script execution after the page is loaded use 'defer' attribute:

<script src="demo_defer.js" defer></script>

Keep in mind this only works with external scripts (called with 'src' attribute)

Documentation:

https://www.w3schools.com/tags/att_script_defer.asp

https://javascript.info/script-async-defer

Kris
  • 328
  • 4
  • 15
  • 3
    I don't understand why this is not the right & simplest solution! – Broken Arrow Oct 14 '22 at 22:49
  • 1
    For me it's a bit misleading. The script will still be downloaded before onload but only executed afterwords. I, just like the author, wanted to not block resources until onload event fires – Moseleyi Feb 16 '23 at 22:14
2

Here is a code I am using and which is working for me.

window.onload = function(){
    setTimeout(function(){
        var scriptElement=document.createElement('script');
        scriptElement.type = 'text/javascript';
        scriptElement.src = "vendor/js/jquery.min.js";
        document.head.appendChild(scriptElement);

        setTimeout(function() {
            var scriptElement1=document.createElement('script');
            scriptElement1.type = 'text/javascript';
            scriptElement1.src = "gallery/js/lc_lightbox.lite.min.js";
            document.head.appendChild(scriptElement1);
        }, 100);
        setTimeout(function() {
            $(document).ready(function(e){
                lc_lightbox('.elem', {
                    wrap_class: 'lcl_fade_oc',
                    gallery : true, 
                    thumb_attr: 'data-lcl-thumb', 
                    slideshow_time  : 3000,
                    skin: 'minimal',
                    radius: 0,
                    padding : 0,
                    border_w: 0,
                }); 
            });
        }, 200);

    }, 150);
};
Prem Acharya
  • 491
  • 4
  • 3
0

<script type="text/javascript">
$(window).bind("load", function() { 

// your javascript event

)};
</script>
Flexo
  • 87,323
  • 22
  • 191
  • 272
Vô Vị
  • 183
  • 1
  • 2
-1

http://jsfiddle.net/c725wcn9/2/embedded

You will need to inspect the DOM to check this works. Jquery is needed.

$(document).ready(function(){
   var el = document.createElement('script');
   el.type = 'application/ld+json';
   el.text = JSON.stringify({ "@context": "http://schema.org",  "@type": "Recipe", "name": "My recipe name" });

   document.querySelector('head').appendChild(el);
});
Aditya Tomar
  • 841
  • 1
  • 13
  • 20