EBernhardson has uploaded a new change for review.
https://gerrit.wikimedia.org/r/248893
Change subject: Re-deploy WME changes after deploying necessary CirrusSearch
change first
......................................................................
Re-deploy WME changes after deploying necessary CirrusSearch change first
Revert "Revert "Rename search.js -> searchSatisfaction.js""
Revert "Revert "Move Schema:Search from CirrusSearch""
Revert "Revert "Refactor search.js to only load deps for users in test""
This reverts commit 43544897a443bd031179d7ba9a472b90f045d7ce.
This reverts commit ab73647d88246259d720bdb9f882d58c99bc0a61.
This reverts commit 2160b92b0160db81314042bab64b6214590ba914.
Change-Id: I205f41d5cecd425235bc718a5efa8f68e2561798
---
M WikimediaEvents.php
M modules/ext.wikimediaEvents.search.js
A modules/ext.wikimediaEvents.searchSatisfaction.js
3 files changed, 169 insertions(+), 105 deletions(-)
git pull
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/WikimediaEvents
refs/changes/93/248893/1
diff --git a/WikimediaEvents.php b/WikimediaEvents.php
index 2a0c0c3..a304498 100644
--- a/WikimediaEvents.php
+++ b/WikimediaEvents.php
@@ -95,6 +95,11 @@
'schema' => 'GeoFeatures',
'revision' => 12914994,
),
+ 'schema.Search' => array(
+ 'class' => 'ResourceLoaderSchemaModule',
+ 'schema' => 'Search',
+ 'revision' => 11670541,
+ ),
'ext.wikimediaEvents' => array(
// Loaded globally for all users (including logged-out)
// Don't remove if empty!
@@ -102,11 +107,12 @@
'ext.wikimediaEvents.resourceloader.js',
'ext.wikimediaEvents.searchSuggest.js',
'ext.wikimediaEvents.statsd.js',
+ 'ext.wikimediaEvents.searchSatisfaction.js',
'ext.wikimediaEvents.search.js',
),
'dependencies' => array(
- 'mediawiki.user', // needed by searchSuggest.js
- 'mediawiki.Uri', // needed by search.js
+ 'mediawiki.user', // needed by search.js,
searchSuggest.js
+ 'mediawiki.Uri', // needed by searchSatisfaction.js
),
'localBasePath' => __DIR__ . '/modules',
'remoteExtPath' => 'WikimediaEvents/modules',
diff --git a/modules/ext.wikimediaEvents.search.js
b/modules/ext.wikimediaEvents.search.js
index ac173f9..0edd61b 100644
--- a/modules/ext.wikimediaEvents.search.js
+++ b/modules/ext.wikimediaEvents.search.js
@@ -1,111 +1,58 @@
-/*!
- * Javacsript module for measuring internal search bounce rate and dwell time.
- *
- * @license GNU GPL v2 or later
- * @author Erik Bernhardson <[email protected]>
- */
-( function ( mw, $, undefined ) {
- var isSearchResultPage = mw.config.get( 'wgIsSearchResultPage' ),
- uri = new mw.Uri( location.href ),
- cameFromSearchResult = uri.query.wprov === 'cirrus';
+/*global mw:true */
+( function ( $ ) {
+ 'use strict';
- function oneIn( populationSize ) {
- return Math.floor( Math.random() * populationSize ) === 0;
- }
+ var defaults, depsPromise, sessionStartTime,
+ getRandomToken = function () {
+ return mw.user.generateRandomSessionId() + ( new Date()
).getTime().toString();
+ },
+ oneIn = function ( populationSize ) {
+ var rand = parseInt(
mw.user.generateRandomSessionId().slice( 0, 13 ), 16 );
+ return rand % populationSize === 0;
+ },
+ isLoggingEnabled = mw.config.get(
'wgCirrusSearchEnableSearchLogging' );
- if ( cameFromSearchResult ) {
- // cleanup the location bar in supported browsers
- if ( window.history.replaceState ) {
- delete uri.query.wprov;
- window.history.replaceState( {}, '', uri.toString() );
- }
- } else if ( !isSearchResultPage ) {
+ // For 1 in a 1000 users the metadata about interaction
+ // with the search form (absent search terms) is event logged.
+ // See https://meta.wikimedia.org/wiki/Schema:Search
+ if ( !isLoggingEnabled || !oneIn( 1000 ) ) {
return;
}
- mw.loader.using( [
- 'jquery.jStorage',
- 'mediawiki.user',
- 'ext.eventLogging',
- 'schema.TestSearchSatisfaction2'
- ] ).then( function () {
- var searchSessionId = $.jStorage.get( 'searchSessionId' ),
- sessionLifetimeMs = 10 * 60 * 1000,
- checkinTimes = [ 10, 20, 30, 40, 50, 60, 90, 120, 150,
180, 210, 240, 300, 360, 420 ],
- pageId = mw.user.generateRandomSessionId(),
- logEvent = function ( action, checkinTime ) {
- var evt = {
- // searchResultPage, visitPage
or checkin
- action: action,
- // identifies a single user
performing searches within
- // a limited time span.
- searchSessionId:
searchSessionId,
- // used to correlate actions
that happen on the same
- // page. Otherwise a user
opening multiple search results
- // in tabs would make their
events overlap and the dwell
- // time per page uncertain.
- pageId: pageId,
- // we noticed a number of
events get sent multiple
- // times from javascript,
especially when using sendBeacon.
- // This logId allows for later
deduplication
- logId:
mw.user.generateRandomSessionId()
- };
- if ( checkinTime !== undefined ) {
- evt.checkin = checkinTime;
- }
- mw.eventLog.logEvent(
'TestSearchSatisfaction2', evt );
- },
- updateHref = function () {
- var uri = new mw.Uri( this.href );
- // try to not add our query param to
unnecessary places
- if ( uri.path.substr( 0, 6 ) === '/wiki/' ) {
- uri.query.wprov = 'cirrus';
- this.href = uri.toString();
- }
- };
+ depsPromise = mw.loader.using( [
+ 'schema.Search',
+ 'ext.eventLogging'
+ ] );
- if ( searchSessionId === 'rejected' ) {
- // User was previously rejected or timed out
- return;
- } else if ( searchSessionId ) {
- // User was previously chosen to participate in the
test.
- // When a new search is performed reset the session
lifetime.
- if ( isSearchResultPage ) {
- $.jStorage.setTTL( 'searchSessionId',
sessionLifetimeMs );
- }
- } else if (
- // Most likely this means the users search session
timed out.
- !isSearchResultPage ||
- // user was not chosen in a sampling of search results
- !oneIn( 200 )
- ) {
- $.jStorage.set( 'searchSessionId', 'rejected', { TTL: 2
* sessionLifetimeMs } );
- return;
- } else {
- // User was chosen to participate in the test and does
not yet
- // have a search session id, generate one.
- searchSessionId = mw.user.generateRandomSessionId();
- $.jStorage.set( 'searchSessionId', searchSessionId, {
TTL: sessionLifetimeMs } );
- // If storage is full jStorage will fail to store our
session
- // identifier and it will come back null. In that case
we
- // can't reliably correlate events from the SERP to the
target
- // pages.
- if ( $.jStorage.get( 'searchSessionId' ) !==
searchSessionId ) {
- return;
- }
+ defaults = {
+ platform: 'desktop',
+ userSessionToken: getRandomToken(),
+ searchSessionToken: getRandomToken()
+ };
+
+ mw.trackSubscribe( 'mediawiki.searchSuggest', function ( topic, data ) {
+ var loggingData = {
+ action: data.action
+ };
+
+ if ( data.action === 'session-start' ) {
+ // update session token if it's a new search
+ defaults.searchSessionToken = getRandomToken();
+ sessionStartTime = this.timeStamp;
+ } else if ( data.action === 'impression-results' ) {
+ loggingData.numberOfResults = data.numberOfResults;
+ loggingData.resultSetType = data.resultSetType;
+ loggingData.timeToDisplayResults = Math.round(
this.timeStamp - sessionStartTime );
+ } else if ( data.action === 'click-result' ) {
+ loggingData.clickIndex = data.clickIndex;
+ loggingData.numberOfResults = data.numberOfResults;
+ } else if ( data.action === 'submit-form' ) {
+ loggingData.numberOfResults = data.numberOfResults;
}
-
- $( '#mw-content-text a:not(.external)' ).each( updateHref );
-
- if ( isSearchResultPage ) {
- logEvent( 'searchResultPage' );
- } else {
- logEvent( 'visitPage' );
- $( checkinTimes ).each( function ( _, checkin ) {
- setTimeout( function () {
- logEvent( 'checkin', checkin );
- }, 1000 * checkin );
- } );
- }
+ loggingData.timeOffsetSinceStart = Math.round( this.timeStamp -
sessionStartTime ) ;
+ $.extend( loggingData, defaults );
+ depsPromise.then( function () {
+ mw.eventLog.logEvent( 'Search', loggingData );
+ } );
} );
-}( mediaWiki, jQuery ) );
+}( jQuery ) );
diff --git a/modules/ext.wikimediaEvents.searchSatisfaction.js
b/modules/ext.wikimediaEvents.searchSatisfaction.js
new file mode 100644
index 0000000..ac173f9
--- /dev/null
+++ b/modules/ext.wikimediaEvents.searchSatisfaction.js
@@ -0,0 +1,111 @@
+/*!
+ * Javacsript module for measuring internal search bounce rate and dwell time.
+ *
+ * @license GNU GPL v2 or later
+ * @author Erik Bernhardson <[email protected]>
+ */
+( function ( mw, $, undefined ) {
+ var isSearchResultPage = mw.config.get( 'wgIsSearchResultPage' ),
+ uri = new mw.Uri( location.href ),
+ cameFromSearchResult = uri.query.wprov === 'cirrus';
+
+ function oneIn( populationSize ) {
+ return Math.floor( Math.random() * populationSize ) === 0;
+ }
+
+ if ( cameFromSearchResult ) {
+ // cleanup the location bar in supported browsers
+ if ( window.history.replaceState ) {
+ delete uri.query.wprov;
+ window.history.replaceState( {}, '', uri.toString() );
+ }
+ } else if ( !isSearchResultPage ) {
+ return;
+ }
+
+ mw.loader.using( [
+ 'jquery.jStorage',
+ 'mediawiki.user',
+ 'ext.eventLogging',
+ 'schema.TestSearchSatisfaction2'
+ ] ).then( function () {
+ var searchSessionId = $.jStorage.get( 'searchSessionId' ),
+ sessionLifetimeMs = 10 * 60 * 1000,
+ checkinTimes = [ 10, 20, 30, 40, 50, 60, 90, 120, 150,
180, 210, 240, 300, 360, 420 ],
+ pageId = mw.user.generateRandomSessionId(),
+ logEvent = function ( action, checkinTime ) {
+ var evt = {
+ // searchResultPage, visitPage
or checkin
+ action: action,
+ // identifies a single user
performing searches within
+ // a limited time span.
+ searchSessionId:
searchSessionId,
+ // used to correlate actions
that happen on the same
+ // page. Otherwise a user
opening multiple search results
+ // in tabs would make their
events overlap and the dwell
+ // time per page uncertain.
+ pageId: pageId,
+ // we noticed a number of
events get sent multiple
+ // times from javascript,
especially when using sendBeacon.
+ // This logId allows for later
deduplication
+ logId:
mw.user.generateRandomSessionId()
+ };
+ if ( checkinTime !== undefined ) {
+ evt.checkin = checkinTime;
+ }
+ mw.eventLog.logEvent(
'TestSearchSatisfaction2', evt );
+ },
+ updateHref = function () {
+ var uri = new mw.Uri( this.href );
+ // try to not add our query param to
unnecessary places
+ if ( uri.path.substr( 0, 6 ) === '/wiki/' ) {
+ uri.query.wprov = 'cirrus';
+ this.href = uri.toString();
+ }
+ };
+
+ if ( searchSessionId === 'rejected' ) {
+ // User was previously rejected or timed out
+ return;
+ } else if ( searchSessionId ) {
+ // User was previously chosen to participate in the
test.
+ // When a new search is performed reset the session
lifetime.
+ if ( isSearchResultPage ) {
+ $.jStorage.setTTL( 'searchSessionId',
sessionLifetimeMs );
+ }
+ } else if (
+ // Most likely this means the users search session
timed out.
+ !isSearchResultPage ||
+ // user was not chosen in a sampling of search results
+ !oneIn( 200 )
+ ) {
+ $.jStorage.set( 'searchSessionId', 'rejected', { TTL: 2
* sessionLifetimeMs } );
+ return;
+ } else {
+ // User was chosen to participate in the test and does
not yet
+ // have a search session id, generate one.
+ searchSessionId = mw.user.generateRandomSessionId();
+ $.jStorage.set( 'searchSessionId', searchSessionId, {
TTL: sessionLifetimeMs } );
+ // If storage is full jStorage will fail to store our
session
+ // identifier and it will come back null. In that case
we
+ // can't reliably correlate events from the SERP to the
target
+ // pages.
+ if ( $.jStorage.get( 'searchSessionId' ) !==
searchSessionId ) {
+ return;
+ }
+ }
+
+ $( '#mw-content-text a:not(.external)' ).each( updateHref );
+
+ if ( isSearchResultPage ) {
+ logEvent( 'searchResultPage' );
+ } else {
+ logEvent( 'visitPage' );
+ $( checkinTimes ).each( function ( _, checkin ) {
+ setTimeout( function () {
+ logEvent( 'checkin', checkin );
+ }, 1000 * checkin );
+ } );
+ }
+ } );
+}( mediaWiki, jQuery ) );
--
To view, visit https://gerrit.wikimedia.org/r/248893
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I205f41d5cecd425235bc718a5efa8f68e2561798
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/WikimediaEvents
Gerrit-Branch: wmf/1.27.0-wmf.3
Gerrit-Owner: EBernhardson <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits