• User Attivo

    JavaScript, conteggiare click siti esterni

    Salve a tutti,
    stavo cercando un modo per conteggiare quanti click vengono fatti verso altri siti, e con una ricerca su Google ho trovato (fonte: stackoverflow. com/questions/5862781/how-to-count-clicks-with-javascript) questa soluzione:

    [HTML]<script type="text/javascript"><!--
    // This variable contains the number of clicks corresponding to the linked URLs
    var clickCount = {}
    // List of all a tags
    , aList = document.getElementsByTagName('a');
    // Function called every time a link is clicked on
    , clickCounter = function()
    {
    clickCount[this.href] = clickCount[this.href] ? clickCount[this.href]+1 : 1;
    }
    ;
    // The event is attached to every link having a "href" attribute
    for (var i=0 ; i<aList.length, a=aList* ; i++)
    {
    if (this.href)
    {
    a.onclick = clickCounter;
    }
    }
    // This example uses jQuery to send the data to a PHP script
    // A POST request is sent just before the window is closed
    onbeforeunload = function()
    {
    $.post('/update-external-counter.php', clickCount);
    }
    // --></script>[/HTML]

    Sfortunatamente jQuery non è il mio forte ed ho cercato di trovare la funzione equivalente in JavaScript che permettesse di processare il form.

    Con altre ricerche ho trovato (fonte: stackoverflow. com/questions/133925/javascript-post-request-like-a-form-submit) questa funzione:

    [HTML]<script type="text/javascript"><!--
    function post_to_url(path, params, method) {
    method = method || "post"; // Set method to post by default, if not specified.

    // The rest of this code assumes you are not using a library.
    // It can be made less wordy if you use one.
    var form = document.createElement("form");
    form.setAttribute("method", method);
    form.setAttribute("action", path);
    
    for(var key in params) {
        if(params.hasOwnProperty(key)) {
            var hiddenField = document.createElement("input");
            hiddenField.setAttribute("type", "hidden");
            hiddenField.setAttribute("name", key);
            hiddenField.setAttribute("value", params[key]);
    
            form.appendChild(hiddenField);
         }
    }
    
    document.body.appendChild(form);
    form.submit();
    document.body.removeChild(form);
    

    }
    // --></script>[/HTML]

    Ho unito i precedenti codici nello stesso file HTML aggiungendo anche qualche indirizzo esterno al dominio, ma non sembra funzionare sostituendo

    [HTML]$.post('/update-external-counter.php', clickCount);[/HTML]

    presente nel primo codice di questo post con quest'altra:

    [HTML]post_to_url("/update-external-counter.php", clickCount, "post");[/HTML]

    Rimane sottinteso che ho creato lo script update-external-counter.php in modo che quando richiamato raccolga le variabili passate con il metodo post, e per semplicità le faccio salvare in un file di testo appendendole in coda, ma per ora non registra nulla.

    Mi sapreste cortesemente dire come fare a rendere il nuovo codice funzionante?
    Grazie in anticipo a tutti.


  • User

    Ti consiglio di rimanere su jQuery per rendere più chiaro il codice, visto che il tuo obiettivo in questo momento è farlo funzionare 🙂 Lo script dovrebbe funzionare senza grosse modifiche...
    Anzitutto metti un alert prima di $.post per vedere se quella porzione di codice viene eseguita. Altra cosa, lo slash che precede l'url in $.post potrebbe far puntare ad un url sbagliato, se sei in una sottodirectory, ma non vorrei dire una cavolata 🙂

    Ciao 🙂


  • User Attivo

    Grazie per questi utili suggerimenti. Mi trovo concorde nel rimanere a jQuery almeno per verificare la correttezza del codice.

    Lo slash lo avevo messo affinché lo script che eseguisse la registrazione del click fosse nella root del dominio e quindi fosse indipendente dal livello di annidamento in cui è sollevato l'evento del click al sito esterno, ma come giustamente fai notare in fase di test è prima necessario verificare che il codice disponibile sia funzionante.

    Per fare ciò ho creato una cartella temporanea per lo scopo ed ho posto come permessi di scrittura 0777, ed ho inserito la libreria jquery-1.9.1.min.js, la pagina prova.htm a cui ho aggiunto l'alert per un po' di debug e questo è il nuovo codice:

    [HTML]<html>
    <head>
    <script type="text/javascript" src="jquery-1.9.1.min.js"></script>
    <script type="text/javascript"><!--
    // This variable contains the number of clicks corresponding to the linked URLs
    var clickCount = {}
    // List of all a tags
    , aList = document.getElementsByTagName('a');
    // Function called every time a link is clicked on
    , clickCounter = function()
    {
    clickCount[this.href] = clickCount[this.href] ? clickCount[this.href]+1 : 1;
    }
    ;
    // The event is attached to every link having a "href" attribute
    for (var i=0 ; i<aList.length, a=aList* ; i++)
    {
    if (this.href)
    {
    a.onclick = clickCounter;
    }
    }
    // This example uses jQuery to send the data to a PHP script
    // A POST request is sent just before the window is closed
    onbeforeunload = function()
    {
    alert(clickCount);
    $.post('update-external-counter.php', clickCount);
    }
    // --></script>
    </head>
    <body>
    <a href="url_1">link 1</a><br>
    <a href="url_2">link 2</a><br>
    <a href="url_3">link 3</a>
    </body>
    </html>[/HTML]

    Riguardo il precedente codice sfortunatamente non viene eseguito l'alert. Una cosa di cui mi viene il dubbio è sul tipo di clickCount che sia di tipo array perchè nel codice appare l'istruzione:

    [HTML]clickCount[this.href] = clickCount[this.href] ? clickCount[this.href]+1 : 1;[/HTML]

    e quindi l'alert potrebbe avere un comportamento anomalo, ma forse sbaglio perché in JavaScript non sono particolarmente ferrato.
    Riguardo il codice update-external-counter.php anch'esso per ora è più di debug (lo raffinerò in seguito prendendo solo la variabile di interesse ricevuta) che altro:

    [PHP]<?php

    foreach($_POST as $chiave => $valore)
    {
    $archivio .= "$chiave => $valore\n";
    }

    file_put_contents("conta-cliccati.txt", $archivio, FILE_APPEND);

    ?>[/PHP]

    Ho fatto anche delle prove con il sito jsfiddle. net ricorrendo alla jQuery 1.6.4 e cambiando il target di $.post con l'indirizzo assoluto in cui si trova il precedente script ma anche in questo caso non è sollevato l'alert.

    Ti ringrazio sinceramente per i suggerimenti. :ciauz:


  • User

    Prova questo: jsfiddle.net/paLZd/15/

    Ti basta cambiare il codice JS. 🙂

    Ciao


  • User Attivo

    MatrixTeo, grazie per avermi prodotto il nuovo codice. In effetti viene mostrato l'alert, ma la cosa strana è che poi anche l'istruzione
    [HTML]console.log(clickCount);[/HTML]
    riporta nuovamente il precedente alert mentre mi sarei atteso il valore in argomento, clickCount. Cosa che ho notato andando per tentativi inserendo dei commenti, è che console.log(clickCount); viene eseguita solo quella presente nella funzione onbeforeunload.

    Altra cosa che ho fatto è stata quella di riscrivere lo script update-external-counter.php per considerare il passaggio di un array:

    [PHP]<?php

    foreach($_POST as $chiave => $valore)
    {
    if (is_array($valore))
    {
    archivio .= "$valore è un array\n";
    foreach ($valore as $k => $elem)
    {
    $archivio .= "[$k] => $elem\n";
    }
    } else $archivio .= "$chiave => $valore\n";
    }

    file_put_contents("conta-cliccati.txt", $archivio, FILE_APPEND);

    ?>[/PHP]

    Pensavo che la precedente versione non considerasse questo caso e quindi fosse la causa della mancata scrittura del file.
    Purtroppo nonostante tutto questo c'è ancora qualche problema. Però ti ringrazio per i preziosi stimoli che mi hai dato.

    Ciao.


  • User

    Hai ragione, avevo sbagliato perchè clickCount per essere passato come parametro deve essere un oggetto, e non array, nel tuo codice iniziale era giusto 😄
    Ho aggiornato qui: jsfiddle.net/paLZd/16/

    Ho problemi a metterti tutto il codice sul forum, quindi l'ho messo qui: pastebin.com/r12deJJM

    Ciao


  • User Attivo

    Ho provato ad eseguire il nuovo codice, ma mi sono accorto che non siano eseguite le istruzioni console.log(clickCount);
    Ho fatto alcune ricerche e secondo alcuni è necessario sostituirlo con console.info(clickCount); poiché l'argomento è un array, oppure ricorrendo a JSON (ma leggo che funziona solo sui moderni browser, pertanto non sembra essere la scelta migliore) invocando JSON.stringify(clickCount); oppure con un alert con una sintassi di questo tipo:

    alert(clickCount.join('\n'));

    Eppure nonostante questo l'esecuzione dello script non si interrompe visualizzando il contenuto in argomento, né viene scritto il file testuale di log.