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

@ads-repo/meta-creative-buckets

v1.0.1

Published

Sort your Meta creatives into Scale, Wait and Kill on a spend vs CRR grid — drop-in Claude Code skill

Readme

Meta Creative Buckets

Sort every creative in your Meta ad account into Scale, Wait, Kill or Not enough data on a Spend × CRR grid. The output is a single self-contained HTML file with the quadrant chart, a time slider that replays the window day by day, and a sortable creative table — no server, no database, no Google Sheet in between.

    CRR bad (high)  │  Wait     │  Kill
                    ├───────────┼──────────
    CRR good (low)  │  NotData  │  Scale
                    └──────────────────────
                      low spend    enough spend

What you get

  • One HTML file with all data embedded, opens straight off disk
  • Quadrant scatter — one bubble per ad, area ∝ spend, X = spend (log), Y = CRR %
  • Time slider — replays the window day by day, with Day / Week / Month granularity and a date-range picker
  • Live thresholds — target CRR and spend gate as sliders, both seeded from your own account
  • Spend distribution bar — what share of budget sits in each bucket
  • Creative table — spend, revenue, purchases, CRR, ROAS, last-3-day trend, CTR, active days, all sortable
  • Cascading filters: campaign / ad set / ad, status, Active-only toggle
  • Day-over-day ▲▼ arrows once you have run it twice
  • Password-locked copy for client sharing (encrypt-dashboard.cjs)
  • adsrepo.com brand styling (Raleway font, orange accent #ff5722)

The metric

CRR = spend ÷ purchase revenue, as a percentage, on the 7-day-click window.

It is ROAS upside down: CRR 40% means 40 € of ads per 100 € of sales, so lower is better (CRR 40% = ROAS 2.5).

| Bucket | Rule (target CRR T, spend gate S) | |---|---| | Not enough data | spend < S — under the gate, never judged | | Scale | spend ≥ S and CRR ≤ T — earning well, give it more | | Wait | spend ≥ S and T < CRR < 3T — mediocre, watch it | | Kill | spend ≥ S and CRR ≥ 3T — burning money |

Both thresholds are computed from your account at build time, not hardcoded: the target starts at your blended CRR, the spend gate at the 75th percentile of per-ad spend (floored at 3 × AOV). Both are sliders — that is only the opening position.

Requirements

  • Node.js 18+ (download)
  • A Meta access token with the ads_read permission
  • Your ad account id — the act_… number in the Ads Manager URL
  • An account that tracks purchases: the grid is built on revenue, so lead-gen accounts have nothing on the Y axis

No npm dependencies — the scripts use only Node's standard library.

Installation

Option A — Claude Code (recommended)

npm install -g @ads-repo/meta-creative-buckets

That copies the skill into ~/.claude/skills/meta-creative-buckets/, available in every session. Restart Claude Code, then say:

build the creative buckets dashboard

Claude picks the skill up from the trigger phrase, fetches the data and opens the dashboard.

Manual install (if you would rather not install globally): unzip the ZIP from adsrepo.com and move the meta-creative-buckets/ folder into ~/.claude/skills/ or <project>/.claude/skills/, then restart Claude Code. Nothing to npm install — there are no dependencies.

Option B — Standalone CLI (no Claude Code)

The scripts are plain Node and run on their own:

cd ~/.claude/skills/meta-creative-buckets
node scripts/fetch-buckets-data.cjs 30
node scripts/build-buckets-matrix.cjs

Setup

Get a token with the ads_read scope from the Graph API Explorer: pick your app, add the scope, generate. That token expires in about an hour — for repeat use, exchange it for a long-lived token or create a System User token in Business Manager.

Then put both values in a .env file in your project root (see env.example):

META_ACCESS_TOKEN=your-token-here
META_AD_ACCOUNT_ID=act_1234567890

Reading several accounts from one project? Suffix each pair with a client slug and pass the flag:

META_ACCESS_TOKEN_ACME_CZ=...
META_AD_ACCOUNT_ID_ACME_CZ=act_9876543210
node scripts/fetch-buckets-data.cjs 30 --client acme-cz

Optionally add buckets.config.json in the project root for a nicer header (account name, logo). Every field is optional — see buckets.config.example.json.

What the script does

  1. Read the account currency and name from the Meta API (never guessed from the account name)
  2. Fetch 30 days of daily ad-level spend and purchase revenue, falling back to day-by-day if Meta refuses the bulk range
  3. Collect the ids that actually spent, then look up creative metadata for just those in batches of 40
  4. Work out CRR, ROAS, CTR and AOV per creative from the summed atoms, never averaged from daily rates
  5. Compute the starting thresholds from your own numbers
  6. Write one self-contained HTML file and open it in your browser

Output

data/meta-ads/<client>/
├── buckets-latest.json              # per-ad summary + daily series
├── history/YYYYMMDD-buckets.json    # dated snapshot, drives the ▲▼ arrows
└── buckets-matrix.html              # the dashboard

The HTML works fully offline once generated. Email it, host it on a static server, or open it locally.

Custom window: node scripts/fetch-buckets-data.cjs 60 2026-09-07 fetches 60 days ending on that date. Passing yesterday avoids a partial final day.

Troubleshooting

| Problem | Fix | |---|---| | credentials missing | Add META_ACCESS_TOKEN and META_AD_ACCOUNT_ID to .env in your project root, not in the skill folder | | Invalid OAuth access token | The Graph API Explorer token expired (about an hour). Generate a new one, or switch to a System User token | | Blank creative thumbnails | Meta rate-limits the creative lookup on busy accounts. Every number is still correct — wait 15-30 min and run node scripts/fetch-creative-meta.cjs to patch them in | | too many calls (error 80004) | Give the account a quiet 15-30 minutes; consecutive runs keep the rolling window full. Raise META_API_RATE_LIMIT_DELAY in .env if it persists | | Every ad in "Not enough data" | Normal on accounts where spend concentrates in a few creatives. Drag the spend gate slider down to judge more of them | | Dashboard opens empty | Check the account actually had spend in the window, and that it tracks purchase events |

Metrics glossary

  • CRR — spend ÷ purchase revenue, as a %. Lower is better. ROAS upside down
  • Target CRR — the line between Scale and Wait. Starts at your account's blended CRR
  • Spend gate — minimum spend before an ad is judged at all. Starts at the 75th percentile of per-ad spend, floored at 3 × AOV
  • CRR 3D — the same ratio over the last three days, so you can see where a creative is heading
  • No revenue yet — ads with spend but no purchases sit in a separate strip, placed by spend only. They are never "Wait": there is nothing to wait on without a single sale

Two attribution notes worth knowing. Revenue is read from the named 7d_click sub-field of action_values, not Meta's plain value — that one is the account default attribution (click + view) and can overstate revenue by roughly a third. And summing revenue across ads gives a higher number than the same period read at account level, typically +8-12%, because one purchase touched by two ads is credited to both. Per-ad CRR is sound for ranking creatives against each other; read the true blended CRR at account level.

License

Copyright (c) 2026 Tomas Kliment / adsrepo.com. All rights reserved. See LICENSE for terms.