In T433431 we introduced reusable anyPageVisit.js instrumentation that allows experiments to easily produce specification-conforming page_visit events for calculating:
- Second day web reader retention
- Second week web reader retention
- 21-day web reader retention
- Daily Web Visit Rate
metrics in GrowthBook, just by writing:
const anyPageVisit = require( './anyPageVisit.js' ); mw.testKitchen.getExperiment( 'my-experiment' ).then( ( experiment ) => experiment.use( anyPageVisit ) );
To calculate metrics like "ratio of internally-to-externally-referred-or-direct page visits" (to be defined in GB), we would need to record referrer class in action_source for those page_visit events. Not all experiments will want this, so it should be optional and anyPageVisit should be configurable to record that when requested.
Notes
Noodlin' on implementation for a parameterized anyPageVisit:
** * @param {boolean} recordSpecialPageName - whether page_title contextual attribute * is included on visits to Special pages (disabled by default) * @param {boolean} recordRawReferrer - whether to record the referrer (raw) on page visits * @return {function(mw.testKitchen.EventSenderInterface): void} - the returned function */ function anyPageVisit( recordSpecialPageName = false, recordRawReferrer = false ) { const interactionData = {}; const pageVisitAttributes = [ 'page_namespace_id' // Required for metrics concerned with *article* visits specifically ]; if ( recordSpecialPageName ) { if ( mw.config.get( 'wgCanonicalSpecialPageName' ) ) { pageVisitAttributes.push( 'page_title' ); } } if ( recordRawReferrer ) { interactionData.action_source = document.referrer; } return ( eventSender ) => { eventSender.send( PAGE_VISIT_ACTION, interactionData, pageVisitAttributes ); }; }
Then to use it:
mw.testKitchen.getExperiment( 'my-experiment' ).then( ( experiment ) => experiment.use( anyPageVisit( recordRawReferrer = true ) ) );
Couple of points:
- We'll want to implement additional parameters over time, so the function signature should support that (maybe use spread syntax or a config parameter with keys like recordRawReferrer?)
- We don't actually want to record raw referrer, but rather a referrer class: "internal_referrer", "external_referrer", "no_referrer" (or "direct"?)
- We technically could do "external_search_referrer" and "external_social_referrer" as classes but IMO distinguishing the type of external referrer is not valuable for on-site experiments
- Dan A.'s pageVisitBotDetection.js may be a helpful reference
- Referrer classification should align with RefererClassifier.java (what we use for webrequest/pageview data)
- Should we consider a separate anyPageVisitWithReferrer reusable instrumentation, rather than parameterizing anyPageVisit?
- No, it's better to have a single parameterized/configurable one so we don't end up duplicating or fragmenting logic across multiple.
Acceptance criteria
- An experiment/instrument can use anyPageVisit to collect referrer class (see notes above) in action_source
- anyPageVisit does not record referrer class by default
- [[ https://codesearch.wmcloud.org/search/?q=anyPageVisit&files=&excludeFiles=&repos= | Anywhere anyPageVisit is used ]] should be updated for compatibility