{"id":13468855,"url":"https://github.com/elbywan/yett","last_synced_at":"2025-05-15T14:07:02.708Z","repository":{"id":40993415,"uuid":"136006508","full_name":"elbywan/yett","owner":"elbywan","description":"🔐A small webpage library to control the execution of (third party) scripts","archived":false,"fork":false,"pushed_at":"2024-09-14T10:28:11.000Z","size":567,"stargazers_count":800,"open_issues_count":9,"forks_count":73,"subscribers_count":40,"default_branch":"master","last_synced_at":"2025-05-15T14:06:50.601Z","etag":null,"topics":["analytics","block","blocker","gdpr","privacy","rgpd","tracking"],"latest_commit_sha":null,"homepage":"https://elbywan.github.io/yett/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/elbywan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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,"zenodo":null}},"created_at":"2018-06-04T10:03:05.000Z","updated_at":"2025-04-07T14:33:14.000Z","dependencies_parsed_at":"2024-01-11T08:49:08.426Z","dependency_job_id":"dbfab96f-7d95-4a67-87d7-aa2c10182b3c","html_url":"https://github.com/elbywan/yett","commit_stats":{"total_commits":102,"total_committers":6,"mean_commits":17.0,"dds":"0.23529411764705888","last_synced_commit":"43a89339d8dea0e89038632a21a2a5b9a929f855"},"previous_names":["snipsco/yett"],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elbywan%2Fyett","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elbywan%2Fyett/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elbywan%2Fyett/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elbywan%2Fyett/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/elbywan","download_url":"https://codeload.github.com/elbywan/yett/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254355335,"owners_count":22057354,"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":["analytics","block","blocker","gdpr","privacy","rgpd","tracking"],"created_at":"2024-07-31T15:01:20.519Z","updated_at":"2025-05-15T14:06:57.697Z","avatar_url":"https://github.com/elbywan.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n  Yett\u003cbr\u003e\n  \u003cbr\u003e\n  \u003ca href=\"https://www.npmjs.com/package/yett\"\u003e\u003cimg alt=\"npm-badge\" src=\"https://img.shields.io/npm/v/yett.svg\" height=\"20\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/elbywan/yett/blob/master/LICENSE\"\u003e\u003cimg alt=\"license-badge\" src=\"https://img.shields.io/npm/l/yett.svg\" height=\"20\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://bundlephobia.com/result?p=yett\"\u003e\u003cimg alt=\"size-badge\" src=\"https://img.shields.io/bundlephobia/minzip/yett.svg\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://app.travis-ci.com/elbywan/yett\"\u003e\u003cimg src=\"https://app.travis-ci.com/elbywan/yett.svg?branch=master\" alt=\"ci-badge\" height=\"20\"\u003e\u003c/a\u003e\n  \u003ca href=\"#browser-compatibility\"\u003e\u003cimg src=\"https://badges.herokuapp.com/browsers?firefox=60\u0026googlechrome=66\u0026safari=11\u0026iexplore=!9,!10,11\u0026microsoftedge=17\" alt=\"bundle-badge\" height=\"20\"\u003e\u003c/a\u003e\n\u003c/h1\u003e\n\n### 🔐 A small webpage library to control the execution of (third party) scripts like analytics\n\n##### Simply drop yett at the top of your html and it will allow you to block and delay the execution of other scripts.\n\n## Background\n\n[❓] **`So, why on Earth would I want to block scripts on my own website?`**\n\nOne way to use `yett` would be to build a [GDPR compliant consent-first-analytics](https://medium.com/snips-ai/gdpr-compliant-website-analytics-putting-users-in-control-684b17a1463f), via an UI like below.\n\n\u003cbr\u003e\n\n\u003cimg src=\"/privacy-bar.png\" alt=\"bar\"\u003e\u003c/img\u003e\n\u003ch6 align=\"center\"\u003e\u003ci\u003eAnalytics scripts are blocked until users Accepts, (previously) in production at \u003ca href=\"https://snips.ai\"\u003ehttps://snips.ai\u003c/a\u003e\u003c/i\u003e\u003c/h6\u003e\n\n\u003cbr\u003e\n\nBlocking execution of analytics script (until consent is given) can be done manually, but the problem is that analytics providers often provide minified code embeds that you have to include in your html as they are. If you want to exercise control over their execution, then you have to tamper with this minified JS yourself, which is complex and does not scale well if you load several 3rd party scripts.\n\nAnother thing to consider is that these scripts first setup a local buffer that record user actions locally, and then upload the data only after a remote script is loaded asynchronously. Meaning that if the whole thing is simply wrapped inside a callback *(as some other libraries do)* then every action performed by the user on the web page before the callback gets executed won't get recorded and will never appear in your analytics dashboard.\n\nThus we invented `yett`. Just drop in the script and define a domain blacklist - `yett` will take care of the rest ✨.\n\n------\n\nAnd on a side note, it is technically quite amazing to know that **[a few lines of js](https://medium.com/snips-ai/how-to-block-third-party-scripts-with-a-few-lines-of-javascript-f0b08b9c4c0)** is all you need to control execution of other scripts, even those included with a script tag. 😉\n\n##### *Also, [yett](https://en.wikipedia.org/wiki/Yett) has an interesting meaning.*\n\n## Usage\n\n#### [:tv: Demo](https://elbywan.github.io/yett/)\n\n#### Small example\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n  \u003chead\u003e\n    \u003c!-- Regular head items here… --\u003e\n\n    \u003c!-- 1) Add a blacklist --\u003e\n    \u003cscript\u003e\n      window.YETT_BLACKLIST = [\n        /my-blacklisted-domain/,\n      ]\n      // Or a whitelist\n      window.YETT_WHITELIST = [\n        /my-whitelisted-domain/,\n      ]\n    \u003c/script\u003e\n    \u003c!-- 2) Include Yett --\u003e\n    \u003cscript src=\"https://unpkg.com/yett\"\u003e\u003c/script\u003e\n    \u003c!-- If you target only modern browsers (!= IE) you should use the following version. It is way smaller! --\u003e\n    \u003c!-- \u003cscript src=\"https://unpkg.com/yett/dist/yett.min.modern.js\"\u003e\u003c/script --\u003e\n    \u003c!-- 3) Profit! --\u003e\n    \u003c!-- This script is blocked --\u003e\n    \u003cscript src=\"https://my-blacklisted-domain.com/file.js\"\u003e\u003c/script\u003e\n    \u003cscript\u003e\n      // This one too\n      (function() {\n        var script = document.createElement('script')\n        script.setAttribute('src', 'https://my-blacklisted-domain.com/some-file.js')\n        script.setAttribute('type', 'application/javascript')\n        document.head.appendChild(script)\n      })()\n    \u003c/script\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003cbutton onclick=\"window.yett.unblock()\"\u003eUnblock\u003c/button\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n**⚠️ It is strongly recommended (but not necessary) that you [add type attributes](https://github.com/elbywan/yett#add-a-type-attribute-manually) to `\u003cscript\u003e` tags having src attributes that you want to block. It has the benefit of preventing the scripts from begin downloaded in major browsers.**\n\n**💡 In any case, if you would like to ensure that cookies are not sent to third-party servers during the initial request you can use the [`crossorigin=\"anonymous\"`](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/crossorigin) attribute. Check [this link](https://github.com/elbywan/yett/issues/20#issuecomment-599256485) for more details.**\n\n## Add a blacklist\n\nYett needs a `blacklist`, which is an array of regexes to test urls against.\n\n```html\n\u003cscript\u003e\n    // Add a global variable *before* yett is loaded.\n    YETT_BLACKLIST = [\n        /www\\.google-analytics\\.com/,\n        /piwik\\.php/,\n        /cdn\\.mxpnl\\.com/\n    ]\n    // OR\n    YETT_WHITELIST = [\n        /my-whitelisted-domain/\n    ]\n\u003c/script\u003e\n```\n\n### CDN\n\n\nFinally, include `yett` with a script tag **before** other scripts you want to delay:\n\n```html\n\u003cscript src='unpkg.com/yett'\u003e\u003c/script\u003e\n```\n\nThen, use `window.yett.unblock()` to resume execution of the blocked scripts.\n\n### NPM\n\nYou can also use npm to install yett:\n\n```bash\nnpm i yett\n```\n\n```js\nwindow.YETT_BLACKLIST = [\n    // ... //\n]\n// OR\nwindow.YETT_WHITELIST = [\n    // ... //\n]\n// Side effects here! Do not import more than once!\nimport { unblock } from 'yett'\n\nunblock()\n```\n\n### Unblock\n\n```js\nunblock(...scriptUrlsOrRegexes: (String | RegExp)[])\n```\n\n\u003e Unblocks blacklisted scripts.\n\nIf you don't specify a `scriptUrlsOrRegexes` argument, all the scripts that were previously blocked will be executed.\nOtherwise, the `scriptUrlsOrRegexes` provided will be either removed from the blacklist or added to the whitelist and executed.\n\n### Build locally\n\n```bash\n# Clone\ngit clone https://github.com/elbywan/yett\ncd yett\n# Install\npnpm i\n# Serves demo @ localhost:8080\npnpm dev\n# Build for release\npnpm build\n```\n\n## Browser compatibility\n\n|                        |                    `\u003cscript\u003e`                   |     `\u003cscript type=\"javascript/blocked\"\u003e`    |      `document.createElement('script')`     |\n|------------------------|:-----------------------------------------------:|:-------------------------------------------:|:-------------------------------------------:|\n| **Prevents loading**   | ![](https://badges.herokuapp.com/browsers?firefox=-60\u0026googlechrome=-66\u0026safari=-11\u0026iexplore=-11\u0026microsoftedge=-17) | ![](https://badges.herokuapp.com/browsers?firefox=60\u0026googlechrome=66\u0026safari=-11\u0026iexplore=-11\u0026microsoftedge=-17) | ![](https://badges.herokuapp.com/browsers?firefox=60\u0026googlechrome=66\u0026safari=11\u0026iexplore=-11\u0026microsoftedge=-17) |\n| **Prevents execution** | ![](https://badges.herokuapp.com/browsers?firefox=60\u0026googlechrome=66\u0026safari=11\u0026iexplore=11\u0026microsoftedge=17) | ![](https://badges.herokuapp.com/browsers?firefox=60\u0026googlechrome=66\u0026safari=11\u0026iexplore=11\u0026microsoftedge=17) | ![](https://badges.herokuapp.com/browsers?firefox=60\u0026googlechrome=66\u0026safari=11\u0026iexplore=11\u0026microsoftedge=17) |\n\nThe most 'advanced' javascript feature that `yett` uses is [MutationObserver](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver), which is compatible with all major browsers as well as `IE11`.\n\nIf you need `IE 9/10` compatibility, you will have to use a [polyfill](https://github.com/megawac/MutationObserver.js):\n\n```html\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/mutationobserver-shim/dist/mutationobserver.min.js\"\u003e\u003c/script\u003e\n```\n\n### Caveats\n\n#### Add a type attribute manually\n\nAdding this attribute prevents the browser from downloading the script on `Chrome` and `Firefox`.\n\n```html\n\u003cscript src=\"...\" type=\"javascript/blocked\"\u003e\u003c/script\u003e\n```\n\n#### Monkey patch\n\nThis library monkey patches `document.createElement`. No way around this.\n\nThis means that `yett` is not compatible with third-party browser extensions that also monkey patch this native browser function.\n\n#### Dynamic requests\n\nScripts loaded using XMLHttpRequest and Fetch are not blocked. It would be trivial to monkey patch them, but most tracking scripts are not loaded using these 2 methods anyway.\n\n## Suggestions\n\nIf you have any request or feedback for us feel free to open an [issue](https://github.com/elbywan/yett/issues)!\n\nSo far we’re using this library for analytics, but it could also be used to block advertising until consent, and other things we haven’t thought about yet. We’re excited to see what use cases the community comes up with!\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felbywan%2Fyett","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felbywan%2Fyett","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felbywan%2Fyett/lists"}