diff --git a/.eslintrc.json b/.eslintrc.json index ebeed34..9508d37 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -6,6 +6,7 @@ }, "globals": { "Chartist": "readonly", + "statify_ajax": "readonly", "statify_translations": "readonly" } } diff --git a/CHANGELOG.md b/CHANGELOG.md index ff359e3..a4daec8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file. This projec * Introduced separate settinge page and reduced widget backview to widget settings only * Add options to track logged in users, feeds and search requests * Add option to show total visits +* Refactored JavaScript tracking to use WP AJAX * Updated Chartist JS library for dashboard widget * Introduced new option to separate display from storage range diff --git a/inc/class-statify-frontend.php b/inc/class-statify-frontend.php index 634741a..6932211 100644 --- a/inc/class-statify-frontend.php +++ b/inc/class-statify-frontend.php @@ -22,42 +22,47 @@ class Statify_Frontend extends Statify { * Track the page view * * @since 0.1.0 - * @version 1.4.2 + * @since 1.7.0 $is_snippet parameter added. + * @version 1.7.0 * - * @return bool + * @param boolean $is_snippet Is tracking triggered via JS (default: false). + * + * @return boolean */ - public static function track_visit() { + public static function track_visit( $is_snippet = false ) { - /* Init vars */ + // Check of JS snippet is configured. $use_snippet = self::$_options['snippet']; - $is_snippet = $use_snippet && get_query_var( 'statify_target' ); - /* Set target & referrer */ - if ( $is_snippet ) { - $target = urldecode( get_query_var( 'statify_target' ) ); - $referrer = urldecode( get_query_var( 'statify_referrer' ) ); + // Set target & referrer. + $target = null; + $referrer = null; + if ( $use_snippet && $is_snippet ) { + if ( isset( $_REQUEST['statify_target'] ) ) { + $target = filter_var( wp_unslash( $_REQUEST['statify_target'] ), FILTER_SANITIZE_URL ); + } + if ( isset( $_REQUEST['statify_referrer'] ) ) { + $referrer = filter_var( wp_unslash( $_REQUEST['statify_referrer'] ), FILTER_SANITIZE_URL ); + } } elseif ( ! $use_snippet ) { - $target = filter_var( - ( isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '/' ), - FILTER_SANITIZE_URL - ); - if ( is_null( $target ) || false === $target ) { - $target = '/'; - } else { - $target = wp_unslash( $target ); + if ( isset( $_SERVER['REQUEST_URI'] ) ) { + $target = filter_var( wp_unslash( $_SERVER['REQUEST_URI'] ), FILTER_SANITIZE_URL ); } - - $referrer = filter_var( - ( isset( $_SERVER['HTTP_REFERER'] ) ? wp_unslash( $_SERVER['HTTP_REFERER'] ) : '' ), - FILTER_SANITIZE_URL - ); - if ( is_null( $referrer ) || false === $referrer ) { - $referrer = ''; + if ( isset( $_SERVER['HTTP_REFERER'] ) ) { + $referrer = filter_var( wp_unslash( $_SERVER['HTTP_REFERER'] ), FILTER_SANITIZE_URL ); } } else { return false; } + // Fallbacks for uninitialized or omitted target and referrer values. + if ( is_null( $target ) || false === $target ) { + $target = '/'; + } + if ( is_null( $referrer ) || false === $referrer ) { + $referrer = ''; + } + /* Invalid target? */ if ( empty( $target ) || ! wp_validate_redirect( $target, false ) ) { return self::_jump_out( $is_snippet ); @@ -116,6 +121,20 @@ public static function track_visit() { return self::_jump_out( $is_snippet ); } + /** + * Track the page view via AJAX. + * + * @return void + */ + public static function track_visit_ajax() { + // Check AJAX referrer. + check_ajax_referer( 'statify_track' ); + // Only do something if snippet use is actually configured. + if ( self::$_options['snippet'] ) { + self::track_visit( true ); + } + } + /** * Find the position of the first occurrence of a substring in a string about a array. * @@ -353,23 +372,31 @@ public static function query_vars( $vars ) { */ public static function wp_footer() { - /* Skip by option */ + // Skip by option. if ( ! self::$_options['snippet'] ) { return; } - /* Skip by internal rules (#84) */ + // Skip by internal rules (#84). if ( self::_is_internal() ) { return; } - /* Load template */ - load_template( - wp_normalize_path( - sprintf( - '%s/views/js-snippet.php', - STATIFY_DIR - ) + wp_enqueue_script( + 'statify-js', + plugins_url( 'js/snippet.min.js', STATIFY_FILE ), + array(), + STATIFY_VERSION, + true + ); + + // Add endpoint to script. + wp_localize_script( + 'statify-js', + 'statify_ajax', + array( + 'url' => admin_url( 'admin-ajax.php' ), + 'nonce' => wp_create_nonce( 'statify_track' ), ) ); } diff --git a/inc/class-statify.php b/inc/class-statify.php index b2694f0..c43b76c 100644 --- a/inc/class-statify.php +++ b/inc/class-statify.php @@ -44,8 +44,8 @@ public static function instance() { * @version 2017-01-10 */ public function __construct() { - // Skip me! - if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) { + // Nothing to do on autosave. + if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { return; } @@ -71,7 +71,9 @@ public function __construct() { ) ); - if ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) { // XMLRPC. + if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) { + add_action( 'wp_ajax_nopriv_statify_track', array( 'Statify_Frontend', 'track_visit_ajax' ) ); + } elseif ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) { // XMLRPC. add_filter( 'xmlrpc_methods', array( 'Statify_XMLRPC', 'xmlrpc_methods' ) ); } elseif ( defined( 'DOING_CRON' ) && DOING_CRON ) { // Cron. add_action( 'statify_cleanup', array( 'Statify_Cron', 'cleanup_data' ) ); diff --git a/js/snippet.js b/js/snippet.js index f196654..34c355a 100644 --- a/js/snippet.js +++ b/js/snippet.js @@ -2,13 +2,14 @@ var statifyReq; try { statifyReq = new XMLHttpRequest(); - statifyReq.open( - 'GET', - document.getElementById( 'statify-js-snippet' ).getAttribute( 'data-home-url' ) + - '?statify_referrer=' + encodeURIComponent( document.referrer ) + + statifyReq.open( 'POST', statify_ajax.url, true ); + statifyReq.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded;' ); + statifyReq.send( + '_ajax_nonce=' + statify_ajax.nonce + + '&action=statify_track' + + '&statify_referrer=' + encodeURIComponent( document.referrer ) + '&statify_target=' + encodeURIComponent( location.pathname + location.search ) ); - statifyReq.send( null ); } catch ( e ) { } }() ); diff --git a/statify.php b/statify.php index 16d7329..875222e 100644 --- a/statify.php +++ b/statify.php @@ -20,6 +20,7 @@ define( 'STATIFY_FILE', __FILE__ ); define( 'STATIFY_DIR', dirname( __FILE__ ) ); define( 'STATIFY_BASE', plugin_basename( __FILE__ ) ); +define( 'STATIFY_VERSION', '1.7.0' ); /* Hooks */ diff --git a/views/js-snippet.php b/views/js-snippet.php deleted file mode 100644 index 5f927a3..0000000 --- a/views/js-snippet.php +++ /dev/null @@ -1,21 +0,0 @@ - - - -
- - -