What TETT Is
TETT (The Easiest Testing Tool) is a lean A/B testing tool that runs entirely in the visitor's browser: no backend, no database, no account behind it. You define experiments here, and the Deploy view turns them into a self-contained snippet that runs on your site's pages.
On each matching page load the snippet assigns each visitor to a variant before the first paint (deterministically, so the same visitor always sees the same variant), injects that variant's CSS and JS, and reports a self-contained tett_exposure event to the page's existing GTM/GA4 dataLayer. The assignment is remembered with one small functional cookie per experiment (a random ID, no PII).
Test mode (the Test Mode view) lets you force any variant on any page; forced visits push no analytics at all, so QA traffic can't pollute your numbers.
Why Deployment Is This Simple
All of TETT fits in one small piece of code on your site. There is no backend to run, no database to host and no account to sign up for: the experiments you build here are compiled into that one piece of code, and the Deploy view creates it for you.
- Automatic (PHP host): upload one small
tett.phpfile once, add one line to your pages'<head>, and every change you make is pushed straight to your site from this dashboard. - Snippet: one self-contained
<script>block in the<head>, for sites that don't update often. - Companion file: one file on your web server behind a single static script tag that never changes.
Updates take seconds. Pick a mode in the Deploy view, and the snippet, the download or the push is built from your current experiments in the browser, with no server of its own involved. Deactivated experiments are simply left out of the next push, so turning a test off is one click in the Experiments view.
Get Started
The pink button opens the experiment editor: name it, set the traffic share and the variant weights, add the CSS/JS for variant B, and the deploy code is ready in the Deploy view.
Experiments
Active experiments are what a push deploys. Deactivate one to disable it on the site with the next push; it stays in your list either way.
No experiments yet. Create one with the button above, or use the import tool below.
Import Experiments
Paste the URL of your page that already runs TETT. The dashboard fetches the page and reads its
window.TETT_CONFIG: either the TETT file the page loads via a <script> tag or, when the config
sits in an inline snippet in its <head>, that snippet, and adds the experiments here.
If the TETT file has a custom name, paste the file's URL directly.
Deploy and Update
Automatic: for when you update experiments regularly and the host site runs PHP.
A one-time tett.php endpoint on your sites server serves the experiments and rewrites
them on every push, so after setup every change is pushed from this dashboard.
Manual: for simple deployments that don’t update often. You place the code on the host
yourself, either as a self-contained snippet or as a companion file.
Snippet: one self-contained <script> block to paste into the host page’s
<head>; every config change means re-editing that HTML.
Companion file: config + runner live in one file on the host site’s web server, referenced by a one-line
script tag that never changes. The file itself must be re-uploaded on every change.
A push deploys every active experiment, and only those.
Paste this snippet into the <head> of your site, before the closing </head> tag. The complete TETT runner is inlined, so no external files are needed.
Add this one line to the page’s <head> (if the file lives at another path, edit the src in the line by hand):
Changed anything in the dashboard? Download the file again and upload it over the old one. That’s the whole update. The one-line script tag in the page never changes. If the file is ever missing or broken, the page simply runs without TETT.
One-time install only once
Pick a password you’ll remember (only its salted hash ends up in the file), download
tett.php and upload it to the host site’s web server. Forgot it later? Just pick a new one,
download a fresh tett.php and re-upload it over the old file, and everything keeps working.
Then add this one line to the page’s
<head> (edit the src by hand to match where you put the file). The endpoint
serves the experiment file itself, so this one line stays valid for every future push:
Push experiments with every change
Whenever you change the experiments, push: the endpoint updates your experiments in place, no re-uploading. Visitors pick the new version up within about five minutes (that’s how often the served file revalidates). The password is the one from the install step; it is hashed in this browser (SHA-256) and never stored or sent in plain. The URL is remembered on this device after a successful push.
How TETT talks to GTM
TETT pushes everything to the page's dataLayer:
- One
tett_exposureevent per experiment per route view. Each event is self-contained:experiment_id,variant,tett_user_idandexperiment_context, so a single custom-event trigger is all the exposure tag needs. - The route's
experiment_context(sortedid-variant|id-variant; empty on routes with nothing active, which clears the previous value) is also written as a root-leveldataLayervariable on every route view. That is what lets every later event on the route, conversions included, carry the visitor's full variant combination. - Test-mode visits push nothing, so QA traffic can't pollute your analytics.
| Key | What it is |
|---|---|
experiment_id | The experiment's ID, e.g. button_color_test. |
variant | The variant the visitor was assigned, e.g. B. |
tett_user_id | One site-wide pseudonymous visitor ID (a random value, no PII). Safe to map to GA4's user_id for cross-device attribution. |
experiment_context | Every experiment active on the route, sorted: exp1-A|exp2-B. Empty when none are active. |
That means you only need, in GTM: four data layer variables for those keys, one custom-event trigger on tett_exposure, and one GA4 event tag fired by it (plus the base Google Tag / gtag.js if GA4 is not running in your container yet). The setup file below generates exactly that, nothing more.
Setup file (import into GTM)
Generates a GTM import file with the exact TETT setup: the base Google Tag (gtag.js), four data layer variables, the tett_exposure trigger, and the GA4 event tag. Import it into your container with GTM's own Import and publish. No Google API access or OAuth needed.
How to import it into GTM
- Open the container's workspace, click Admin in the top navigation, and in the right panel's Settings press Import Container.
- Choose the downloaded file. If the workspace already has items, GTM asks whether to merge (add to it) or overwrite (replace it). Merge is safest for a container that already has tags; conflicting items are resolved manually.
- The items land in the workspace unpublished. Review them, then Publish the container.
The file includes the standard built-in variables (Event, Page URL, …), so an overwrite leaves a complete, working workspace.
Manual setup
Prefer to set it up by hand? Create these four items in GTM, in this order. Every name and key has a copy button, so you can paste it straight into the GTM UI.
1. Google Tag (gtag.js) only if your container has none yet
GTM: Tags > New > Google Tag.
This base tag loads the GA4 library, and the GA4 tag below needs it to run.
| Name | Google Tag (gtag.js) |
|---|---|
| Tag ID | Your GA4 Measurement ID, e.g. G-XXXXXXXXXX |
| Triggering | All Pages |
2. Data layer variables create 4, one per row
GTM: Variables > New > Data Layer Variable.
Copy the display name into the name field and the key into the Data Layer Variable name field.
| Display name | Data Layer Variable name |
|---|---|
DLV - experiment_id | experiment_id |
DLV - variant | variant |
DLV - tett_user_id | tett_user_id |
DLV - experiment_context | experiment_context |
3. Custom event trigger
GTM: Triggers > New > Custom Event.
Set Occurrence to Some and add the filter Event equals the event name below.
| Name | CE - tett_exposure |
|---|---|
| Custom event | tett_exposure |
4. GA4 event tag
GTM: Tags > New > GA4 Event.
It fires on the trigger from step 3.
| Name | GA4 - TETT Experiment Exposure |
|---|---|
| Event name | experiment_exposure or any name you like |
| Measurement ID | The same one as the Google Tag from step 1 |
| Triggering | CE - tett_exposure |
Event parameters, one row each:
| Parameter | Value |
|---|---|
experiment_id | {{DLV - experiment_id}} |
variant | {{DLV - variant}} |
tett_user_id | {{DLV - tett_user_id}} |
experiment_context | {{DLV - experiment_context}} |
Optional: also add a user property user_id set to {{DLV - tett_user_id}}. The ID is pseudonymous (no PII), so this enables attribution across devices.
Done? Review the workspace, then publish it in GTM.
Significance Calculator
Once an experiment has been running a while, filter GA4 by experiment_id and variant for each arm and note the Users (N) and your conversions (C). Enter both arms below: a two-proportion z-test (two-tailed, 95%) tells you whether the difference is real (p < 0.05), and the uplift tells you how big it is. Both matter: a big effect that isn't significant needs more traffic, and a tiny one that is significant may not be worth shipping.
Variant A (Control)
Variant B (Test)
Two-proportion z-test, two-tailed. Significant when p < 0.05 (95% confidence). Uplift = (p&sub2; − p&sub1;) / p&sub1;.
Live Status and Test Mode
Install the bookmarklet once by dragging it into your favorites bar, then click it on any page where TETT runs. It opens a live status panel for that page: when the deployed config was generated (a stale cached file is visible at a glance right after a push), each experiment's state (active, inactive, which variant is in effect, which pages it targets), and any runner errors (e.g. a variant's JS failing). The panel is also the test mode tool: pick an experiment and a variant, then open it in a new tab, apply it here, or copy the link. While a force is active on the page, a Stop test mode button appears.
No favorites bar in your browser? Press Ctrl+Shift+B to show it (works in all browsers). You can also right click it and copy manually.
Test without the bookmarklet
Paste the URL of a page that runs TETT. The dashboard fetches it, reads its window.TETT_CONFIG, and builds a forced test URL
from your pick below. The live status and runner errors require use of the bookmarklet, as they only exist once you are on the page.