EBernhardson has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/270879

Change subject: Increase deliverability guarantee of unload events in search 
satisfaction schema
......................................................................

Increase deliverability guarantee of unload events in search satisfaction schema

The schema currently isn't able to track outbound clicks to other
domains, such as when we do backend interwiki searches. We decided
not to do it previously because sendBeacon isn't available in IE
which means we get a distorted view of reality.

This extends core event logging to utilize local storage to improve
deliverability guarantees of browsers that are not using event logging.

Should probably start off by doing a test, recording clicks directly
on the SERP and then comparing the events recorded vs the visitPage
events we record.

Change-Id: I32c69a6e7a6144a3221e2059b855a0c2516e4548
---
M extension.json
M modules/ext.wikimediaEvents.searchSatisfaction.js
2 files changed, 127 insertions(+), 4 deletions(-)


  git pull 
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/WikimediaEvents 
refs/changes/79/270879/1

diff --git a/extension.json b/extension.json
index eb00e4e..ef90aff 100644
--- a/extension.json
+++ b/extension.json
@@ -101,7 +101,7 @@
                "schema.TestSearchSatisfaction2": {
                        "class": "ResourceLoaderSchemaModule",
                        "schema": "TestSearchSatisfaction2",
-                       "revision": 15344952
+                       "revision": 15352873
                },
                "schema.GeoFeatures": {
                        "class": "ResourceLoaderSchemaModule",
diff --git a/modules/ext.wikimediaEvents.searchSatisfaction.js 
b/modules/ext.wikimediaEvents.searchSatisfaction.js
index 013bb38..5a9c130 100644
--- a/modules/ext.wikimediaEvents.searchSatisfaction.js
+++ b/modules/ext.wikimediaEvents.searchSatisfaction.js
@@ -25,7 +25,7 @@
                return;
        }
 
-       var search, autoComplete, session,
+       var search, autoComplete, session, eventLog,
                isSearchResultPage = mw.config.get( 'wgIsSearchResultPage' ),
                uri = new mw.Uri( location.href ),
                checkinTimes = [ 10, 20, 30, 40, 50, 60, 90, 120, 150, 180, 
210, 240, 300, 360, 420 ],
@@ -234,6 +234,120 @@
                setTimeout( action, 1000 * timeout );
        }
 
+       /**
+        * Increase deliverability of events fired close to unload, such as
+        * autocomplete results that the user selects. Uses a bit of optimism 
that
+        * multiple tabs are not working on the same localStorage queue at the 
same
+        * time. Could perhaps be improved with locking, but not sure the
+        * code+overhead is worth it.
+        *
+        * @return {Object}
+        */
+       function extendMwEventLog() {
+               var self,
+                       localQueue = [],
+                       queueKey = 'wmE-Ss-queue';
+
+               // if we have send beacon or do not track is enabled do nothing
+               if ( navigator.sendBeacon || mw.eventLog.sendBeacon === $.noop 
) {
+                       return mw.eventLog;
+               }
+
+               /**
+                * Add a url to the queue of events that havn't been delivered.
+                *
+                * @param {string} url
+                */
+               function add( url ) {
+                       localQueue.push( url );
+               }
+
+               /**
+                * Remove a url from the queue of events that havn't been 
delivered.
+                *
+                * @param {string} url
+                */
+               function remove( url ) {
+                       var i;
+                       for ( i = localQueue.length - 1; i >= 0; i-- ) {
+                               if ( localQueue[ i ] === url ) {
+                                       localQueue.splice( i, 1 );
+                                       return;
+                               }
+                       }
+               }
+
+               self = $.extend( {}, mw.eventLog, {
+                       /**
+                        * Transfer data to a remote server by making a 
lightweight
+                        * HTTP request to the specified URL.
+                        *
+                        * @param {string} url URL to request from the server.
+                        */
+                       sendBeacon: function ( url ) {
+                               // increase deliverability guarantee of events 
fired
+                               // close to page unload, while adding some 
latency
+                               // and chance of duplicate events
+                               var img = document.createElement( 'img' ),
+                                       handler = function () { remove( url ); 
};
+
+                               add( url );
+                               img.addEventListener( 'load', handler );
+                               img.addEventListener( 'error', handler );
+                               img.setAttribute( 'src', url );
+                       },
+
+                       /**
+                        * Construct and transmit to a remote server a record 
of some event
+                        * having occurred.
+                        *
+                        * This is a direct copy of mw.eventLog.logEvent. It is 
necessary
+                        * to override the call to sendBeacon.
+                        *
+                        * @param {string} schemaName
+                        * @param {Object} eventData
+                        * @return {jQuery.Promise}
+                        */
+                       logEvent: function ( schemaName, eventData ) {
+                               var event = self.prepare( schemaName, eventData 
),
+                                       url = self.makeBeaconUrl( event ),
+                                       sizeError = self.checkUrlSize( 
schemaName, url ),
+                                       deferred = $.Deferred();
+
+                               if ( !sizeError ) {
+                                       self.sendBeacon( url );
+                                       deferred.resolveWith( event, [ event ] 
);
+                               } else {
+                                       deferred.rejectWith( event, [ event, 
sizeError ] );
+                               }
+                               return deferred.promise();
+                       }
+               } );
+
+               $( document ).ready( function () {
+                       var i,
+                               queue = mw.storage.get( queueKey );
+
+                       if ( queue ) {
+                               mw.storage.remove( queueKey );
+                               for ( i = 0; i < queue.length; i++ ) {
+                                       self.sendBeacon( queue[ i ] );
+                               }
+                       }
+               } );
+
+               $( window ).on( 'beforeunload', function () {
+                       if ( localQueue.length > 0 ) {
+                               mw.storage.set(
+                                       queueKey,
+                                       localQueue.concat( mw.storage.get( 
queueKey ) || [] )
+                               );
+                       }
+               } );
+
+               return self;
+       }
+
        function genLogEventFn( source, session ) {
                return function ( action, extraData ) {
                        var scrollTop = $( window ).scrollTop(),
@@ -274,7 +388,8 @@
 
                        // ship the event
                        mw.loader.using( [ 'schema.TestSearchSatisfaction2' ] 
).then( function () {
-                               mw.eventLog.logEvent( 
'TestSearchSatisfaction2', evt );
+                               eventLog = eventLog || extendMwEventLog();
+                               eventLog.logEvent( 'TestSearchSatisfaction2', 
evt );
                        } );
                };
        }
@@ -298,7 +413,12 @@
                                'click',
                                '.mw-search-result-heading a',
                                { wprovPrefix: search.wprovPrefix },
-                               updateSearchHref
+                               function ( evt ) {
+                                       updateSearchHref( evt );
+                                       logEvent( 'click', {
+                                               position: $( evt.target ).data( 
'serp-pos' );
+                                       } );
+                               }
                        );
                        logEvent( 'searchResultPage', {
                                query: mw.config.get( 'searchTerm' ),
@@ -352,6 +472,9 @@
                                // to the link so we know when the user arrives 
they came from autocomplete
                                // and what position they clicked.
                                data.formData.linkParams.wprov = 
autoComplete.wprovPrefix + data.index;
+                               logEvent( 'click', {
+                                       position: data.index,
+                               } );
                        }
 
                } );

-- 
To view, visit https://gerrit.wikimedia.org/r/270879
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I32c69a6e7a6144a3221e2059b855a0c2516e4548
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/WikimediaEvents
Gerrit-Branch: master
Gerrit-Owner: EBernhardson <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to