12789/feat/AB Testing#12788
Conversation
for more information, see https://pre-commit.ci
|
Thank you for this contribution, @Sadashii! Copilot has been assigned for an initial review. A reviewer must first be assigned to this PR. There are currently 71 open PRs of equal or higher priority ahead of yours in the queue. Possible improvements for this PR
PR triage checklist (maintainers / Pam)
Note This comment was automatically generated by Pam, Open Library's Project AI Manager, on behalf of @mekarpeles. Pam is designed to provide status visibility, perform basic project management functions and relevant codebase research, and provide actionable feedback so contributors aren't left waiting. |
There was a problem hiding this comment.
Pull request overview
Adds a deterministic A/B testing framework that assigns experiment variants consistently on both legacy web.py and FastAPI paths, and exposes the resulting assignments to templates and client-side code.
Changes:
- Introduces core experiment bucketing + override support (
openlibrary/core/experiments.py) with unit tests. - Injects evaluated experiments into legacy template context and serializes them into the page head as
window.OL_EXPERIMENTS, plus a JS helper (window.getExperiment/ ES module). - Adds FastAPI middleware to populate
request.state.experimentsfor ASGI requests.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| openlibrary/core/experiments.py | New deterministic bucketing + override evaluation for active experiments. |
| openlibrary/tests/core/test_experiments.py | Adds unit tests covering fallback behavior, distribution smoke test, and overrides. |
| openlibrary/plugins/openlibrary/processors.py | Adds a web.py processor to compute experiments and inject into web.ctx and infogami context. |
| openlibrary/plugins/openlibrary/code.py | Registers the new ExperimentsProcessor in the legacy processor chain. |
| openlibrary/templates/site/head.html | Serializes computed experiments into window.OL_EXPERIMENTS during page load. |
| openlibrary/plugins/openlibrary/js/experiments.js | Adds getExperiment() helper and exposes it on window. |
| openlibrary/plugins/openlibrary/js/index.js | Ensures experiments helper is bundled site-wide. |
| openlibrary/fastapi/middleware/experiments.py | Adds FastAPI middleware to compute experiments per request. |
| openlibrary/asgi_app.py | Registers the new FastAPI A/B testing middleware. |
| openlibrary/i18n/messages.pot | Updates POT output (currently appears truncated / incomplete). |
…d improve typing - Convert ABTestingMiddleware to pure ASGI middleware to reduce BaseHTTPMiddleware overhead. - Restrict and filter query overrides in both web.py and FastAPI to ignore non-experiment inputs and avoid reading POST bodies. - Update get_variant and get_user_experiments signatures to support str | None for user_identifier. - These changes are based on Copilot suggestions.
…alidation - Use built-in verify_session_cookie to prevent cookie spoofing without DB/cache lookup overhead - Use Literal for audience configuration targeting rules in ExperimentConfig - Update test cases to dynamically inject ACTIVE_EXPERIMENTS and support Audience logic - Reformat code to pass all ruff check, ruff format, and mypy pre-commit hooks Co-authored-by: Copilot Suggestions <support@copilot.github.com>
for more information, see https://pre-commit.ci
…tion, and clean up tests
for more information, see https://pre-commit.ci
| def json_encode(d, indent=0) -> str: | ||
| return json.dumps(d, indent=indent) | ||
| return json.dumps(d, indent=indent).replace("<", "\\u003c").replace(">", "\\u003e").replace("&", "\\u0026") |
There was a problem hiding this comment.
Not sure of simpler ways, do you have any recommendations?
Closes #12789
feat - This PR adds a deterministic client-and-server side A/B testing architecture.
Technical
web.py, theExperimentsProcessorpopulatesweb.ctx["experiments"]andinfogami.utils.context.context["experiments"](making variables directly accessible to Templetor templates/macros).FastAPI, theABTestingMiddlewareregisters variants on the ASGIrequest.state.experiments.window.OL_EXPERIMENTS) during page load. The helpergetExperimentis exposed onwindowand as an ES module for Vue, Lit, and jQuery components to consume synchronously.?experiment_[experiment_name]=[variant_name]format.Testing
http://localhost:8080/?experiment_AB_Testing=bwindow.OL_EXPERIMENTS(or callwindow.getExperiment('AB_Testing')) to verify it matches your query override.Screenshot
No visual UI updates are introduced; this is a behavioral framework change. Manual verification of the output via browser developer console:
Stakeholders