65

Currently, most of the popular websites, like google, yahoo detect if the user connection speed is slow and then give a option to load basic version of the website instead of the high end one.

What are the methods available to detect slow internet connections?

P.S. I think this is achieved through javascript, so I will tag it as a javascript question? However, I am looking for answers oriented more towards PHP, if this is also server related.

Starx
  • 77,474
  • 47
  • 185
  • 261
  • 3
    Just guessing: I can imagine that they use a simple timeout and check after that if the page contains certain elements. If not, the user must have a slow connection. – Felix Kling Aug 09 '11 at 09:36
  • I found [this](http://stackoverflow.com/questions/5529718/how-to-detect-internet-speed-in-javascript) question asked here on SO. So, this question is a propable duplicate, but still answers there are not giving a concrete concept. You guys can close it, if you think otherwise. – Starx Aug 09 '11 at 09:37
  • @Felix Kling, May be, but Markup Elements load quite faster, the real time is consumed while rendering it like applying css, loading images etc. Will it give a definate output? – Starx Aug 09 '11 at 09:40
  • @Starx Rendering and css overheads/delays apply when it is loading on a super fast connection too, how are they so quick in that case? The network is slower than even reflows. A slow network is slower than everything. – doug65536 Nov 18 '21 at 01:05

5 Answers5

88

You can start a timeout in an inline script block in <head>, which will be run as soon as it's encountered. You would then cancel the timeout when the load event fires. If the timeout ever fires, the page is loading slowly. For example:

<script type="text/javascript">
    var slowLoad = window.setTimeout( function() {
        alert( "the page is taking its sweet time loading" );
    }, 10 );

    window.addEventListener( 'load', function() {
        window.clearTimeout( slowLoad );
    }, false );
</script>

Obviously you would want to replace the alert with something a little more useful. Also note that the example uses the W3C/Netscape event API and thus won't work in Internet Explorer before version 9.

Sam Hanes
  • 2,789
  • 23
  • 22
  • Just wanted to point out that you may need to use `window.addEventListener`. `document.addEventListener` didn't work for me. – danqing Aug 26 '16 at 08:59
16

Here's a full implementation I just completed for a site I'm working on. Felt like sharing it. It uses a cookie to dismiss the message (for people who don't mind that the site takes a long time to load.) The message will show if the page is taking longer than 1 second to load. Best to change this to around 5 seconds or so.

The code below should be added right after the opening <head> tag, because it has to be loaded as soon as possible, but it can't appear before the html or head tag, because these tags need to be present in the DOM when the script is run. It's all inline code, so the scripts and styles are loaded before any other external files (css, js or images).

<style>
    html { position: relative; }
    #slow-notice { width:300px; position: absolute; top:0; left:50%; margin-left: -160px; background-color: #F0DE7D; text-align: center; z-index: 100; padding: 10px; font-family: sans-serif; font-size: 12px; }
    #slow-notice a, #slow-notice .dismiss { color: #000; text-decoration: underline; cursor:pointer; }
    #slow-notice .dismiss-container { text-align:right; padding-top:10px; font-size: 10px;}
</style>
<script>

    function setCookie(cname,cvalue,exdays) {
        var d = new Date();
        d.setTime(d.getTime()+(exdays*24*60*60*1000));
        var expires = "expires="+d.toGMTString();
        document.cookie = cname + "=" + cvalue + ";path=/;" + expires;
    }

    function getCookie(cname) {
        var name = cname + "=";
        var ca = document.cookie.split(';');
        for(var i=0; i<ca.length; i++) {
            var c = ca[i].trim();
            if (c.indexOf(name)==0) return c.substring(name.length,c.length);
        }
        return "";
    } 

    if (getCookie('dismissed') != '1') {
        var html_node = document.getElementsByTagName('html')[0];
        var div = document.createElement('div');
        div.setAttribute('id', 'slow-notice');

        var slowLoad = window.setTimeout( function() {
            var t1 = document.createTextNode("The website is taking a long time to load.");
            var br = document.createElement('br');
            var t2 = document.createTextNode("You can switch to the ");
            var a = document.createElement('a');
            a.setAttribute('href', 'http://light-version.mysite.com');
            a.innerHTML = 'Light Weight Site';

            var dismiss = document.createElement('span');
            dismiss.innerHTML = '[x] dismiss';
            dismiss.setAttribute('class', 'dismiss');
            dismiss.onclick = function() {
                setCookie('dismissed', '1', 1);
                html_node.removeChild(div);
            }

            var dismiss_container = document.createElement('div');
            dismiss_container.appendChild(dismiss);
            dismiss_container.setAttribute('class', 'dismiss-container');

            div.appendChild(t1);
            div.appendChild(br);
            div.appendChild(t2);
            div.appendChild(a);
            div.appendChild(dismiss_container);

            html_node.appendChild(div);


        }, 1000 );

        window.addEventListener( 'load', function() {
            try {
                window.clearTimeout( slowLoad );
                html_node.removeChild(div);
            } catch (e){
                // that's okay.
            }

        });
    }

</script>

The result should look like this:

enter image description here

Hope it helps.

Jules Colle
  • 11,227
  • 8
  • 60
  • 67
7

You could listen to two DOM events, DOMContentLoaded and load, and calculate the difference between the time these two events are dispatched.

DOMContentLoaded is dispatched when the DOM structure is ready, but external resources, images, CSS, etc. may not be.

load is dispatched when everything is ready.

How Javascript Loading Works - DOMContentLoaded and OnLoad (Wayback Link)

Michael M.
  • 10,486
  • 9
  • 18
  • 34
Ryan Li
  • 9,020
  • 7
  • 33
  • 62
  • I read that article, but one thing strikes me. To read the connection speed, the JS codes have to wait for completion of both these events, but that's not what google or yahoo does. They detect speeds, as the page is being loaded, and prompt to the user about it... – Starx Aug 09 '11 at 09:53
  • @Starx: as said in the article, inline JavaScript could be run as the documents loads, before `DOMContentLoaded` is triggered. – Ryan Li Aug 09 '11 at 09:55
  • So what do you think, should be it those inline javascript? – Starx Aug 09 '11 at 09:58
  • @Startx: yes, it's absolutely viable there. Just a short line to record current time. – Ryan Li Aug 09 '11 at 15:51
  • But, to record time in between those two events we have to wait for both of them to complete. Or is there another event we can record... during the page loading. – Starx Aug 10 '11 at 00:07
  • @Startx: you only need to record the time when `DOMContentLoaded` is dispatched, set a certain timeout, if `load` isn't fired after the time, you could tell that the connection is slow. – Ryan Li Aug 10 '11 at 02:29
  • Still, both the events `DOMContentLoaded` and `Load` have to be completed or fired, to know the speed, right? – Starx Aug 10 '11 at 06:01
  • And, Please call me **Starx**, startx seems kinda geeky – Starx Aug 10 '11 at 06:05
  • @Starx: sorry, got used to `startx` :-P. Yeah, it's true if you use these two events, but if you just want to know the speed you could ask the browser to fetch an arbitrary file from the server and record the start/finish time. – Ryan Li Aug 10 '11 at 06:10
3

The newer Network Information API provides this information (and more) in the browser. window.navigator.connection.effectiveType will return a string that is either 'slow-2g', '2g', '3g', or '4g'. Here's one simple way it could be used to detect slow connections:

if (window.navigator.connection.effectiveType.endsWith("2g")) {
  // user is on a 2g connection
}

Be aware that this is an experimental API with limited browser support (Chromium-only as of this writing).

Here is the browser support in Can I Use website which is 74.83%

mo3n
  • 1,522
  • 2
  • 10
  • 34
zgreen
  • 4,182
  • 1
  • 24
  • 19
2

You can get the connection speed by downloading some test resource (image would be more suitable) whose size is known to you (which is easy to get) and measuring the time taken to download it. Keep in mind that testing one time will only gives you the connection speed at that instant. Results may vary from time to time if user is using bandwidth parallel to the image tests. This results in the bandwidth available for your app, which is what we need exactly.

I read somewhere Google does similar trick using some 1x1 grid pixel image for testing the connection speed at the page load and it even shows you something like 'Connection seems slow, try HTML version'... or similar.

Here is another link describing the same technique - http://www.ehow.com/how_5804819_detect-connection-speed-javascript.html

Brad Larson
  • 170,088
  • 45
  • 397
  • 571
manikanta
  • 8,100
  • 5
  • 59
  • 66