@ads-repo/meta-creative-buckets 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +14 -0
- package/README.md +76 -0
- package/SKILL.md +231 -0
- package/buckets.config.example.json +8 -0
- package/env.example +29 -0
- package/install-to-claude.js +36 -0
- package/package.json +40 -0
- package/scripts/build-buckets-matrix.cjs +1367 -0
- package/scripts/config.cjs +133 -0
- package/scripts/encrypt-dashboard.cjs +241 -0
- package/scripts/fetch-buckets-data.cjs +398 -0
- package/scripts/fetch-creative-meta.cjs +172 -0
- package/scripts/optional/README.md +65 -0
- package/scripts/optional/extract-promo-labels.cjs +78 -0
- package/scripts/optional/extract-thumbs.cjs +169 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Copyright (c) 2026 Tomas Kliment / adsrepo.com
|
|
2
|
+
|
|
3
|
+
All rights reserved.
|
|
4
|
+
|
|
5
|
+
This tool and its contents are the exclusive property of adsrepo.com.
|
|
6
|
+
You may use this tool solely for your own internal business purposes.
|
|
7
|
+
|
|
8
|
+
You may NOT:
|
|
9
|
+
- Redistribute, resell, sublicense, or share this tool or any part of it
|
|
10
|
+
- Make the source code or generated outputs publicly available
|
|
11
|
+
- Use this tool to build competing products or services
|
|
12
|
+
- Share download links or access credentials with third parties
|
|
13
|
+
|
|
14
|
+
For licensing inquiries: tomas@adsrepo.com
|
package/README.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Meta Creative Buckets
|
|
2
|
+
|
|
3
|
+
A Claude Code skill that reads your Meta ad account and plots every creative on a
|
|
4
|
+
spend vs efficiency grid, so each ad lands in one of four buckets:
|
|
5
|
+
|
|
6
|
+
```
|
|
7
|
+
CRR bad (high) │ Wait │ Kill
|
|
8
|
+
├───────────┼──────────
|
|
9
|
+
CRR good (low) │ NotData │ Scale
|
|
10
|
+
└──────────────────────
|
|
11
|
+
low spend enough spend
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
The output is a single self-contained HTML file that opens in your browser.
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install -g @ads-repo/meta-creative-buckets
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
That copies the skill into `~/.claude/skills/meta-creative-buckets`. Restart Claude
|
|
23
|
+
Code and it will pick it up.
|
|
24
|
+
|
|
25
|
+
## Setup
|
|
26
|
+
|
|
27
|
+
You need two values from Meta.
|
|
28
|
+
|
|
29
|
+
**1. An access token** with the `ads_read` permission. The quickest route is the
|
|
30
|
+
[Graph API Explorer](https://developers.facebook.com/tools/explorer/): pick your app,
|
|
31
|
+
add the `ads_read` scope, generate the token. That one expires in about an hour - for
|
|
32
|
+
repeat use, exchange it for a long-lived token or create a System User token in
|
|
33
|
+
Business Manager.
|
|
34
|
+
|
|
35
|
+
**2. Your ad account id** - the `act_…` number in the Ads Manager URL.
|
|
36
|
+
|
|
37
|
+
Put both in a `.env` file in your project root:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
META_ACCESS_TOKEN=your-token-here
|
|
41
|
+
META_AD_ACCOUNT_ID=act_1234567890
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Reading several accounts from one project? Suffix each pair with a client slug
|
|
45
|
+
(`META_ACCESS_TOKEN_ACME_CZ`) and pass `--client acme-cz`.
|
|
46
|
+
|
|
47
|
+
## Use it
|
|
48
|
+
|
|
49
|
+
In Claude Code, say:
|
|
50
|
+
|
|
51
|
+
> build the creative buckets dashboard
|
|
52
|
+
|
|
53
|
+
It pulls 30 days of ad-level spend and purchase revenue, works out CRR per creative,
|
|
54
|
+
and opens the dashboard in your browser.
|
|
55
|
+
|
|
56
|
+
## The metric
|
|
57
|
+
|
|
58
|
+
**CRR = spend ÷ purchase revenue**, on the 7-day-click window. It is ROAS upside down:
|
|
59
|
+
CRR 40% means 40 € of ads per 100 € of sales, so **lower is better** (CRR 40% = ROAS 2.5).
|
|
60
|
+
|
|
61
|
+
Both thresholds are computed from your own account at build time - the target starts at
|
|
62
|
+
your blended CRR, the spend gate at the 75th percentile of per-ad spend - and both are
|
|
63
|
+
live sliders you can move.
|
|
64
|
+
|
|
65
|
+
## Requires
|
|
66
|
+
|
|
67
|
+
- Node.js 18+
|
|
68
|
+
- Claude Code
|
|
69
|
+
- A Meta ad account that tracks purchases (the grid is built on revenue)
|
|
70
|
+
|
|
71
|
+
No npm dependencies: the scripts use only Node's standard library.
|
|
72
|
+
|
|
73
|
+
## Docs
|
|
74
|
+
|
|
75
|
+
Full walkthrough, bucket rules and the two Meta API details worth knowing:
|
|
76
|
+
<https://adsrepo.com/products/meta-creative-buckets>
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: meta-creative-buckets
|
|
3
|
+
description: >
|
|
4
|
+
Build a Spend × CRR creative-bucket matrix dashboard from any Meta ad account — every ad
|
|
5
|
+
plotted as a bubble in a Not-enough-data / Wait / Scale / Kill quadrant grid, with a time
|
|
6
|
+
slider that replays the window day by day. Answers "which creatives deserve more budget
|
|
7
|
+
and which are burning it" for ecommerce accounts, using CRR (spend ÷ revenue) as the
|
|
8
|
+
efficiency metric.
|
|
9
|
+
|
|
10
|
+
Auto-activates when you mention:
|
|
11
|
+
- "creative buckets", "buckets dashboard", "creative matrix"
|
|
12
|
+
- "which creatives should I scale", "scale kill wait"
|
|
13
|
+
- "crr dashboard", "spend vs crr matrix", "roas by creative"
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# Meta Creative Buckets
|
|
17
|
+
|
|
18
|
+
Sorts every creative into four buckets on a Spend × CRR grid, so you can see at a glance
|
|
19
|
+
which ads deserve more budget and which are burning it.
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
CRR bad (high) │ Wait │ Kill
|
|
23
|
+
├───────────┼──────────
|
|
24
|
+
CRR good (low) │ NotData │ Scale
|
|
25
|
+
└──────────────────────
|
|
26
|
+
low spend enough spend
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Works with any Meta ad account that tracks purchases. One dependency: a Meta access token.
|
|
30
|
+
|
|
31
|
+
## Setup (once)
|
|
32
|
+
|
|
33
|
+
**1. Get a Meta access token** with `ads_read` permission for the account you want to read.
|
|
34
|
+
The quickest route is [Graph API Explorer](https://developers.facebook.com/tools/explorer/):
|
|
35
|
+
pick your app, add the `ads_read` scope, generate the token. Short-lived tokens expire in an
|
|
36
|
+
hour — for repeated use, exchange it for a long-lived one or create a System User token in
|
|
37
|
+
Business Manager.
|
|
38
|
+
|
|
39
|
+
**2. Find your ad account id** — it is the `act_…` number in the Ads Manager URL.
|
|
40
|
+
|
|
41
|
+
**3. Put both in `.env`** in your project root (see `env.example` in this folder):
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
META_ACCESS_TOKEN=your-token-here
|
|
45
|
+
META_AD_ACCOUNT_ID=act_1234567890
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Managing several accounts? Suffix each pair with the client slug, upper-cased:
|
|
49
|
+
`META_ACCESS_TOKEN_ACME_CZ` / `META_AD_ACCOUNT_ID_ACME_CZ`, then pass `--client acme-cz`.
|
|
50
|
+
|
|
51
|
+
**4. Add the npm scripts** to your `package.json`:
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
"meta:buckets": "node .claude/skills/meta-creative-buckets/scripts/fetch-buckets-data.cjs 30 && node .claude/skills/meta-creative-buckets/scripts/build-buckets-matrix.cjs",
|
|
55
|
+
"meta:buckets-chart": "node .claude/skills/meta-creative-buckets/scripts/build-buckets-matrix.cjs",
|
|
56
|
+
"meta:buckets-creatives": "node .claude/skills/meta-creative-buckets/scripts/fetch-creative-meta.cjs",
|
|
57
|
+
"meta:buckets-lock": "node .claude/skills/meta-creative-buckets/scripts/encrypt-dashboard.cjs"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
No install step — the scripts use only Node's standard library. They are `.cjs` so they run
|
|
61
|
+
in both ESM and CommonJS projects.
|
|
62
|
+
|
|
63
|
+
**5. Optional — `buckets.config.json`** in your project root, for a nicer header:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"client": "acme-cz",
|
|
68
|
+
"accountName": "Acme s.r.o.",
|
|
69
|
+
"logo": "public/acme-logo.png",
|
|
70
|
+
"agencyLogo": "public/my-agency-logo.png"
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Every field is optional. With no config the client slug is `default`, the title comes from
|
|
75
|
+
the account name Meta reports, and no logo is drawn.
|
|
76
|
+
|
|
77
|
+
## Running it
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
npm run meta:buckets # fetch 30 days + build (the usual command)
|
|
81
|
+
npm run meta:buckets-chart # rebuild the HTML from data already on disk
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The dashboard opens in your browser automatically. Everything lands in
|
|
85
|
+
`data/meta-ads/<client>/`:
|
|
86
|
+
|
|
87
|
+
- `buckets-latest.json` — per-ad summary + daily series
|
|
88
|
+
- `history/YYYYMMDD-buckets.json` — dated snapshot, drives the day-over-day ▲▼ arrows
|
|
89
|
+
- `buckets-matrix.html` — the dashboard
|
|
90
|
+
|
|
91
|
+
Run it a second day and the table gains movement arrows, comparing against the last snapshot.
|
|
92
|
+
|
|
93
|
+
Custom window: `node …/fetch-buckets-data.cjs 60 2026-09-07` fetches 60 days ending on that
|
|
94
|
+
date. Passing yesterday avoids a partial final day.
|
|
95
|
+
|
|
96
|
+
## The metric
|
|
97
|
+
|
|
98
|
+
**CRR = spend ÷ purchase revenue**, shown as a percentage, on the 7-day-click window.
|
|
99
|
+
|
|
100
|
+
It is **ROAS upside down**: CRR 40% means you spend 40 € of ads per 100 € of sales, so
|
|
101
|
+
**lower is better** (CRR 40% = ROAS 2.5).
|
|
102
|
+
|
|
103
|
+
## Bucket rules
|
|
104
|
+
|
|
105
|
+
With **target CRR** `T` and **spend gate** `S` (both live sliders):
|
|
106
|
+
|
|
107
|
+
| Bucket | Rule |
|
|
108
|
+
|---|---|
|
|
109
|
+
| **Not enough data** | `spend < S` — under the gate, never judged |
|
|
110
|
+
| **Scale** | `spend ≥ S` and `CRR ≤ T` — earning well, give it more |
|
|
111
|
+
| **Wait** | `spend ≥ S` and `T < CRR < 3T` — mediocre, watch it |
|
|
112
|
+
| **Kill** | `spend ≥ S` and `CRR ≥ 3T` — burning money |
|
|
113
|
+
|
|
114
|
+
An ad with **no revenue at all** stays in Not-enough-data until it burns `3 × S`, then goes
|
|
115
|
+
to Kill. It is never "Wait" — there is nothing to wait on without a single purchase. Those
|
|
116
|
+
ads have no CRR, so they sit in a separate strip below the plot, placed by spend only.
|
|
117
|
+
|
|
118
|
+
## Defaults come from the data
|
|
119
|
+
|
|
120
|
+
Both defaults are computed at build time from your account, not hardcoded:
|
|
121
|
+
|
|
122
|
+
- **Target CRR** = the account's **blended CRR** over the window. Starting the line at the
|
|
123
|
+
account average splits creatives into "better than my current average" vs "worse", which
|
|
124
|
+
is the honest opening question.
|
|
125
|
+
- **Spend gate** = 75th percentile of per-ad spend, floored at **3 × AOV**, rounded to 10.
|
|
126
|
+
An ad that has not spent a few average order values cannot be judged on revenue; the
|
|
127
|
+
median would wave through far too many.
|
|
128
|
+
|
|
129
|
+
Both are sliders and click-to-edit — these are only the opening position.
|
|
130
|
+
|
|
131
|
+
## The dashboard
|
|
132
|
+
|
|
133
|
+
A standalone HTML file, no server needed. Open it off disk, email it, put it anywhere.
|
|
134
|
+
|
|
135
|
+
- **Quadrant scatter** — bubble per ad, area ∝ spend, X = spend (log), Y = CRR %. Click a
|
|
136
|
+
zone to filter the table; click a bubble (or tick a row) to select across both views.
|
|
137
|
+
- **Time slider** — replays the window day by day; every bubble animates to its cumulative
|
|
138
|
+
position as of that day. Day / Week / Month granularity, plus a date-range calendar with
|
|
139
|
+
presets. Picking a range restarts accumulation at the range start. On a first visit the
|
|
140
|
+
thumb pulses with a hint, dismissed for good after the first drag.
|
|
141
|
+
- **Aggregate tiles** — Spend, Revenue and CRR (with ROAS) for whatever is in focus:
|
|
142
|
+
selection > clicked bucket > everything shown. CRR is spend ÷ revenue weighted, never an
|
|
143
|
+
average of per-ad CRRs.
|
|
144
|
+
- **Spend distribution bar** — what share of budget sits in each bucket. Usually the fastest
|
|
145
|
+
read on the page.
|
|
146
|
+
- **Filters** — campaign / ad set / ad (cascading), status, and an Active-only toggle
|
|
147
|
+
(= spent money on the selected day).
|
|
148
|
+
- **Table** — thumbnail + name, spend, revenue, purchases, CRR (with ▲▼ vs the previous
|
|
149
|
+
snapshot), ROAS, last-3-day spend and CRR, CTR, active days. Sortable; ads with no CRR
|
|
150
|
+
always sort last. Click a thumbnail for a lightbox; `←` `→` step through the current sort.
|
|
151
|
+
|
|
152
|
+
## Sharing it with a password
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
npm run meta:buckets-lock -- "your-password"
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Writes `buckets-matrix-locked.html` next to the original: the page is AES-encrypted and asks
|
|
159
|
+
for the password before rendering. Good enough to stop a passer-by following a shared link —
|
|
160
|
+
the ciphertext is public, so do not treat it as confidential.
|
|
161
|
+
|
|
162
|
+
## Two API details worth knowing
|
|
163
|
+
|
|
164
|
+
**Currency is read from the API, never assumed.** An account named "… CZ" may well bill in
|
|
165
|
+
EUR. Inferring a currency from the account name was once wrong by a factor of ~25.
|
|
166
|
+
|
|
167
|
+
**Revenue uses the named `7d_click` sub-field** of `action_values`, not Meta's plain `value`.
|
|
168
|
+
`value` is the account's default attribution (click + view) and can overstate revenue by
|
|
169
|
+
roughly a third, which would silently understate CRR.
|
|
170
|
+
|
|
171
|
+
## Rate limiting
|
|
172
|
+
|
|
173
|
+
Meta counts API calls **per account over a rolling window**, so the size of the account
|
|
174
|
+
matters more than the size of the window you asked for. Three defences are built in:
|
|
175
|
+
|
|
176
|
+
1. **Creative metadata is fetched by id, only for the ads in the window.** An account
|
|
177
|
+
accumulates every ad ever created — 8,000+ is ordinary — while a 30-day window usually has
|
|
178
|
+
a couple of hundred with spend. Paging the whole `/ads` edge to reach those few hundred
|
|
179
|
+
spends the limit on ads that will never appear in the output, and then the creative call
|
|
180
|
+
that carries the thumbnails gets refused. So the fetch reads the insights first, collects
|
|
181
|
+
the ids that actually spent, and looks those up in batches of 40.
|
|
182
|
+
2. **The fetch degrades instead of failing.** A refused creative pass leaves
|
|
183
|
+
`media_type: 'unknown'` and no preview, rather than discarding the expensive daily
|
|
184
|
+
insights. If the bulk insights range is refused, it falls back to fetching day by day.
|
|
185
|
+
3. **`npm run meta:buckets-creatives` is a repair pass** — re-run it later to patch media
|
|
186
|
+
types and previews into the existing JSON without re-fetching insights. Rarely needed now
|
|
187
|
+
that the main fetch is narrow, but useful if you were already near the limit.
|
|
188
|
+
|
|
189
|
+
Raise `META_API_RATE_LIMIT_DELAY` in `.env` (default 400 ms) if you keep hitting it, and give
|
|
190
|
+
the account a quiet 15-30 minutes before retrying — consecutive runs keep the window full.
|
|
191
|
+
The bucket maths never depended on creative metadata, so a run without it is still correct.
|
|
192
|
+
|
|
193
|
+
## Per-ad revenue does not sum to the account total (expected)
|
|
194
|
+
|
|
195
|
+
Summing revenue across ads gives a **higher** number than the same period read at account
|
|
196
|
+
level — typically **+8–12%**. This is Meta's **cross-ad deduplication**, not a bug: one
|
|
197
|
+
purchase touched by two ads is credited to both in ad-level rows, but counted once at
|
|
198
|
+
account level. Any per-ad report has this property.
|
|
199
|
+
|
|
200
|
+
In practice:
|
|
201
|
+
|
|
202
|
+
- **Per-ad CRR is sound for ranking creatives against each other** — that is what this
|
|
203
|
+
dashboard is for.
|
|
204
|
+
- The **aggregate CRR tile is slightly optimistic** versus Ads Manager's account view. Do
|
|
205
|
+
not quote it as the account's true blended CRR; read that at account level.
|
|
206
|
+
- The gap grows with retargeting overlap.
|
|
207
|
+
|
|
208
|
+
## Optional extras
|
|
209
|
+
|
|
210
|
+
`scripts/optional/` holds two scripts that add promo labels and creative thumbnails from a
|
|
211
|
+
Meta Ad Library scrape. They need a scraping and classification pipeline this skill does not
|
|
212
|
+
include — see the README in that folder for the file format if you want to wire up your own.
|
|
213
|
+
The dashboard works fine without them.
|
|
214
|
+
|
|
215
|
+
## When explaining results to the user
|
|
216
|
+
|
|
217
|
+
Use MEDIUM-SIMPLE language, in the user's language.
|
|
218
|
+
|
|
219
|
+
Explain **CRR** plainly: how much you spend on ads to earn 100 € of sales. CRR 38% means 38 €
|
|
220
|
+
of ads per 100 € of revenue, so **lower is better**. It is ROAS upside down (CRR 38% = ROAS 2.6).
|
|
221
|
+
|
|
222
|
+
Say plainly how many ads sit in **Not enough data**. On most accounts that is the majority,
|
|
223
|
+
because spend concentrates in a handful of creatives. That is a finding, not a gap: the
|
|
224
|
+
question "should I spread budget wider?" follows directly from it.
|
|
225
|
+
|
|
226
|
+
Quote **CRR and spend together**. A creative can look excellent on a small budget; the
|
|
227
|
+
interesting question is what happens to CRR as spend rises, which the matrix answers by
|
|
228
|
+
position, not the table by sorting.
|
|
229
|
+
|
|
230
|
+
Do not present the aggregate CRR tile as the account's blended CRR — per-ad revenue
|
|
231
|
+
double-counts (see above). Read the real one at account level.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": "Copy to buckets.config.json in your PROJECT ROOT (not this folder). Every field is optional — with no config file at all the dashboard uses the client slug 'default', takes its title from the account name Meta reports, and renders no logo.",
|
|
3
|
+
|
|
4
|
+
"client": "acme-cz",
|
|
5
|
+
"accountName": "Acme s.r.o.",
|
|
6
|
+
"logo": "public/acme-logo.png",
|
|
7
|
+
"agencyLogo": "public/my-agency-logo.png"
|
|
8
|
+
}
|
package/env.example
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Meta Creative Buckets — credentials
|
|
2
|
+
#
|
|
3
|
+
# Copy the lines you need into your project's .env (or .env.local) in the project root.
|
|
4
|
+
# Never commit the real values — .env belongs in .gitignore.
|
|
5
|
+
|
|
6
|
+
# --- Single account -----------------------------------------------------------
|
|
7
|
+
# The simplest setup. Works with the default client slug, no config file needed.
|
|
8
|
+
|
|
9
|
+
META_ACCESS_TOKEN=your-access-token-here
|
|
10
|
+
META_AD_ACCOUNT_ID=act_1234567890
|
|
11
|
+
|
|
12
|
+
# --- Several accounts ---------------------------------------------------------
|
|
13
|
+
# Suffix each pair with the client slug, upper-cased and non-alphanumerics turned
|
|
14
|
+
# into underscores: --client acme-cz -> _ACME_CZ
|
|
15
|
+
#
|
|
16
|
+
# META_ACCESS_TOKEN_ACME_CZ=...
|
|
17
|
+
# META_AD_ACCOUNT_ID_ACME_CZ=act_1234567890
|
|
18
|
+
# META_ACCESS_TOKEN_OTHER_CLIENT=...
|
|
19
|
+
# META_AD_ACCOUNT_ID_OTHER_CLIENT=act_9876543210
|
|
20
|
+
|
|
21
|
+
# --- Optional tuning ----------------------------------------------------------
|
|
22
|
+
# Raise the delay if the account keeps tripping Meta's rate limit (error 80004).
|
|
23
|
+
|
|
24
|
+
# META_API_VERSION=v25.0
|
|
25
|
+
# META_API_PAGE_SIZE=500
|
|
26
|
+
# META_API_RATE_LIMIT_DELAY=400
|
|
27
|
+
|
|
28
|
+
# Default client when no --client flag is passed.
|
|
29
|
+
# BUCKETS_CLIENT=acme-cz
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const os = require('os');
|
|
5
|
+
|
|
6
|
+
const SKILL_NAME = 'meta-creative-buckets';
|
|
7
|
+
const target = path.join(os.homedir(), '.claude', 'skills', SKILL_NAME);
|
|
8
|
+
const source = __dirname;
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
fs.mkdirSync(target, { recursive: true });
|
|
12
|
+
|
|
13
|
+
// env.example and the config sample travel with the skill: the first thing a new
|
|
14
|
+
// user needs is to know which two values go where, and they are easier to find
|
|
15
|
+
// next to SKILL.md than inside a node_modules folder.
|
|
16
|
+
['SKILL.md', 'README.md', 'env.example', 'buckets.config.example.json'].forEach(f => {
|
|
17
|
+
const src = path.join(source, f);
|
|
18
|
+
if (fs.existsSync(src)) fs.copyFileSync(src, path.join(target, f));
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
['scripts'].forEach(d => {
|
|
22
|
+
const src = path.join(source, d);
|
|
23
|
+
if (fs.existsSync(src)) fs.cpSync(src, path.join(target, d), { recursive: true });
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
console.log(`\n✅ Skill installed to ${target}`);
|
|
27
|
+
console.log(` Restart Claude Code to pick it up.`);
|
|
28
|
+
console.log(` Next: add META_ACCESS_TOKEN and META_AD_ACCOUNT_ID to a .env file`);
|
|
29
|
+
console.log(` in your project (see env.example in the folder above).`);
|
|
30
|
+
console.log(` Updates: npm update -g @ads-repo/meta-creative-buckets`);
|
|
31
|
+
console.log(` More skills: https://adsrepo.com\n`);
|
|
32
|
+
} catch (err) {
|
|
33
|
+
console.error(`\n❌ Install failed: ${err.message}`);
|
|
34
|
+
console.error(` Try running manually: install-meta-creative-buckets\n`);
|
|
35
|
+
process.exit(0);
|
|
36
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ads-repo/meta-creative-buckets",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Sort your Meta creatives into Scale, Wait and Kill on a spend vs CRR grid — drop-in Claude Code skill",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"claude-code",
|
|
7
|
+
"skill",
|
|
8
|
+
"meta-ads",
|
|
9
|
+
"creative-testing",
|
|
10
|
+
"crr",
|
|
11
|
+
"roas",
|
|
12
|
+
"adsrepo"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://adsrepo.com/products/meta-creative-buckets",
|
|
15
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
16
|
+
"author": "adsrepo",
|
|
17
|
+
"files": [
|
|
18
|
+
"LICENSE",
|
|
19
|
+
"SKILL.md",
|
|
20
|
+
"README.md",
|
|
21
|
+
"env.example",
|
|
22
|
+
"buckets.config.example.json",
|
|
23
|
+
"scripts/",
|
|
24
|
+
"install-to-claude.js"
|
|
25
|
+
],
|
|
26
|
+
"bin": {
|
|
27
|
+
"install-meta-creative-buckets": "install-to-claude.js"
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"postinstall": "node ./install-to-claude.js",
|
|
31
|
+
"buckets": "node scripts/fetch-buckets-data.cjs 30 && node scripts/build-buckets-matrix.cjs",
|
|
32
|
+
"buckets-chart": "node scripts/build-buckets-matrix.cjs"
|
|
33
|
+
},
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=18"
|
|
36
|
+
},
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
}
|
|
40
|
+
}
|