Ik ben aan het uitzoeken hoe ik iets gelijkaardig kan maken aan het trackingscript van google analytics. Deze werken met een javascript code om gegevens te verzenden zonder ajax.
Met wat opzoekwerk vond ik dit:

<script type="text/javascript">
var statsPage = 'http://www.uw-url.be/process.php';
var stats = {
    page: location.href,
    browser: 'ie',
    ip: '127.0.0.1',
    referral: 'google.com?search=test'
};
var params = $.param(stats);
alert(statsPage+'?'+params);
</script>

De alert geeft alles mooi weer.
Nu ben ik nog op zoek naar hoe ik die parameters naar de url opgegeven in statsPage kan verzenden. Ik heb hier geen idee en kan dit ook nergens terugvinden precies. Misschien is er een betere methode om dit te doen ook. Ik luister naar jullie...

Ik vond wel deze, maar weet niet of dit gaat werken:

$('<img>', {
    src: statsPage + '?' + params
}).appendTo('body').remove()


Als ik analytics script bekijk ziet dit er totaal anders uit, maar ik versta daar niet zoveel van. Misschien kan iemand mij dit even uitleggen?
Een voorbeeld:

<script>
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

  ga('create', 'UA-49578310-1', 'auto');
  ga('send', 'pageview');

</script>

De bedoeling zou uiteindelijk zijn dat iedereen dat javascript op zijn pagina kan plakken en ik in de backend alles mooi kan opvangen. Vandaar wou ik niet met AJAX werken en ook niet met een REST API. Daar kan niet iedereen mee overweg.

Voor mijn script (eerst geposte) heb ik ook jquery nodig en voor de analytics.js script niet blijkbaar. In mijn geval moet ook iedereen het jquery script (<script src="https://code.jquery.com/jquery-1.12.4.js"></script>) boven de code gaan zetten. Misschien is dit ook te omslachting?
Deze eerder geposte code heb ik vroeger nog gebruikt op oude websites om dat bij te houden en dat werkt wel goed...

var startTime = new Date();        //Start the clock!
    window.onbeforeunload = function()        //When the user leaves the page(closes the window/tab, clicks a link)...
    {
        var endTime = new Date();        //Get the current time.
        var timeSpent = (endTime - startTime);        //Find out how long it's been.
        var xmlhttp;        //Make a variable for a new ajax request.
        if (window.XMLHttpRequest)        //If it's a decent browser...
        {
            // code for IE7+, Firefox, Chrome, Opera, Safari
            xmlhttp = new XMLHttpRequest();        //Open a new ajax request.
        }
        else        //If it's a bad browser...
        {
            // code for IE6, IE5
            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");        //Open a different type of ajax call.
        }
        var url = "http://www.my-url.com/response.php?userID=1&pag_titel=1&datum=1&time="+timeSpent;        //Send the time on the page to a php script of your choosing.
        xmlhttp.open("GET",url,false);        //The false at the end tells ajax to use a synchronous call which wont be severed by the user leaving.
        xmlhttp.send(null);        //Send the request and don't wait for a response.
        
    }

Of ze betrouwbaar is weet ik niet, maar het werkt ondertussen al 3 jaar. Dus de functie onbeforeunload zit hier ook in, waarom is deze dan niet goed in mijn nieuwe code?
Het is in geen van beide gevallen goed of betrouwbaar, je hebt alleen de illusie dat het werkt. Dat is heel wat anders dan dat het daadwerkelijk werkt. De enige manier om "bij te houden" hoe lang men op een pagina aanwezig is, is meten wanneer de volgende pagina wordt opgevraagd.

//When the user leaves the page(closes the window/tab, clicks a link)...
En dat is gewoonweg niet het gedrag van onbeforeunload. In oudere IE versies wel, nu mogelijk ook al niet meer.
onbeforeunload wordt aangeroepen als je op een link klikt of refresht. Wanneer onbeforeunload een resultaat geeft wordt een vraag gesteld of navigatie moet plaatvinden en wordt deze gebruikt voor de tekst in de navigatievraag.
De geposte code stuurt een datum mee van zodra de user de pagina verlaat. Ik hou dat bij in database en er is geen enkel record die die gegevens niet heeft. Dus ga ik er van uit dat het wel werkt?
Wat jij bedoeld is hier waarschijnlijk telkens een referrer mee te sturen ook? En op die manier te meten? Ik heb ook geen idee hoe dit aan te pakken eigenlijk... Maar wil dat wel eens proberen. Kan jij me hier even op weg helpen? En wat gaat er gebeuren als iemand een laatste pagina heeft bezocht en dan de browser tab sluit? Dan heb ik waarschijnlijk geen data hieromtrent?

[size=xsmall]Toevoeging op 29/10/2016 19:09:51:[/size]

Is er geen nieuwere manier om die onbeforeunload te laten werken? Of moet ik dit dan toch totaal vergeten? Vind dat raar aangezien dat nu bij mijn oudere websites wel werkt en alles mooi meekomt in de database.

[size=xsmall]Toevoeging op 29/10/2016 19:56:55:[/size]

Ik zie dat een script zoals google analytics gebruikt maakt van onderstaande:

navigator.sendBeacon = navigator.sendBeacon || function () {
    var xhr = new XMLHttpRequest();

    xhr.open('GET', 'http://www.my-url.com/response.php?pag_title=1');
    xhr.send();

}
};

Is dat iets interessants?
Ik vond ook deze: http://jasonzissman.com/timeme/index.html, dat toont toch duidelijk dat die onbeforeunload nog steeds werkt?
Ik heb nergens gezegd dat het *nooit* werkt, ik heb gezegd dat het *onbetrouwbaar* is. Het is deels afhankelijk van de browserinstellingen welke browser je gebruikt etc. In theorie kun je een xhr doen, maar deze zal wel synchroon moeten lopen, omdat de pagina anders al verlaten is voordat de request kan worden gestart. onbeforeunload is in die zin niet meer dan een hack. en wat doe je in het geval dat een pagina legitiem gebruik maakt van onbeforeunload? Dan registreer je een onterechte unload as er op nee wordt geklikt, of je overschrijft de methode zodat dat uberhaupt niet meer werkt. navigator.sendBeacon is een nieuwe methode die dat zo betrouwbaar mogelijk maakt. Zie https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon
Ben van Velzen op 27/10/2016 23:13:58

Wat meestal gewoon wordt gedaan is gebruik maken van een "meetpixel", dus een image van 1x1 die feitelijk een php script is. Deze kun je gewoon met javascript invoegen, en als je aan iets minder gegevens genoeg hebt kan het zelfs zonder javascript?

Overigens heb je strict genomen jquery nooit *nodig*. De cross browser zaken moet je dan alleen wel even zelf doen. In het geval van het invoegen van een plaatje hoef je niets bijzonders te doen. Zie document.createElement, of zonder fysieke image een Image object.


Hallo Ben,

Dit lijkt mij interessant om meer te weten maar dan zonder javascript. Mag ik hier wat meer over weten
Waar loop je dan op vast? Het idee is eenvoudig genoeg, je hebt een PHP script dat een plaatje uitpoept en op de achtergrond wat statistiek bijhoudt.
Indien die sendbeacon een degelijke oplossing zou zijn zou ik graag weten waarom mijn code niet werkt hier.

navigator.sendBeacon = navigator.sendBeacon || function () {
    var xhr = new XMLHttpRequest();

    xhr.open('GET', 'http://www.my-url.com/response.php?pag_title=1');
    xhr.send();

}
};

Ook hier krijg ik geen response terug. Misschien omdat er geen return in de functie is opgenomen? Enig idee hoe dit aan te pakken?

Voor de meetpixel: de vraag is hoe ik de tijd kan meten tussen de pagina's. Dat zie ik niet.
Wanneer je de functie op die manier maakt is het automatisch een no-op. Zie https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon voor de rationale en de manier waarop sendBeacon gebruikt moet worden. Ook staat er nog een alternatief met het maken van een image in de unload.

Waar het op neerkomt is het volgende:
De meeste browsers negeren het gebruik van asynchrone XHR tijdens unload, maar navigator.sendBeacon niet. Deze moet je echter wel even zelf aanroepen tijdens unload.

Je huidige aanpak overschrijft de functie indien deze nog niet bestaat, deels correct.
Wat je wilt doen is het gedrag van navigator.sendBeacon emuleren wanneer deze niet bestaat, door een *synchrone* XHR request te doen, dus met de 3e parameter van xhr.open op false, en met directe doorgave van de data in de attributen zoals de request url niet hardcoded.

Wat je op de pagina op MDN zult terugzien is dat browserondersteuning voor sendBeacon beperkt is.

>> Voor de meetpixel: de vraag is hoe ik de tijd kan meten tussen de pagina's. Dat zie ik niet.
Niet? Trek de request tijd van de vorige en de huidige pagina van elkaar af. *boem* tijd die besteed is op de vorige pagina. Juist om die reden zet je per bezoek een cookie die een "sessie" representeert.
De uiteindelijk code zou dus zo moeten zijn:

window.addEventListener('unload', logData, false);

function logData() {
  navigator.sendBeacon = navigator.sendBeacon || function () {
    var xhr = new XMLHttpRequest();
	var endTime = new Date();

    xhr.open('GET', 'http://www.my-url.com/response.php?endTime='+endTime, false);
    xhr.send();

};
}

Of is dit nog steeds niet juist? Hoe krijg ik hier een response terug in alert van mijn reponse.php file?
Ik heb deze geprobeerd toe te voegen aan mijn functie logData maar krijg niks terug:

xhr.onreadystatechange = function() {
    if (xhr.readyState == XMLHttpRequest.DONE) {
        alert(xhr.responseText);
    }
}

Wat bedoel je met de direct doorgave van de url niet harcoded?
Ik weet dat de browser ondersteuning beperkt is, heb dat gelezen.

Meetpixel: Wat gebeurd er dan met de eerst bezochte pagina? Die heeft toch geen request tijd?
En hoe kan ik nu weten in dezelfde response.php wat de eerste tijd was en wat de tweede tijd was? Hoe vang ik dat op?
Hoezo alert? Je weet dat alerts e.d. gewoon genegeerd worden door de browser tijdens unload? Je zult je script ergens iets moeten laten schrijven om te zien dat het werkt. Tijdens unload werkt alleen het synchroon opvragen van XHR, dus de readystate zal niets gaan doen.

>> Wat bedoel je met de direct doorgave van de url niet harcoded?
Ik weet dat de browser ondersteuning beperkt is, heb dat gelezen.

Simpel. navigator.sendBeacon is een alternatief voor XHR, die zelf een url vraagt als argument. Het is dus de bedoeling om de url uit het argument te gebruiken in je *vervangende* functie, niet om deze daar te gaan hardcoden.

>> Meetpixel: Wat gebeurd er dan met de eerst bezochte pagina? Die heeft toch geen request tijd?
En hoe kan ik nu weten in dezelfde response.php wat de eerste tijd was en wat de tweede tijd was? Hoe vang ik dat op?

Natuurlijk heeft die dat wel, dat is de tijd waarop hij wordt opgevraagd. Dat gooi je gewoon in je database. Ik zie echt niet wat daar niet duidelijk aan is.


Het eindresultaat is heel simpel, je gooit de instructies nu gewoon door elkaar en hoopt dat het werkt, terwijl iets als dit beter zal gaan:

navigator.sendBeacon = navigator.sendBeacon || function (url, data) {
    var xhr = new XMLHttpRequest();
    xhr.open('POST', url, false);
    xhr.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
    xhr.send(data);
};

function logData() {
  var data = {'endDate': new Date()};
  navigator.sendBeacon('http://www.my-url.com/response.php', data);
}

window.addEventListener('unload', logData, false);



Uiteraard niet getest, maar het zal iets in deze geest moeten worden. Dit POST gegevens naar response.php, geheel volgens sendBeacon specificatie.

Reageren