This repository provides a template for building browser-based research studies with the Rally platform and the WebScience library.
Extension API capability | Example uses | On a regular website (davidxie.net) | On YouTube | Possible workaround |
---|---|---|---|---|
Get page visiting data when user begin visiting this page and stop visiting this page | Working | Referral URL is blank |
chrome.webNavigation API documentationPer this API documentation : “webpages and browsers are increasingly limiting when referrers are sent”
|
|
Check browser’s idling state and notify when this state changes, which can be used to gather whether user’s paying attention on a page. |
function idleStateChangeListener(idleState) {return console.log("Browser's Idle State: " + idleState);} webScience.idle.onStateChanged.addListener(idleStateChangeListener, {detectionInterval: 1}) |
Working (web page independent, but took about 3 minutes to observe browser idle state change; this timer is believed to be hard-coded on the browser itself, and there are other factors that would make this time vary). | Can also use chrome.idle.onStateChanged API |
|
Listen to Web Extension Event |
const pageVisitListener = function(details) {console.log("Page ID: " + details.pageId + ", Tab ID: " + details.tabId + ", windowID: " + details.windowId);} webScience.pageManager.onPageVisitStart.addListener(pageVisitListener, {privateWindows: false}); |
Not Tested (could not figure out creating web extension custom events (not DOM nor extension built-in event)) | ||
Store extension-generated data to local computer, use Associative Array data type (key-value pairs) |
Yes (web page independent). Should use this way to store data as user can use extension’s data export function to read it OR parse it into data analyzing programs.
const exampleStorage = webScience.storage.createKeyValueStorage("exampleName"); exampleStorage.set("exampleName", {key: 1, value: 2}).then(()=>console.log("Done Saving exampleName local storage")); |
|||
Detects whether user pauses/resumes data collection. | Yes (web page independent), this Mozilla extension will send a message when such state changes. | |||
Within background script, listen to messages from content script and respond accordingly. | Not tested, I recommend using Firefox extension’s native message-passing APIs, as it can easily send and receive JSON-formatted objects. | |||
Gather Links (that matches to a pattern) within this webpage |
const linkExposureDataListener = function (details) {console.log(details);} webScience.linkExposure.onLinkExposureData.addListener(linkExposureDataListener, {linkMatchPatterns: [ "*://*.youtube.com/*" ], privateWindows: true}) |
Unknown (attempted to use it but no result)
I do see this WebScience error: matchPatterns is undefined in the browser console. I have tried an approach by coping a code of a extension from Stanford but did not solve this issue)
I’ve also tried creating custom match pattern from following the tutorial here , but still no progress.
|
Use JavaScript native DOM API to query links within this webpage, but it might not work on hrefs that only contain relative link or no link but rather front-end framework page routers. | |
Parse article main text from a web page |
// Handle onTextParsed event callbacks
webScience.pageText.onTextParsed.addListener(async (pageData) => {const surveyUserID = await webScience.userSurvey.getSurveyId() const output = {"type" : "WebScience.articleContents","visitId" : pageData.pageId,"userId" : ""+surveyUserID,"url" : pageData.url,"title" : pageData.title,"textContent" : pageData.textContent} console.log(output);}, {matchPatterns: destinationDomains}); |
Same as above | ||
Get details regarding users’ basic page-browsing behaviors (such as the amount of time page had user attention and page playing audio) |
const pageDataListener = function(details) {console.log("PageDataListener Response");console.log(details);} webScience.pageNavigation.onPageData.addListener(pageDataListener, {matchPatterns: destinationDomains, privateWindows: false}); |
Same as above | ||
Listen to PageTransition actions (such as URL change through History API) |
const pageTransitionDataListener = function(details) {console.log("PageTransitionDataListener Response")console.log(details);} webScience.pageTransition.onPageTransitionData.addListener(pageTransitionDataListener, {matchPatterns: destinationDomains, privateWindows: false}); |
Same as above | ||
Observe whether a user left browser idle for a day or for a week |
webScience.scheduling.onIdleDaily.addListener((event)=>{console.log("You've been idled for a day")}); webScience.scheduling.onIdleWeekly.addListener((event)=>{console.log("You've been idled for a week")}); |
Both idle for a day listener and idle for a week listener are working | ||
Observe users’ link-sharing on social media |
// Social Media Sharing callback const socialMediaShareCallback = function(details) {console.log("From Social Media Sharing callback");console.log(details);} webScience.socialMediaLinkSharing.onShare(socialMediaShareCallback); |
NOT Working:
Extension builder will translate
webScience.socialMediaLinkSharing.onShare(socialMediaShareCallback); to
onShare(socialMediaShareCallback); , which would be nowhere defined.
|
Note: API author is making ground-breaking change on this API (see here) |
Chrome Extension API Reference (can directly use most syntax as-is in Firefox)
Utility features in WebScience that may not be necessary for this project
Extension API capability |
---|
Unified high-resolution timing |
Dispatch worker processes |
Prompt or remind participants to complete survey (located on an external URL). It highly unlikely supports local survey html files. |
Parse social media posts’ high-level content (supported platforms: Facebook, Twitter, and Reddit). Note: API author is making ground-breaking change on this API (see here) |
Assign different values to different study participants, particularly useful for A/B testing and experiment/control groups. I assume this is not needed because this YouTube misinformation study is an observational study not an experiment. |
Before working with this template, we recommend familiarizing yourself with the following concepts.
- Implementing Research Studies as Browser Extensions
- JavaScript - The scripting language commonly used for web applications, including browser extensions. Studies on Rally are implemented in JavaScript. If you haven't worked with JavaScript in awhile, we especially recommend catching up on modules, promises, and web workers, since those features are used in Rally, WebScience, and this template.
- WebExtensions - An API for building browser extensions. Each study on Rally is a separate extension. If you haven't worked with WebExtensions in awhile, we recommend reviewing the structure of browser extensions, including manifests, background scripts which run in a background page, and content scripts which run on ordinary pages.
- WebScience - A library for building browser-based research studies. WebScience provides production-quality functionality that is commonly required, difficult to implement correctly, and difficult to maintain.
- Rally SDK - A library for integrating your study with the Rally platform. Rally SDK communicates with the Rally Web Platform, which manages user enrollment.
- Building and Testing Research Study Browser Extensions
- ESLint - A linter for JavaScript. This template invokes ESLint with Node.js commands; you should not have to manually run ESLint or modify the ESLint configuration.
- Node.js - A JavaScript runtime for web applications. This template uses Node.js in two primary ways. First, Node.js provides a convenient toolkit for managing JavaScript library dependencies (see
npm
andpackage.json
). You can easily integrate Node.js packages from the npm public registry. Second, Node.js enables running build and test commands that are similar to makefile targets (see package scripts andnpm run
). You should not have to modify these Node.js commands. Note that this template does not use Node.js as a runtime for research studies. - Rollup - A module bundler for JavaScript. This template uses Rollup to merge module dependencies (either your own modules or npm modules) into a study extension and to remove unused code from dependencies. The template also enables using module depencies in content and worker scripts. You should not have to modify the Rollup configuration of the template.
- web-ext - A toolkit for building and testing browser extensions. This template invokes web-ext with Node.js commands; you should not have to modify the web-ext configuration.
This template includes the following files.
.eslintignore
and.eslintrc
- ESLint configuration. You should not have to modify these files..gitignore
- Git configuration. You should not not have to modify this file.CODE_OF_CONDUCT.md
- The code of conduct for the study extension. You should update this file to reflect your code of conduct.LICENSE
- The license for the study extension. You can use the provided license or your own license, so long as your license is compatible with Rally requirements and the licenses of dependencies.README.md
- A README for the study extension. You should update this file to describe your study and its implementation.manifest.json
- A WebExtensions manifest for the study. You should update thedescription
,author
,name
,version
, andhomepage_url
fields for your study. You can also updatepermissions
as necessary for implementing your study. The Rally team will provide a value for thebrowser_specific_settings.gecko.id
field.package.json
- A Node.js package configuration for the study. You should update thename
,version
,description
,repository
,keywords
,author
,license
,bugs
, andhomepage
fields. You should not have to update thescripts
field, which specifies a set of commands that function like makefile targets. You can adddependencies
for your study implementation, either manually or withnpm install
. Note that you must usenpm install
to install dependencies andnpm update
to update dependencies.package-lock.json
- A file automatically generated by Node.js package management that describes package dependencies. You should not have to manually edit this file.rollup.config.js
- A Rollup configuration for the study. You should not have to modify this file.web-ext-config.js
- A web-ext configuration for the study. This configuration will, on browser startup, automatically open both the Browser Console and Firefox Developer Tools for the background page. You should not have to modify this file..circleci/
- CircleCI configuration.config.yml
- A basic CircleCI configuration for the study template. You can use this file as a starting point for your own tests, or you can safely remove the file.
.github/
- GitHub configuration.dependabot.yml
- A GitHub dependency update configuration. You can use this file for managing dependency updates, or you can safely remove the file.
src/
- The source for the study implementation. You should include all your study JavaScript files in this directory, and you can optionally include non-JavaScript assets. The build system will bundle JavaScript files to the/dist
directory, as described below. The build system will also copy non-JavaScript assets (i.e., any files that do not end in.js
) to thedist/
directory.background.js
- The main background script for the study. The build system will bundle this script and output todist/background.js
. Note that the WebExtensions manifest already specifiesdist/background.js
as a background script for the extension.exampleContentScript.content.js
- An example content script for the study. The build system automatically recognizes a*.content.js
file as a content script, bundles it separately from the main background script, and outputs to the same relative path indist/
that the file has insrc/
. The build system will output this content script file, for example, todist/exampleContentScript.content.js
. We provide this functionality so that study content scripts can include module dependencies.exampleModule.js
- An example module for the study. The build system will bundle this module into the main background script; there is no separate output indist/
. If you want to split your background script implementation into multiple files, we recommend using modules imported intobackground.js
to benefit from performance optimizations in bundling, rather than using multiple background scripts specified inmanifest.json
.exampleWorkerScript.worker.js
- An example web worker script for the study. The build system treats*.worker.js
files the same way as*.content.js
files.
tests/integration/
- A basic Selenium integration test for the study template. You can use these files as a starting point for your own tests, or you can safely remove the files.
Prerequisites: current versions of Firefox and Node.js. You might find it helpful to install Node.js with a package manager, such as Scoop on Windows, Homebrew on macOS, or apt-get
on Ubuntu Linux.
- Either fork this repository or create a new repository from this template.
- Update the WebExtensions manifest (
manifest.json
) for your study. You should update thedescription
,author
,name
,version
, andhomepage_url
fields. The Rally team will provide a value for thebrowser_specific_settings.gecko.id
field. - Update the Node.js package configuration (
package.json
) for your study. You should update thename
,version
,description
,repository
,keywords
,author
,license
,bugs
, andhomepage
fields. - In the forked repository, run
npm install
to install Node.js package dependencies. A newnode_modules/
directory will be automatically populated with these dependencies. - Run
npm run dev
. The build system will build your study extension, launch Firefox with the study extension installed, and automatically open both the Browser Console and Firefox Developer Tools for the background page. - Commit your study extension to a repository! You now have a clean and functional starting point for implementing your study. If this template is updated in future, you can also easily merge those updates into your study.
This template comes with a set of predefined Node.js commands, which function similar to makefile targets. These commands should help you with study implementation, debugging, testing, and deployment. You run each command with npm run <command>
.
build
- Builds the study extension, by bundling JavaScript implementation insrc/
and copying non-JavaScript files. Output is in thedist/
directory.dev
- Bundles the study extension (likebuild
), but in developer mode, launch Firefox with the study extension installed, automatically rebuild the study if a file changes, and automatically reload the study in Firefox if the study is rebuilt. In developer mode, Rally SDK does not contact the website or the Firebase backend. Developer mode also provides a source map for bundled JavaScript, so you can use the Debugger as if the JavaScript were not bundled. You should typically use developer mode when implementing and testing your study.dev:emulator
- Likedev
, but run in emulator mode, which connects to a local Firebase emulator. See the Rally Web Platform docs for information on running a local Firebase emulator.lint
: Run linting on the study extension.package
: Build the study extension (build
), then package the built study into an archive for distribution. Output is in theweb-ext-artifacts/
directory.test:integration
: Packages the study extension (package
), then runs the provided integration test.
- Debugging the Background Script - Navigate to the browser debugging page (
about:debugging
), click This Firefox, then click Inspect on the study extension. The page that opens is Firefox Developer Tools for the background page, including a Web Console, JavaScript Debugger, and Network Monitor. Background script console output will also appear on the Browser Console. The template's web-ext configuration will automatically open both Firefox Developer Tools for the background page and the Browser Console on browser startup. - Debugging a Content Script - On a page where the content script is running, open Firefox Developer Tools. The Web Console will include output from the content script, and you can select the content script in the JavaScript Debugger. Content script console output will also appear on the Browser Console.