npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

weaveeye-scan

v0.3.1

Published

Fail your build when a tracker sends data before consent. A pre-consent tracking gate for CI (GDPR / ePrivacy / CIPA).

Readme

weaveeye-scan

Fail your build when a tracker sends data before consent.

A pre-consent tracking gate for CI. It loads your site in a real browser, detects and accepts the consent banner, and records every third party that fired before consent was given. If a consent-requiring tracker fired first, the build fails — with a millisecond-timestamped list of exactly which ones and who owns them.

This is the enforcement layer for the thing regulators and plaintiffs actually go after: pre-consent tracking under GDPR/ePrivacy in the EU and CIPA-style wiretapping claims in the US. A CMP tells you that you have a banner. This tells you whether the banner is actually holding trackers back — and keeps the next deploy from silently regressing it.

The WEAVEEYE project

WEAVEEYE checks whether a website loads trackers before the user consents — the pre-consent tracking that GDPR / ePrivacy and US CIPA lawsuits target. It has two halves, across three repos:

A scanner — point it at any URL and see, to the millisecond, what data went to third-party trackers before consent. The "see the problem" half.

A CI gate — the same check in your pipeline, failing the build when a tracker sends data before consent. The "stop the problem" half.

  • weaveeye-ci — this repo: the GitHub Action, published to npm as the CLI weaveeye-scan. (Action = mohitgauniyal/weaveeye-ci; CLI = npx weaveeye-scan. The Action does not require the npm package.)

Both halves share one detection engine (classification, CMP handling, verdict logic), so a finding in the scanner matches the CI gate. How classification works and what is / isn't claimed: METHODOLOGY. A sample scan of real sites: FINDINGS.

You're reading the docs for the CI gate (repo weaveeye-ci, npm weaveeye-scan).


Quick start

npx weaveeye-scan https://staging.example.com
WEAVEEYE consent scan — example.com

✗ NON-COMPLIANT  3 third parties received data before consent was given.
CMP: OneTrust   consent accepted at 4.2s   14 before / 22 after

Data sent to third parties before consent:
  FIRED  CATEGORY     DOMAIN                          OWNER              DATA
  340ms  Advertising  securepubads.g.doubleclick.net  Google / Alphabet  269KB
  520ms  Analytics    static.chartbeat.com            Chartbeat          100KB
  890ms  Data Broker  api.rlcdn.com                   LiveRamp           —

  Classification: 100% of these domains identified from curated data or public
  tracker databases (Disconnect.me, DuckDuckGo). Unknown domains are never flagged.

NON-COMPLIANT means "does not pass the policy you configured" (e.g. nothing before consent) — a check against your rule, not a legal ruling. See METHODOLOGY.md for exactly what is and isn't claimed.

Exit code is 0 if clean, 1 on a violation, 2 on an error — so it drops straight into any pipeline.


GitHub Action

# .github/workflows/consent.yml
on: pull_request
permissions:
  contents: read
  pull-requests: write

jobs:
  consent:
    runs-on: ubuntu-latest
    steps:
      - uses: mohitgauniyal/weaveeye-ci@v0
        with:
          url: https://your-preview-deploy.example.com

On a pull request it posts (and updates in place) a comment with the verdict and the full table of pre-consent trackers, and writes the same to the job summary. See .github/workflows/example-consent-gate.yml.

Action inputs

| Input | Default | Description | |---|---|---| | url | — (required) | URL to scan — typically your preview deployment. | | policy | auto | Path to a policy file. .weaveeye.yml is picked up automatically. | | fail-on | Advertising,Analytics,Data Broker | Categories that fail the build. | | allow | — | Comma-separated domains to exempt. | | inconclusive | warn | Treat INCONCLUSIVE as fail, warn, or pass. | | comment | true | Post/update a PR comment. | | github-token | ${{ github.token }} | Token used for the comment. |

Outputs: passed, verdict, violations.


Policy

Drop a .weaveeye.yml at your repo root (see the annotated .weaveeye.yml here). Everything is optional.

fail_on_categories: [Advertising, Analytics, Data Broker]
allow:
  - onetrust.com          # exempt your CMP or anything with a lawful basis
verdicts:
  non_compliant: fail
  no_banner_detected: fail
  inconclusive: warn      # don't fail a build just because we couldn't click the banner
  compliant: pass

Verdicts

| Verdict | Meaning | Default action | |---|---|---| | COMPLIANT | Banner accepted, nothing consent-requiring fired first. | pass | | NON_COMPLIANT | Banner accepted, but trackers fired before it. | fail | | NO_BANNER_DETECTED | No consent mechanism; trackers fired anyway. | fail | | INCONCLUSIVE | A banner was present but couldn't be operated. | warn |

INCONCLUSIVE defaults to a warning on purpose: the scanner failing to click a banner is not proof the site is broken, and a gate that fails on it would cry wolf. Set it to fail once you trust detection on your stack.


CLI

weaveeye-scan <url> [options]

  --policy <path>        Policy file (.yml/.yaml/.json). Default: .weaveeye.yml if present.
  --format <fmt>         terminal | json | markdown       (default: terminal)
  --output <path>        Also write the formatted report to a file.
  --json-out <path>      Write the machine-readable JSON result to a file.
  --allow <domains>      Comma-separated domains to exempt.
  --fail-on <categories> Comma-separated categories that fail the build.
  --inconclusive <act>   fail | warn | pass.
  --timeout <ms>         Navigation timeout (default: 30000).
  --no-color             Disable ANSI colour.
  --headful              Show the browser (debugging).

Programmatic API

import { consentScan, evaluate, loadPolicy } from "weaveeye-scan";

const scan = await consentScan("https://staging.example.com");
const result = evaluate(scan, loadPolicy(".weaveeye.yml"));
if (!result.passed) process.exit(1);

How it works, and its limits

  • Real browser. Playwright loads the page like a visitor would; it does not just parse HTML or read the cookie jar.
  • Before vs after. Third parties are timestamped and split at the moment consent is accepted. The "before" set, filtered to consent-requiring categories, is the finding.
  • Ownership. Trackers are attributed to their parent company using a bundled snapshot of Disconnect.me + DuckDuckGo Tracker Radar data plus a curated map. Regenerate it with npm run build:snapshot.

Geography matters. Consent banners are shown based on the visitor's region. To meaningfully test EU behaviour the job must run from an EU IP; for US/CIPA, a US IP. A runner in the wrong region will see NO_BANNER_DETECTED where a real user sees a banner. Choose your runner region deliberately.

This is not legal advice. It reports what the browser did, with timestamps and a traceable source for every domain flagged. Whether a given data flow is lawful depends on the site's legal basis and jurisdiction — a call for your counsel. The evidence is here to inform that, not replace it. Full details of how classification works and what is and isn't claimed: METHODOLOGY.md.


Development

npm install
npx playwright install chromium
npm test                  # unit tests (node:test) — no browser or network
npm run build:snapshot    # refresh the bundled tracker data
node src/cli.js example.com

License

MIT