jenkins-bot has submitted this change and it was merged.
Change subject: Allow measuring impact of section collapsing in
Schema:MobileWebSectionUsage
......................................................................
Allow measuring impact of section collapsing in Schema:MobileWebSectionUsage
* Update schema revision to 15038458;
* Trigger "scrolled-into-view" event when a heading is
scrolled into the user's viewport or is already in it;
* 50% of the sampled users will be bucketed as group A;
* Users in the A group will see sections expanded by default in stable
and while on a small screen;
* Make isUserInBucket method of the Schema public (update tests)
This experiment must be enabled via
$wgExperiments['sectionCollapsing']['enabled] = true
Bug: T120292
Change-Id: I91f82ed3c1bc7dcd70305a7e0baebd5e8b77068c
---
M includes/MobileFrontend.hooks.php
M includes/Resources.php
M includes/config/Experimental.php
M resources/mobile.startup/Schema.js
M resources/mobile.toggle/toggle.js
M tests/qunit/mobile.startup/test_Schema.js
6 files changed, 92 insertions(+), 14 deletions(-)
Approvals:
BryanDavis: Looks good to me, but someone else must approve
Jdlrobson: Looks good to me, approved
jenkins-bot: Verified
diff --git a/includes/MobileFrontend.hooks.php
b/includes/MobileFrontend.hooks.php
index 383d838..f2936e2 100644
--- a/includes/MobileFrontend.hooks.php
+++ b/includes/MobileFrontend.hooks.php
@@ -996,7 +996,7 @@
'MobileWebDiffClickTracking' => 10720373,
'MobileWebMainMenuClickTracking' => 11568715,
'MobileWebSearch' => 12054448,
- 'MobileWebSectionUsage' => 14321266,
+ 'MobileWebSectionUsage' => 15038458,
'MobileWebUIClickTracking' => 10742159,
'MobileWebWatching' => 11761466,
'MobileWebWatchlistClickTracking' => 10720361,
diff --git a/includes/Resources.php b/includes/Resources.php
index 591b057..5bdd878 100644
--- a/includes/Resources.php
+++ b/includes/Resources.php
@@ -922,7 +922,7 @@
'mobile.toggle' => $wgMFResourceFileModuleBoilerplate + array(
'dependencies' => array(
'mobile.settings',
- // uses util.js
+ // uses util.js and jquery.throttle-debounce
'mobile.startup',
),
'styles' => array(
diff --git a/includes/config/Experimental.php b/includes/config/Experimental.php
index f230e1c..f9dbd8f 100644
--- a/includes/config/Experimental.php
+++ b/includes/config/Experimental.php
@@ -28,6 +28,15 @@
'A' => 0.03,
),
),
+ // A/B test that measures the impact of section collapsing by default
+ 'sectionCollapsing' => array(
+ 'name' => 'sectionCollapsing',
+ 'enabled' => false,
+ 'buckets' => array(
+ 'control' => 0.5,
+ 'A' => 0.5,
+ ),
+ ),
);
/**
diff --git a/resources/mobile.startup/Schema.js
b/resources/mobile.startup/Schema.js
index fe72c39..bcddb0d 100644
--- a/resources/mobile.startup/Schema.js
+++ b/resources/mobile.startup/Schema.js
@@ -82,9 +82,8 @@
/**
* Whether the user is bucketed.
* @returns {Boolean}
- * @private
*/
- _isUserInBucket: function () {
+ isUserInBucket: function () {
if ( mw.config.get( 'wgMFIgnoreEventLoggingBucketing' )
) {
return true;
} else if ( this._isInBucket === undefined ) {
@@ -127,7 +126,7 @@
var deferred = $.Deferred();
// Log event if logging schema is not sampled or if
user is in the bucket
- if ( !this.isSampled || this._isUserInBucket() ) {
+ if ( !this.isSampled || this.isUserInBucket() ) {
mw.track( 'event.' + this.name, $.extend( {},
this.defaults, data ) );
return deferred.resolve();
diff --git a/resources/mobile.toggle/toggle.js
b/resources/mobile.toggle/toggle.js
index ad51223..ded4d24 100644
--- a/resources/mobile.toggle/toggle.js
+++ b/resources/mobile.toggle/toggle.js
@@ -11,7 +11,8 @@
name: 'arrow',
additionalClassNames: 'indicator'
},
- Icon = M.require( 'mobile.startup/Icon' );
+ Icon = M.require( 'mobile.startup/Icon' ),
+ $window = $( window );
/**
* A class for enabling toggling
@@ -24,10 +25,10 @@
* @extends OO.EventEmitter
*/
function Toggler( $container, prefix, page, schema ) {
+ this.schema = schema;
OO.EventEmitter.call( this );
this._enable( $container, prefix, page );
if ( schema ) {
- this.schema = schema;
this.connect( this, {
toggled: 'onToggle'
} );
@@ -239,10 +240,13 @@
* @private
*/
Toggler.prototype._enable = function ( $container, prefix, page ) {
- var tagName, expandSections, indicator,
+ var tagName, expandSections, indicator, inSample,
$firstHeading,
self = this,
- collapseSectionsByDefault = mw.config.get(
'wgMFCollapseSectionsByDefault' );
+ collapseSectionsByDefault = mw.config.get(
'wgMFCollapseSectionsByDefault' ),
+ shouldLogScrolledIntoView = false,
+ experiments = mw.config.get( 'wgMFExperiments' ),
+ isTestA = false;
// Also allow .section-heading if some extensions like Wikibase
// want to toggle other headlines than direct descendants of
$container.
@@ -255,6 +259,20 @@
}
expandSections = !collapseSectionsByDefault ||
( context.isBetaGroupMember() && settings.get(
'expandSections', true ) === 'true' );
+
+ // A/B test to measure the impact of section collapsing
+ if ( self.schema && self.schema.isUserInBucket() &&
experiments.sectionCollapsing ) {
+ inSample = mw.experiments.getBucket(
experiments.sectionCollapsing, mw.user.sessionId() ) === 'A';
+
+ // Bucketed users who are in stable and using a small
screen device
+ // will see expanded sections by default
+ // @see T120292
+ if ( inSample && context.getMode() === 'stable' &&
!browser.isWideScreen() ) {
+ expandSections = true;
+ shouldLogScrolledIntoView = true;
+ isTestA = true;
+ }
+ }
$container.find( tagName ).each( function ( i ) {
var $heading = $( this ),
@@ -298,7 +316,7 @@
// Expand sections by default on wide
screen devices or if the expand sections setting is set
self.toggle.call( self, $heading );
}
-
+ logWhenHeadingIsScrolledIntoView( $heading, i,
isTestA );
}
} );
@@ -332,6 +350,58 @@
}
}
+ /**
+ * Check if at least half of the element's height and half of
its width are in viewport
+ *
+ * @method
+ * @param {jQuery.Object} $el - element that's being tested
+ * @return {Boolean}
+ */
+ function isElementInViewport( $el ) {
+ var windowHeight = $window.height(),
+ windowWidth = $window.width(),
+ windowScrollLeft = $window.scrollLeft(),
+ windowScrollTop = $window.scrollTop(),
+ elHeight = $el.height(),
+ elWidth = $el.width(),
+ elOffset = $el.offset();
+
+ return (
+ ( windowScrollTop + windowHeight >=
elOffset.top + elHeight / 2 ) &&
+ ( windowScrollLeft + windowWidth >=
elOffset.left + elWidth / 2 ) &&
+ ( windowScrollTop <= elOffset.top + elHeight /
2 )
+ );
+ }
+
+ /**
+ * Log when the heading is scrolled into the viewport
+ *
+ * @param {jQuery.Object} $heading
+ * @param {Number} sectionId that was scrolled into the viewport
+ * @param {Boolean} isTestA whether the user is in the A bucket
+ */
+ function logWhenHeadingIsScrolledIntoView( $heading, sectionId,
isTestA ) {
+ /**
+ * Log when a heading is seen by the user
+ * @ignore
+ */
+ function log() {
+ if ( isElementInViewport( $heading ) ) {
+ $window.off( 'scroll.' + $heading.attr(
'id' ), log );
+ self.schema.log( {
+ eventName: 'scrolled-into-view',
+ isTestA: isTestA,
+ section: sectionId
+ } );
+ }
+ }
+
+ if ( self.schema ) {
+ $window.on( 'scroll.' + $heading.attr( 'id' ),
$.debounce( 250, log ) );
+ log();
+ }
+ }
+
checkInternalRedirectAndHash();
checkHash( this );
// Restricted to links created by editors and thus outside our
control
diff --git a/tests/qunit/mobile.startup/test_Schema.js
b/tests/qunit/mobile.startup/test_Schema.js
index b3b36cf..97d1232 100644
--- a/tests/qunit/mobile.startup/test_Schema.js
+++ b/tests/qunit/mobile.startup/test_Schema.js
@@ -53,13 +53,13 @@
// Default sampling rate is 0.5, isSampled is true, and
Math.random returns 0.4
this.sandbox.stub( Math, 'random' ).returns( 0.4 );
- assert.strictEqual( testSchema._isUserInBucket(), true, 'user
is in bucket' );
+ assert.strictEqual( testSchema.isUserInBucket(), true, 'user is
in bucket' );
// Default sampling rate is 0.5, isSampled is true, and
Math.random returns 0.6
testSchema = new TestSchema();
Math.random.restore();
this.sandbox.stub( Math, 'random' ).returns( 0.6 );
- assert.strictEqual( testSchema._isUserInBucket(), false, 'user
is not in bucket' );
+ assert.strictEqual( testSchema.isUserInBucket(), false, 'user
is not in bucket' );
// Default sampling rate is 0.5, isSampled is false (default),
and Math.random returns 0.4
TestSchema = Schema.extend( {
@@ -68,7 +68,7 @@
testSchema = new TestSchema();
Math.random.restore();
this.sandbox.stub( Math, 'random' ).returns( 0.4 );
- assert.strictEqual( testSchema._isUserInBucket(), false, 'user
is not in bucket' );
+ assert.strictEqual( testSchema.isUserInBucket(), false, 'user
is not in bucket' );
} );
QUnit.test( '#log', 2, function ( assert ) {
@@ -90,7 +90,7 @@
} );
schema.isSampled = true;
- this.sandbox.stub( schema, '_isUserInBucket' ).returns( false );
+ this.sandbox.stub( schema, 'isUserInBucket' ).returns( false );
schema.log( event ).fail( function () {
assert.strictEqual(
--
To view, visit https://gerrit.wikimedia.org/r/257820
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I91f82ed3c1bc7dcd70305a7e0baebd5e8b77068c
Gerrit-PatchSet: 6
Gerrit-Project: mediawiki/extensions/MobileFrontend
Gerrit-Branch: master
Gerrit-Owner: Bmansurov <[email protected]>
Gerrit-Reviewer: Bmansurov <[email protected]>
Gerrit-Reviewer: BryanDavis <[email protected]>
Gerrit-Reviewer: Jdlrobson <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits