{"id":18521717,"url":"https://github.com/transferwise/mitosis","last_synced_at":"2025-04-09T09:33:20.646Z","repository":{"id":55535816,"uuid":"72776006","full_name":"transferwise/mitosis","owner":"transferwise","description":"A/B split filter","archived":true,"fork":false,"pushed_at":"2024-04-04T23:41:39.000Z","size":96,"stargazers_count":2,"open_issues_count":2,"forks_count":4,"subscribers_count":115,"default_branch":"master","last_synced_at":"2025-03-03T04:44:56.001Z","etag":null,"topics":["ab-testing","filter"],"latest_commit_sha":null,"homepage":null,"language":"Groovy","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/transferwise.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-11-03T18:44:39.000Z","updated_at":"2024-08-30T15:35:02.000Z","dependencies_parsed_at":"2024-11-06T17:34:59.954Z","dependency_job_id":"9f2d1825-5869-4a8d-969f-216317432e17","html_url":"https://github.com/transferwise/mitosis","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/transferwise%2Fmitosis","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/transferwise%2Fmitosis/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/transferwise%2Fmitosis/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/transferwise%2Fmitosis/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/transferwise","download_url":"https://codeload.github.com/transferwise/mitosis/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248012861,"owners_count":21033254,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ab-testing","filter"],"created_at":"2024-11-06T17:27:12.666Z","updated_at":"2025-04-09T09:33:19.991Z","avatar_url":"https://github.com/transferwise.png","language":"Groovy","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Mitosis [![CircleCI](https://circleci.com/gh/transferwise/mitosis/tree/master.svg?style=shield)](https://circleci.com/gh/transferwise/mitosis/tree/master)\n\nA/B traffic split servlet filter.\n\n## Installation\n\nJust add the following configuration to your `build.gradle` file\n\n```gradle\nallprojects {\n    repositories {\n        maven { url 'https://jitpack.io' }\n    }\n}\n\ndependencies {\n    compile 'com.github.transferwise:mitosis:1.1.0'\n}\n```\n\n## Configuration\n\nIf we wanted to [uniformly distribute](https://en.wikipedia.org/wiki/Uniform_distribution_(continuous)) `a` and `b` variants for an experiment `test` across the requests of our application, the configuration would be\n\n```java\n@Bean\npublic Filter experimentFilter() {\n    return ExperimentFilter.builder().build()\n        .prepare(new UserExperiment(\"test\", asList([\"a\", \"b\"])));\n}\n```\n\nIf we wanted to uniformly distribute `a` and `b` variants for an experiment `test` across the request *paths* of our application, the configuration would be\n\n```java\npublic Filter experimentFilter() {\n    return ExperimentFilter.builder().build()\n        .prepare(new SeoExperiment(\"test\", asList([\"a\", \"b\"])));\n}\n```\n\nFor a SeoExperiment a given path will always return the same variant (unless overridden by request parameters).\n\n## Usage\n\nIn Spring controllers.\n\n```java\n@RequestMapping(\"/do-something\")\npublic String doSomething(@RequestAttribute(\"experiments\") Map\u003cString, String\u003e experiments) {\n    if (experiments.get(\"test\").equals(\"a\")) {\n        return goForVariantA();\n    }\n    if (experiments.get(\"test\").equals(\"b\")) {\n        return goForVariantB();\n    }\n}\n```\n\nIn Thymeleaf templates.\n\n```html\n\u003cdiv th:if=\"${experiments['test'] == 'a'}\"\u003e\n    This is the A version\n\u003c/div\u003e\n\n\u003cdiv th:if=\"${experiments['test'] == 'b'}\"\u003e\n    This is the B version\n\u003c/div\u003e\n\n\u003cscript th:inline=\"javascript\"\u003e\n    var experiments = [[${experiments}]];\n    if (experiments['test'] === 'a') {\n        goForVariantA();\n    }\n    if (experiments['test'] === 'b') {\n        goForVariantB();\n    }\n\u003c/script\u003e\n```\n\n## Forcing an experiment variant\n\nVariants are uniformly distributed automatically. A way of forcing a specific experiment variant, so you can share and preview the experiment, is to pass the preferred variant as a request parameter.\n\nIn an experiment configuration like the following\n\n```java\n@Bean\npublic Filter experimentFilter() {\n    return ExperimentFilter.builder().build()\n        .prepare(new UserExperiment(\"test1\", asList(\"a\", \"b\")))\n        .prepare(new UserExperiment(\"test2\", asList(\"c\", \"d\")));\n}\n```\n\nYou can force the test `test1` to variant `b` by setting the `activate` query parameter in the following way\n\n    https://yoursite.com/?activate=test1:b\n\nWorth mentioning that if you have multiple experiments running and you want to force multiple variants you can do\n\n    https://yoursite.com/?activate=test1:b,test2:c\n\n## Advanced use\n\nYou can use lambda functions to create more complex filters, so you will split your traffic only under controlled circumstances.\nLet's imagine you want to run your test only for people visiting some urls starting with \"/path\":\n\n\n```java \n@Bean\npublic Filter experimentFilter() {\n    return ExperimentFilter.builder().build()\n        .prepare(\"test\", asList(\"a\", \"b\"), r -\u003e r.getRequestURI().contains(\"/path\"));\n}\n\n``` \n \nWhen using lambda functions, the experiment variant will be assigned only if the function returns `true`. **Otherwise, no variant will be assigned**, so you need to handle within your logic.\n\nMitosis provides a handful request filters that can be combined at will. If we wanted to assign variants only to english-speaking users, excluding Googlebot crawler so our experiment won't affect SEO, we can configure the experiment in the following way\n\n```java\nfilter.prepare(\"test\", asList(\"a\", \"b\"), languageEquals(\"en\").and(userAgentContains(\"googlebot\").negate()));\n```\n\n## Cookie Consent\n\nWhen building the experiment filter you may optionally configure a cookie consent check.\n\nIf a cookie with the cookie consent cookie name does not exist then mitosis will not set any cookies.\n\nIf a cookie with the cookie consent cookie name does exist but the value of that cookie does not match the regex provided, mitosis will not set any cookies.\n\nNote that user experiments rely on cookies so may only be run on users who have accepted the cookie consent. SEO experiments do not rely on cookies.\n\nIf a cookie with the cookie consent cookie name does exist and the value of that cookie matches the regex provided, mitosis will operate as normal.\n\n```java\n@Bean\npublic Filter experimentFilter() {\n    return ExperimentFilter.builder()\n        .cookieConsent(\"consentCookie\", \"^1$\")\n        .build()\n        .prepare(\"test\", asList(\"a\", \"b\"));\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftransferwise%2Fmitosis","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftransferwise%2Fmitosis","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftransferwise%2Fmitosis/lists"}