yett: holding third party scripts at the door until users consent
šA small webpage library to control the execution of (third party) scripts
At a glance
- What is it?
- yett is a small MIT licensed JavaScript library that blocks or delays third party scripts such as analytics until a page decides otherwise, using regex blacklists or whitelists. It solves the consent banner problem that minified vendor embeds create, and it does not solve the problem of a script that already ran.
- Who is it for?
- Adopt yett when you ship analytics or marketing embeds on a page that has to ask for consent first, and skip it when the scripts you care about are already inline or loaded before your tag, since the library only intercepts what it can reach. Verify first that your blacklist regexes match the exact URLs your vendors embed today, because the block happens on URL matching and a mismatch means a script runs unblocked.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 122 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A regex list decides which third party scripts wait
The library's entire configuration is one or two global variables holding arrays of regular expressions. You declare a blacklist before loading yett, include yett itself, and every script URL that matches is held back. The documentation puts it plainly: drop yett at the top of your HTML and it will block and delay the execution of other scripts.
<!DOCTYPE html>
<html>
<head>
<!-- 1) Add a blacklist -->
<script>
window.YETT_BLACKLIST = [
/my-blacklisted-domain/,
]
// Or a whitelist
window.YETT_WHITELIST = [
/my-whitelisted-domain/,
]
</script>
<!-- 2) Include Yett -->
<script src="https://unpkg.com/yett"></script>Both lists are optional in principle and either can be used. What is not optional is ordering: the variables must exist before yett runs, because the library reads them at load time. A blacklist entry such as `/www\.google-analytics\.com/` matches on the substring level, so it catches whichever path and query string the vendor embeds. The matching is done on URLs, not on script contents, which keeps the library small enough to sit in the critical path of every page.
Scripts blocked by tag are also blocked when created in code
Blocking a `<script>` tag is the easy case. The harder case is a script that a vendor snippet creates at runtime, appended to the document head after the page has already parsed. The library's example covers exactly that shape:
<!-- 3) Profit! -->
<!-- This script is blocked -->
<script src="https://my-blacklisted-domain.com/file.js"></script>The same page then creates a script element in JavaScript, sets a `src` and a type of `application/javascript`, and appends it to the head. Under yett that element does not run either. This matters because vendor embeds are rarely a single tag. They are a small loader that builds the real request itself, and a library that only patched the parser would let most of the traffic through.
The implementation lives in `src/`, is bundled by rollup into `dist/yett.min.js`, and the published npm package ships only the `dist` folder according to the `files` field in `package.json`. The library is loaded before the scripts it is meant to hold back, which is why the ordering constraint in the example is not a style preference but a requirement.
The buffering behaviour of analytics vendors is the real problem
The documentation explains why hand wrapping a vendor snippet in a callback is not enough. Analytics providers usually ship minified embeds that you have to paste into your HTML as they are, so controlling them means editing vendor code, which does not scale across several third party scripts.
The second problem is subtler and matters more. These scripts set up a local buffer that records user actions, and only upload the data after a remote script loads asynchronously. So if a whole integration is wrapped in a callback, every action a user performs before that callback fires is never recorded and never appears in your analytics dashboard. The data is lost at the source, not at the upload step.
yett sidesteps this by intercepting the script element itself rather than wrapping a call. The vendor's own loader code never runs, so no buffer is created and no buffer is discarded. The result is that no data is collected before consent and no data is lost after it. The repository topics name the use case directly, with `gdpr`, `rgpd`, `privacy`, `blocker` and `tracking`, and the README points at a consent first analytics pattern with a UI like the one in `privacy-bar.png`.
A type attribute stops the download, not only the execution
Blocking execution and blocking the network request are different things, and the browser compatibility table in the documentation draws that line. For a plain `<script>` tag, prevention of loading is only supported by older browsers in the table, while prevention of execution is broadly supported. For a script with the type `javascript/blocked`, both rows are supported in the modern browsers listed, with Internet Explorer excluded.
That is why the documentation strongly recommends adding type attributes to the script tags you want blocked, saying it has the benefit of preventing the scripts from being downloaded in major browsers. A blocked script that never leaves the browser is a different privacy outcome from one that is fetched and then not run.
A second detail is worth copying. If you want to be sure cookies are not sent to third party servers during the initial request, the documentation suggests the `crossorigin="anonymous"` attribute, linking to an issue comment for the full explanation. The library does not add that attribute for you.
There is also a second, smaller bundle, `dist/yett.min.modern.js`, described as the version to use if you target only modern browsers and not IE. The main entry stays the compatible build.
unblock() is the consent callback and it takes optional filters
Once the visitor accepts, the page calls `window.yett.unblock()`. The documented signature accepts optional script URLs or regexes.
unblock(...scriptUrlsOrRegexes: (String | RegExp)[])With no argument, every script that was previously blocked executes. With arguments, the given URLs are either removed from the blacklist or added to the whitelist and then executed. That second behaviour is the interesting one for a consent banner with categories: a visitor who refuses analytics can have those scripts released on request later, without a page reload and without reloading the whole vendor snippet.
The implementation is small enough that the API surface fits in a single function, which is the appeal. What it does not give you is a UI, a cookie policy text or a record of what was consented to. The consent logic and its storage stay in your application.
The npm build warns that importing it twice has side effects
Beyond the CDN tag, the library is published to npm as `yett` and can be installed with a single command.
npm i yettThe module form differs from the global form in one important respect. The package sets its global side effects when it loads, so the configuration is still declared on `window`.
window.YETT_BLACKLIST = [
// ... //
]
// OR
window.YETT_WHITELIST = [
// ... //
]
// Side effects here! Do not import more than once!
import { unblock } from 'yett'The comment in the example is explicit: importing more than once is not supported because of those side effects. In practice that means one import in your entry module, and the `unblock` function used from there. The `main` and `browser` fields both point at `dist/yett.min.js`, and the published `files` list contains only `dist`, so what you install is the bundle, not the source.
The package version in `package.json` is `0.2.3`, and the repository has no GitHub releases, so npm is the only channel through which a versioned build reaches you.
Local development runs rollup builds and karma across three browsers
The project is small enough to develop entirely locally, and the documentation gives the exact sequence.
git clone https://github.com/elbywan/yett
cd yett
pnpm i
pnpm devThe dev script serves the demo at localhost:8080 while watching for changes. Under the hood the `dev` script runs rollup in watch mode together with an HTTP server, and the build script runs linting before producing the bundles, including one written into `docs/` for the hosted demo page and another into `test/scripts/`.
Tests run under karma in Chrome, Firefox and Safari, in two modes. The `test` script chains a blacklist run and a whitelist run, and the whitelist run is selected by setting the `WHITELIST` environment variable. Both run with the single run flag. So the same codebase is exercised in both listing directions, which matches the design where either list can drive the behaviour.
The repository layout is consistent with that: `src/` for the library, `test/` with a karma configuration, `docs/` holding the hosted demo, plus `.babelrc`, `.eslintrc.json` and two rollup configurations, one of them dedicated to the modern browser build.
Editorial conclusion
Adopt yett when you ship analytics or marketing embeds on a page that has to ask for consent first, and skip it when the scripts you care about are already inline or loaded before your tag, since the library only intercepts what it can reach. Verify first that your blacklist regexes match the exact URLs your vendors embed today, because the block happens on URL matching and a mismatch means a script runs unblocked.
Frequently asked questions
How do I install and use yett on a page?
Install it with `npm i yett` or load it from a CDN with a script tag placed before the scripts you want to hold back. Then set `window.YETT_BLACKLIST` or `window.YETT_WHITELIST` to an array of regular expressions before yett loads, and call `window.yett.unblock()` when the visitor consents.
Does yett stop analytics scripts from loading or only from running?
Both, depending on how the tag is written. The compatibility table shows that prevention of execution is broadly supported, while prevention of the download needs a type attribute on the script tag, which the documentation strongly recommends.
Can I unblock only some scripts after the visitor accepts?
Yes. The `unblock` function accepts optional script URLs or regexes. Without arguments it releases every blocked script, and with arguments the matching scripts are removed from the blacklist or added to the whitelist and then executed.
What licence is yett published under and is it still worked on?
The licence is MIT, stated both in the `package.json` metadata and in the LICENSE file at the repository root. The repository is not archived and the last push was on 2026-06-23, with the npm package version at 0.2.3.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/elbywan-yett)Was this useful?