Need help with touchstone?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

130 Stars 5 Forks Eclipse Public License 1.0 159 Commits 1 Opened issues


Split testing library for Clojure

Services available


Need anything else?

Contributors list

# 17,959
136 commits
# 68,890
1 commit

Taoensso open-source

CHANGELOG | API | current Break Version:

[com.taoensso/touchstone "2.0.2"] ; Stable

See here if you're interested in helping support my open-source work, thanks! - Peter Taoussanis

Touchstone: a split testing library for Clojure

A/B testing is great for conversion optimization. We should all be doing more of it. But traditional A/B tests can be a nuisance to setup and monitor.

Touchstone is an attempt to bring dead-simple, high-power split-testing to any Clojure web application. It uses multi-armed bandit techniques to provide fast, accurate, low-maintenance conversion optimization. The API is simple and highly flexible.

Library status

Last updated: Jan 2016

Haven't updated the lib in forever, but it's stable and works well in production. Do have some new stuff planned for a future update (particularly docs re: use with modern Cljs applications), but no ETA on that yet.

- Peter Taoussanis


  • Tiny, simple API
  • Great performance backed by Redis+Carmine
  • High flexibility (variations are arbitrary Clojure forms)
  • Low maintenace (fire-and-forget, automatic-selection algorithm)
  • Fire-and-forget multivariate testing
  • Advanced capabilities like test composition (dependent tests), arbitrary scoring, engagement testing, etc.
  • Ring middleware

Getting started

Add the necessary dependency to your project:

Leiningen: [com.taoensso/touchstone "2.0.2"] ; or
deps.edn:   com.taoensso/touchstone {:mvn/version "2.0.2"}

And setup your namespace imports:

(ns my-ns
  (:require [taoensso.touchstone :as touchstone :refer (*ts-id*)]))


Traditional split-testing consists of 4 steps:

  1. Defining content variations (e.g. possible labels for a sign-up button)
  2. Distributing content variations to test subjects (our users)
  3. Recording events of interest (sign-ups) by variation
  4. Analyzing the results and adopting our most successful content (best button label)

The particular multi-armed bandit technique used by Touchstone means that we only concern ourselves with steps 1 and 3. Steps 2 and 4 are handled automatically by the algorithm.

To optimize a Ring web application

Start by adding

to your middleware stack.

One or more test selectors can then be used as part of your page content:

  {:conn-opts {} ; Optional, as per Carmine's `wcar` conn-opts
  *ts-id* ; Dynamic test-subject-id (assigned by middleware)
  :my-app/landing.buttons.sign-up ; Test id
  :sign-up  "Sign-up!"   ; Named variation #1
  :join     "Join!"      ; Named variation #2
  :join-now "Join now!"  ; Named variation #3

And relevant events (e.g. conversions) recorded:

;; On sign-up button click, etc.:
  {} ; Same opts as given to `mab-select`
  *ts-id* :my-app/landing.buttons.sign-up 1)

Touchstone will now automatically start using accumulated statistical data to optimize the selection of the

test variations for maximum clicks.

And you're done! That's literally all there is to it.

See the

API docs for info on more advanced capabilities like multivariate testing, test composition (dependent tests), arbitrary scoring, engagement testing, etc.

Contacting me / contributions

Please use the project's GitHub issues page for all questions, ideas, etc. Pull requests welcome. See the project's GitHub contributors page for a list of contributors.

Otherwise, you can reach me at Happy hacking!

- Peter Taoussanis


Distributed under the EPL v1.0 (same as Clojure).
Copyright © 2012-2020 Peter Taoussanis.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.