@koda-sl/baker-cli 0.25.1 → 0.27.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/README.md +218 -0
- package/dist/cli.js +1 -1
- package/dist/commands/ads/index.d.ts.map +1 -1
- package/dist/commands/ads/index.js +12 -3
- package/dist/commands/ads/index.js.map +1 -1
- package/dist/commands/ads/linkedin/account.d.ts +20 -0
- package/dist/commands/ads/linkedin/account.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/account.js +39 -0
- package/dist/commands/ads/linkedin/account.js.map +1 -0
- package/dist/commands/ads/linkedin/accounts.d.ts +20 -0
- package/dist/commands/ads/linkedin/accounts.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/accounts.js +56 -0
- package/dist/commands/ads/linkedin/accounts.js.map +1 -0
- package/dist/commands/ads/linkedin/analytics.d.ts +84 -0
- package/dist/commands/ads/linkedin/analytics.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/analytics.js +249 -0
- package/dist/commands/ads/linkedin/analytics.js.map +1 -0
- package/dist/commands/ads/linkedin/audience-size.d.ts +28 -0
- package/dist/commands/ads/linkedin/audience-size.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/audience-size.js +75 -0
- package/dist/commands/ads/linkedin/audience-size.js.map +1 -0
- package/dist/commands/ads/linkedin/audit.d.ts +35 -0
- package/dist/commands/ads/linkedin/audit.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/audit.js +136 -0
- package/dist/commands/ads/linkedin/audit.js.map +1 -0
- package/dist/commands/ads/linkedin/bid-pricing.d.ts +38 -0
- package/dist/commands/ads/linkedin/bid-pricing.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/bid-pricing.js +76 -0
- package/dist/commands/ads/linkedin/bid-pricing.js.map +1 -0
- package/dist/commands/ads/linkedin/campaign-groups.d.ts +32 -0
- package/dist/commands/ads/linkedin/campaign-groups.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/campaign-groups.js +50 -0
- package/dist/commands/ads/linkedin/campaign-groups.js.map +1 -0
- package/dist/commands/ads/linkedin/campaigns.d.ts +36 -0
- package/dist/commands/ads/linkedin/campaigns.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/campaigns.js +57 -0
- package/dist/commands/ads/linkedin/campaigns.js.map +1 -0
- package/dist/commands/ads/linkedin/conversation.d.ts +36 -0
- package/dist/commands/ads/linkedin/conversation.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/conversation.js +77 -0
- package/dist/commands/ads/linkedin/conversation.js.map +1 -0
- package/dist/commands/ads/linkedin/conversions.d.ts +2 -0
- package/dist/commands/ads/linkedin/conversions.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/conversions.js +102 -0
- package/dist/commands/ads/linkedin/conversions.js.map +1 -0
- package/dist/commands/ads/linkedin/creatives.d.ts +36 -0
- package/dist/commands/ads/linkedin/creatives.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/creatives.js +57 -0
- package/dist/commands/ads/linkedin/creatives.js.map +1 -0
- package/dist/commands/ads/linkedin/demographics.d.ts +40 -0
- package/dist/commands/ads/linkedin/demographics.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/demographics.js +117 -0
- package/dist/commands/ads/linkedin/demographics.js.map +1 -0
- package/dist/commands/ads/linkedin/facets.d.ts +2 -0
- package/dist/commands/ads/linkedin/facets.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/facets.js +95 -0
- package/dist/commands/ads/linkedin/facets.js.map +1 -0
- package/dist/commands/ads/linkedin/forecast.d.ts +50 -0
- package/dist/commands/ads/linkedin/forecast.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/forecast.js +83 -0
- package/dist/commands/ads/linkedin/forecast.js.map +1 -0
- package/dist/commands/ads/linkedin/index.d.ts +19 -0
- package/dist/commands/ads/linkedin/index.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/index.js +83 -0
- package/dist/commands/ads/linkedin/index.js.map +1 -0
- package/dist/commands/ads/linkedin/leads.d.ts +40 -0
- package/dist/commands/ads/linkedin/leads.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/leads.js +75 -0
- package/dist/commands/ads/linkedin/leads.js.map +1 -0
- package/dist/commands/ads/linkedin/presets.d.ts +40 -0
- package/dist/commands/ads/linkedin/presets.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/presets.js +193 -0
- package/dist/commands/ads/linkedin/presets.js.map +1 -0
- package/dist/commands/ads/linkedin/presets.test.d.ts +2 -0
- package/dist/commands/ads/linkedin/presets.test.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/presets.test.js +98 -0
- package/dist/commands/ads/linkedin/presets.test.js.map +1 -0
- package/dist/commands/ads/linkedin/schemas.d.ts +2 -0
- package/dist/commands/ads/linkedin/schemas.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/schemas.js +300 -0
- package/dist/commands/ads/linkedin/schemas.js.map +1 -0
- package/dist/commands/ads/linkedin/shared.d.ts +17 -0
- package/dist/commands/ads/linkedin/shared.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/shared.js +116 -0
- package/dist/commands/ads/linkedin/shared.js.map +1 -0
- package/dist/commands/ads/linkedin/top-companies.d.ts +44 -0
- package/dist/commands/ads/linkedin/top-companies.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/top-companies.js +86 -0
- package/dist/commands/ads/linkedin/top-companies.js.map +1 -0
- package/dist/commands/ads/x/accounts.d.ts +14 -0
- package/dist/commands/ads/x/accounts.d.ts.map +1 -0
- package/dist/commands/ads/x/accounts.js +73 -0
- package/dist/commands/ads/x/accounts.js.map +1 -0
- package/dist/commands/ads/x/active-entities.d.ts +43 -0
- package/dist/commands/ads/x/active-entities.d.ts.map +1 -0
- package/dist/commands/ads/x/active-entities.js +88 -0
- package/dist/commands/ads/x/active-entities.js.map +1 -0
- package/dist/commands/ads/x/audiences.d.ts +19 -0
- package/dist/commands/ads/x/audiences.d.ts.map +1 -0
- package/dist/commands/ads/x/audiences.js +65 -0
- package/dist/commands/ads/x/audiences.js.map +1 -0
- package/dist/commands/ads/x/campaigns.d.ts +34 -0
- package/dist/commands/ads/x/campaigns.d.ts.map +1 -0
- package/dist/commands/ads/x/campaigns.js +56 -0
- package/dist/commands/ads/x/campaigns.js.map +1 -0
- package/dist/commands/ads/x/cards.d.ts +19 -0
- package/dist/commands/ads/x/cards.d.ts.map +1 -0
- package/dist/commands/ads/x/cards.js +65 -0
- package/dist/commands/ads/x/cards.js.map +1 -0
- package/dist/commands/ads/x/error-parser.d.ts +3 -0
- package/dist/commands/ads/x/error-parser.d.ts.map +1 -0
- package/dist/commands/ads/x/error-parser.js +80 -0
- package/dist/commands/ads/x/error-parser.js.map +1 -0
- package/dist/commands/ads/x/funding.d.ts +19 -0
- package/dist/commands/ads/x/funding.d.ts.map +1 -0
- package/dist/commands/ads/x/funding.js +65 -0
- package/dist/commands/ads/x/funding.js.map +1 -0
- package/dist/commands/ads/x/index.d.ts +2 -0
- package/dist/commands/ads/x/index.d.ts.map +1 -0
- package/dist/commands/ads/x/index.js +50 -0
- package/dist/commands/ads/x/index.js.map +1 -0
- package/dist/commands/ads/x/line-items.d.ts +34 -0
- package/dist/commands/ads/x/line-items.d.ts.map +1 -0
- package/dist/commands/ads/x/line-items.js +55 -0
- package/dist/commands/ads/x/line-items.js.map +1 -0
- package/dist/commands/ads/x/media.d.ts +24 -0
- package/dist/commands/ads/x/media.d.ts.map +1 -0
- package/dist/commands/ads/x/media.js +70 -0
- package/dist/commands/ads/x/media.js.map +1 -0
- package/dist/commands/ads/x/output.d.ts +13 -0
- package/dist/commands/ads/x/output.d.ts.map +1 -0
- package/dist/commands/ads/x/output.js +75 -0
- package/dist/commands/ads/x/output.js.map +1 -0
- package/dist/commands/ads/x/presets.d.ts +15 -0
- package/dist/commands/ads/x/presets.d.ts.map +1 -0
- package/dist/commands/ads/x/presets.js +60 -0
- package/dist/commands/ads/x/presets.js.map +1 -0
- package/dist/commands/ads/x/promoted-tweets.d.ts +29 -0
- package/dist/commands/ads/x/promoted-tweets.d.ts.map +1 -0
- package/dist/commands/ads/x/promoted-tweets.js +74 -0
- package/dist/commands/ads/x/promoted-tweets.js.map +1 -0
- package/dist/commands/ads/x/run-list.d.ts +17 -0
- package/dist/commands/ads/x/run-list.d.ts.map +1 -0
- package/dist/commands/ads/x/run-list.js +60 -0
- package/dist/commands/ads/x/run-list.js.map +1 -0
- package/dist/commands/ads/x/stats/index.d.ts +2 -0
- package/dist/commands/ads/x/stats/index.d.ts.map +1 -0
- package/dist/commands/ads/x/stats/index.js +32 -0
- package/dist/commands/ads/x/stats/index.js.map +1 -0
- package/dist/commands/ads/x/stats/job-create.d.ts +58 -0
- package/dist/commands/ads/x/stats/job-create.d.ts.map +1 -0
- package/dist/commands/ads/x/stats/job-create.js +95 -0
- package/dist/commands/ads/x/stats/job-create.js.map +1 -0
- package/dist/commands/ads/x/stats/job-status.d.ts +18 -0
- package/dist/commands/ads/x/stats/job-status.d.ts.map +1 -0
- package/dist/commands/ads/x/stats/job-status.js +58 -0
- package/dist/commands/ads/x/stats/job-status.js.map +1 -0
- package/dist/commands/ads/x/stats/job.d.ts +63 -0
- package/dist/commands/ads/x/stats/job.d.ts.map +1 -0
- package/dist/commands/ads/x/stats/job.js +183 -0
- package/dist/commands/ads/x/stats/job.js.map +1 -0
- package/dist/commands/ads/x/stats/sync.d.ts +73 -0
- package/dist/commands/ads/x/stats/sync.d.ts.map +1 -0
- package/dist/commands/ads/x/stats/sync.js +151 -0
- package/dist/commands/ads/x/stats/sync.js.map +1 -0
- package/dist/commands/ads/x/targeting-constants.d.ts +34 -0
- package/dist/commands/ads/x/targeting-constants.d.ts.map +1 -0
- package/dist/commands/ads/x/targeting-constants.js +80 -0
- package/dist/commands/ads/x/targeting-constants.js.map +1 -0
- package/dist/commands/ads/x/targeting-criteria.d.ts +24 -0
- package/dist/commands/ads/x/targeting-criteria.d.ts.map +1 -0
- package/dist/commands/ads/x/targeting-criteria.js +69 -0
- package/dist/commands/ads/x/targeting-criteria.js.map +1 -0
- package/dist/env.d.ts +2 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +8 -0
- package/dist/env.js.map +1 -1
- package/dist/error-handler.d.ts +1 -1
- package/dist/error-handler.d.ts.map +1 -1
- package/dist/error-handler.js +6 -0
- package/dist/error-handler.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -27,6 +27,9 @@ export BAKER_GA4_PROPERTY_ID="properties/123456789"
|
|
|
27
27
|
# Optional: default GSC site URL
|
|
28
28
|
export BAKER_GSC_SITE_URL="https://example.com/"
|
|
29
29
|
|
|
30
|
+
# Optional: default X Ads account ID (base36)
|
|
31
|
+
export BAKER_X_ADS_ACCOUNT_ID="18ce53xyz"
|
|
32
|
+
|
|
30
33
|
# Required for `baker actions ...` commands that stage against a chat
|
|
31
34
|
export BAKER_CHAT_ID="<chat-id>"
|
|
32
35
|
```
|
|
@@ -36,6 +39,7 @@ export BAKER_CHAT_ID="<chat-id>"
|
|
|
36
39
|
- `BAKER_GOOGLE_ADS_CUSTOMER_ID` — default Google Ads customer ID (10 digits). Used when `--customer-id` is not passed. If neither is set and the account has exactly one Google Ads customer, it is auto-selected.
|
|
37
40
|
- `BAKER_GA4_PROPERTY_ID` — default GA4 property ID. Used when `--property-id` is not passed. If neither is set and exactly one property is connected, it is auto-selected.
|
|
38
41
|
- `BAKER_GSC_SITE_URL` — default GSC site URL. Used when `--site-url` is not passed. If neither is set and exactly one site is verified, it is auto-selected.
|
|
42
|
+
- `BAKER_X_ADS_ACCOUNT_ID` — default X Ads account ID (base36). Used when `--account-id` is not passed. If neither is set and exactly one X Ads account is connected, it is auto-selected.
|
|
39
43
|
|
|
40
44
|
## Output Format
|
|
41
45
|
|
|
@@ -688,6 +692,75 @@ All errors include a `fix` object with `action`, `correctedCommand` (when applic
|
|
|
688
692
|
|
|
689
693
|
---
|
|
690
694
|
|
|
695
|
+
### X (Twitter) Ads (`baker ads x`)
|
|
696
|
+
|
|
697
|
+
Read X Ads campaigns, line items, promoted tweets, creatives, audiences, and analytics. Powered by the X Ads API v12.
|
|
698
|
+
|
|
699
|
+
**Environment:**
|
|
700
|
+
- `BAKER_X_ADS_ACCOUNT_ID` — default account ID (base36). Used when `--account-id` is not passed. If neither is set and exactly one X Ads account is connected, it's auto-selected.
|
|
701
|
+
|
|
702
|
+
**Subcommands:**
|
|
703
|
+
|
|
704
|
+
| Subcommand | What it returns |
|
|
705
|
+
|---|---|
|
|
706
|
+
| `accounts` | All accessible X Ads accounts |
|
|
707
|
+
| `funding` | Funding instruments for an account |
|
|
708
|
+
| `campaigns` | Campaigns (filter by `--funding-instrument-ids`, `--campaign-ids`) |
|
|
709
|
+
| `line-items` | Line items / ad groups (filter by `--campaign-ids`, `--line-item-ids`) |
|
|
710
|
+
| `promoted-tweets` | Promoted tweets (filter by `--line-item-ids`) |
|
|
711
|
+
| `cards` | Website cards, video cards, carousels |
|
|
712
|
+
| `media` | Media library (images / GIFs / videos) — `--media-type IMAGE\|GIF\|VIDEO` |
|
|
713
|
+
| `audiences` | Custom audiences (size, targetable status) |
|
|
714
|
+
| `targeting-criteria` | Targeting attached to line items |
|
|
715
|
+
| `targeting-constants` | Lookup locations / interests / events / devices etc. — `--constant <name> --q "Madrid"` |
|
|
716
|
+
| `active-entities` | Entities with metric activity in a time range |
|
|
717
|
+
| `stats sync` | Synchronous analytics (≤7 days, no segmentation) |
|
|
718
|
+
| `stats job` | Async stats end-to-end (creates + polls + downloads + decompresses). Must run in the background (the harness enforces this). Use for ranges >7 days, segmented stats, or when sync limits are hit. |
|
|
719
|
+
| `stats job-create` | Low-level: create async stats job, return ID immediately |
|
|
720
|
+
| `stats job-status` | Low-level: poll job status / get download URL |
|
|
721
|
+
|
|
722
|
+
**Examples:**
|
|
723
|
+
|
|
724
|
+
```bash
|
|
725
|
+
baker ads x accounts
|
|
726
|
+
baker ads x campaigns --account-id 18ce53xyz
|
|
727
|
+
baker ads x line-items --account-id 18ce53xyz --campaign-ids abc
|
|
728
|
+
baker ads x promoted-tweets --account-id 18ce53xyz
|
|
729
|
+
|
|
730
|
+
# Sync analytics with a preset (saves tokens)
|
|
731
|
+
baker ads x stats sync --preset campaign-engagement-7d --entity-ids abc,def
|
|
732
|
+
|
|
733
|
+
# Free-form sync stats
|
|
734
|
+
baker ads x stats sync --account-id 18ce53xyz --entity LINE_ITEM \
|
|
735
|
+
--entity-ids abc,def --start-time 2026-05-01T00:00:00Z --end-time 2026-05-07T00:00:00Z \
|
|
736
|
+
--metric-groups ENGAGEMENT,BILLING --granularity DAY
|
|
737
|
+
|
|
738
|
+
# Async job, sync from the CLI's perspective (creates → polls → downloads → returns).
|
|
739
|
+
# Must be invoked with run_in_background: true. The harness will block otherwise.
|
|
740
|
+
baker ads x stats job --account-id 18ce53xyz --entity CAMPAIGN \
|
|
741
|
+
--entity-ids abc --start-time 2026-04-01T00:00:00Z --end-time 2026-05-01T00:00:00Z \
|
|
742
|
+
--metric-groups ENGAGEMENT,BILLING --segmentation-type LOCATIONS
|
|
743
|
+
|
|
744
|
+
# Low-level (don't wait, manage polling yourself):
|
|
745
|
+
baker ads x stats job-create --account-id 18ce53xyz --entity CAMPAIGN \
|
|
746
|
+
--entity-ids abc --start-time 2026-04-01T00:00:00Z --end-time 2026-05-01T00:00:00Z \
|
|
747
|
+
--metric-groups ENGAGEMENT,BILLING --segmentation-type LOCATIONS
|
|
748
|
+
baker ads x stats job-status --account-id 18ce53xyz --job-id <jobId>
|
|
749
|
+
|
|
750
|
+
# List sync presets
|
|
751
|
+
baker ads x stats sync --list-presets
|
|
752
|
+
|
|
753
|
+
# Targeting lookups
|
|
754
|
+
baker ads x targeting-constants --constant locations --q "Madrid" --country-code ES
|
|
755
|
+
baker ads x targeting-constants --constant interests
|
|
756
|
+
```
|
|
757
|
+
|
|
758
|
+
**Caching:** account list 1h · campaigns/line items/promoted tweets 1h (date-keyed) · cards/media/audiences 6h · stats sync 1h · targeting constants 7 days. Pass `--no-cache` to bypass.
|
|
759
|
+
|
|
760
|
+
**Rate limits:** server-side buckets (`xAds:read`, `xAds:write`, `xAds:analyticsSync`, `xAds:analyticsAsync`, `xAds:audiences`) sit well under X's published quotas; 429s honor `x-account-rate-limit-reset` / `x-rate-limit-reset` headers.
|
|
761
|
+
|
|
762
|
+
---
|
|
763
|
+
|
|
691
764
|
### Meta Ads (`baker ads meta`)
|
|
692
765
|
|
|
693
766
|
Meta Marketing API (Facebook + Instagram). Connect via OAuth in the dashboard, pick which ad accounts to scope to, then call from the CLI. Account ID via `--account-id act_123` or `BAKER_META_AD_ACCOUNT_ID` env var.
|
|
@@ -784,6 +857,151 @@ The HTTP backend exposes more endpoints (catalogs, ad-studies, ad-images, labels
|
|
|
784
857
|
|
|
785
858
|
---
|
|
786
859
|
|
|
860
|
+
### LinkedIn Ads (`baker ads linkedin`)
|
|
861
|
+
|
|
862
|
+
LinkedIn Marketing API for B2B ad insights. Connect via OAuth in the dashboard, pick which ad accounts to scope to, then call from the CLI. Account ID via `--account-id 503001492` (numeric) or `--account-urn urn:li:sponsoredAccount:503001492`, or set `BAKER_LINKEDIN_AD_ACCOUNT_ID` env.
|
|
863
|
+
|
|
864
|
+
**LinkedIn's superpower over Meta/Google:** firmographic pivots on every analytics query — `pivot=job-title|company|industry|seniority|function|company-size`. Meta has nothing like `MEMBER_COMPANY` returning company URNs of every account whose employees saw the ad. AI agents should reach for `linkedin demographics` and `linkedin top-companies` first when answering ABM/persona questions.
|
|
865
|
+
|
|
866
|
+
**Read-only v1.** No campaign/creative writes. The surface is curated for AI agents per the LinkedIn Ads playbook (B2B operating manual covering audits, ABM, attribution, scaling).
|
|
867
|
+
|
|
868
|
+
#### Common AI questions, mapped to commands
|
|
869
|
+
|
|
870
|
+
```bash
|
|
871
|
+
# "How is account X doing this week?"
|
|
872
|
+
baker ads linkedin analytics
|
|
873
|
+
|
|
874
|
+
# "Who are we reaching, by job title?" (the LinkedIn killer)
|
|
875
|
+
baker ads linkedin analytics --level campaign --campaign-id 1234 \
|
|
876
|
+
--pivot job-title --intent baseline --last-days 30
|
|
877
|
+
|
|
878
|
+
# "Top companies seeing this campaign" (ABM feedback loop)
|
|
879
|
+
baker ads linkedin top-companies --campaign-id 1234 --last-days 30
|
|
880
|
+
|
|
881
|
+
# "Who is in our audience by industry/seniority/function/title — all at once?"
|
|
882
|
+
baker ads linkedin demographics --campaign-id 1234 --last-days 30
|
|
883
|
+
|
|
884
|
+
# "Revenue by campaign over Q1"
|
|
885
|
+
baker ads linkedin analytics --level campaign --campaign-id 1,2,3 \
|
|
886
|
+
--intent revenue --start 2026-01-01 --end 2026-03-31 --granularity MONTHLY
|
|
887
|
+
|
|
888
|
+
# "How is the lead form converting?"
|
|
889
|
+
baker ads linkedin analytics --level campaign --campaign-id 1234 --intent lead-gen
|
|
890
|
+
|
|
891
|
+
# "Which creatives are fatigued?"
|
|
892
|
+
baker ads linkedin analytics --level creative --creative-id 1,2,3 --intent ranking
|
|
893
|
+
|
|
894
|
+
# "Run the playbook audit"
|
|
895
|
+
baker ads linkedin audit --account-id 503001492
|
|
896
|
+
baker ads linkedin audit --account-id 503001492 --format md # deliverable-ready table
|
|
897
|
+
|
|
898
|
+
# "Pull the leads from the last 7 days"
|
|
899
|
+
baker ads linkedin leads --account-id 503001492 --since-days 7
|
|
900
|
+
|
|
901
|
+
# "Is the Insight Tag healthy?"
|
|
902
|
+
baker ads linkedin conversions health --account-id 503001492
|
|
903
|
+
|
|
904
|
+
# "Pre-launch sanity check: is this audience too narrow?"
|
|
905
|
+
baker ads linkedin audience-size --account-id 503001492 --targeting-file targeting.json
|
|
906
|
+
|
|
907
|
+
# "What bid should I start at?"
|
|
908
|
+
baker ads linkedin bid-pricing --account-id 503001492 \
|
|
909
|
+
--objective LEAD_GENERATION --cost-type CPC --targeting-file targeting.json
|
|
910
|
+
```
|
|
911
|
+
|
|
912
|
+
#### Smart defaults
|
|
913
|
+
|
|
914
|
+
**`analytics`** — the 3-axis workhorse:
|
|
915
|
+
- `--level account` (override: `campaign-group|campaign|creative`)
|
|
916
|
+
- `--intent baseline` field bundle. Intents: `baseline | revenue | funnel | engagement | video | lead-gen | inmail | document | ranking | identity`. List with `--list-intents`.
|
|
917
|
+
- `--pivot none`. Pivots: `none | campaign | campaign-group | creative | company | account | conversion | job-title | job-function | seniority | industry | company-size | country | region | device | placement | serving-location | card-index | objective | conversation-node | conversation-node-button`. List with `--list-pivots`.
|
|
918
|
+
- `--granularity DAILY`. Auto-forced to `ALL` when pivoting on a `MEMBER_*` dim (LinkedIn rejects DAILY + demographic) — surfaced in stderr + `warnings`.
|
|
919
|
+
- `--last-days 7` unless you pass `--start`/`--end`.
|
|
920
|
+
- Sort: `costInUsd` descending. `--no-sort` to disable.
|
|
921
|
+
- Derived metrics injected client-side: `ctr`, `cpc`, `cpm`, `frequency`, `leadCompletionRate` — LinkedIn doesn't return these.
|
|
922
|
+
- URN normalization: every URN field becomes `{type, id, urn}` so rows are self-describing.
|
|
923
|
+
- Wide windows (>180d) auto-segment into 30-day chunks and combine, since `q=analytics` caps at 15,000 rows with no pagination.
|
|
924
|
+
|
|
925
|
+
**Listings** (`campaign-groups`/`campaigns`/`creatives`) default to `ACTIVE` only — pass `--all-statuses` to widen, or `--statuses ACTIVE,PAUSED` for a custom set.
|
|
926
|
+
|
|
927
|
+
**Pagination** is auto-drained (start/count loop hidden).
|
|
928
|
+
|
|
929
|
+
**Demographic pivots** (`MEMBER_*`) come back delayed 12-24h with a ≥3-event privacy floor — small buckets are dropped. The CLI surfaces `DELAYED_DEMOGRAPHIC` and (when results are unexpectedly empty) `BELOW_PRIVACY_FLOOR` warnings.
|
|
930
|
+
|
|
931
|
+
#### Full command surface
|
|
932
|
+
|
|
933
|
+
```
|
|
934
|
+
accounts # accounts in the connected picker scope
|
|
935
|
+
accounts --include-all # every account the token can see
|
|
936
|
+
account # single-account detail (currency, type, status)
|
|
937
|
+
|
|
938
|
+
campaign-groups # default ACTIVE-only
|
|
939
|
+
campaigns # default ACTIVE-only; reveals audit-relevant settings
|
|
940
|
+
creatives # default ACTIVE intended-status
|
|
941
|
+
|
|
942
|
+
analytics # see "Smart defaults" above (3-axis: level × intent × pivot)
|
|
943
|
+
demographics # sweep all firmographic pivots in one call
|
|
944
|
+
top-companies # pivot=MEMBER_COMPANY shortcut (ABM)
|
|
945
|
+
conversation # pivot=CONVERSATION_NODE_BUTTON shortcut (Sponsored Messaging)
|
|
946
|
+
|
|
947
|
+
facets list # all targeting facets (industries, seniorities, titles, employers, …)
|
|
948
|
+
facets values --facet titles --query "..." # typeahead → URNs
|
|
949
|
+
audience-size # estimate reach for a targetingCriteria payload + sweet-spot warnings
|
|
950
|
+
bid-pricing # min/suggested/max bid + playbook §06 floor (2/3 of suggested)
|
|
951
|
+
forecast # adSupplyForecasts wrapper for greenfield planning
|
|
952
|
+
|
|
953
|
+
leads # Lead Gen Form responses (90d retention — sync to your CRM)
|
|
954
|
+
conversions list # conversion rules (Insight Tag + CAPI)
|
|
955
|
+
conversions health # 5-point Insight Tag / CAPI health check (playbook §07)
|
|
956
|
+
|
|
957
|
+
audit # 30+ playbook checks → severity-tagged findings
|
|
958
|
+
audit --format md # deliverable-ready markdown table
|
|
959
|
+
```
|
|
960
|
+
|
|
961
|
+
#### `audit` — playbook diagnostic
|
|
962
|
+
|
|
963
|
+
Runs in parallel: account detail + every campaign + every creative + conversion rules + account-level analytics + per-campaign frequency. Synthesizes findings across:
|
|
964
|
+
|
|
965
|
+
- **Settings** — Audience Expansion disabled, LinkedIn Audience Network disabled, Manual CPC bidding (not Maximum Delivery), daily budget ≥ $50, lifetime budget cap set, budget-fragmentation guard
|
|
966
|
+
- **Tracking** — at least one enabled rule, lead/purchase event configured, CAPI events recent (≤7d), `ONE_TIME_EACH_MEMBER` for leads, view-through window ≤7d, click attribution 7-90d
|
|
967
|
+
- **Creative** — ≥3 ad formats per campaign, TLA presence, no creative active >90d, frequency <7, REJECTED creatives flagged
|
|
968
|
+
- **Performance** — account CTR ≥ 0.4%, LP CVR ≥ 2%, lead-form completion ≥ 10%, delivered impressions in window, spend > $0
|
|
969
|
+
- **Hygiene** — no abandoned DRAFT campaigns, every active campaign has at least one creative
|
|
970
|
+
|
|
971
|
+
Each finding: `{id, area, check, status, severity, evidence, fix: {explanation, playbookRef}}`. Filter with `--severity critical,high` or `--area Settings,Tracking`. The JSON `summary` counts pass/critical/high/medium/low/n_a.
|
|
972
|
+
|
|
973
|
+
#### Auth + caching
|
|
974
|
+
|
|
975
|
+
- OAuth tokens auto-refresh server-side. On 401, reconnect LinkedIn from dashboard → integrations.
|
|
976
|
+
- Account scoping: backend rejects calls against an account not in the picker selection.
|
|
977
|
+
- Pinned API version: `Linkedin-Version: 202604` (declared in `oauth/constants.ts`). Bump as a coordinated change — LinkedIn deprecates monthly with a ~12-month support window.
|
|
978
|
+
- Cache TTLs: accounts/account-detail 1h, listings 30m, analytics 15m–6h (depends on date range), facets 7d, urn-resolve 1h, bid-pricing/forecast 6h, audience-size 1h.
|
|
979
|
+
- `--skip-cache` (server-side) and `--no-cache` (client-side, where supported) on any command.
|
|
980
|
+
|
|
981
|
+
#### LinkedIn-specific gotchas
|
|
982
|
+
|
|
983
|
+
- **Demographic + DAILY = error.** CLI auto-forces granularity=ALL when pivoting on `MEMBER_*` and warns.
|
|
984
|
+
- **3-event privacy floor.** Small demographic buckets are dropped silently — widen the date range if results are sparse.
|
|
985
|
+
- **15,000-row cap on `q=analytics`** (no pagination). CLI auto-segments by month for wide windows.
|
|
986
|
+
- **Lead Gen Form 90-day retention.** Sync via `baker ads linkedin leads` regularly or lose them.
|
|
987
|
+
- **LinkedIn can overspend daily budget by 50%** — only `totalBudget` lifetime cap stops runaway spend (audit check).
|
|
988
|
+
- **CPC can look high** ($8–14 NA baseline) but CPL competitive thanks to firmographic targeting. Use playbook §00 dynamic benchmarks (geo + industry multipliers) before judging.
|
|
989
|
+
- **No native change-history API.** Activity logs are not surfaced — playbook §24 calls this out as a gap.
|
|
990
|
+
|
|
991
|
+
#### Error codes
|
|
992
|
+
|
|
993
|
+
| HTTP | LinkedIn `serviceErrorCode` | CLI maps to | Action |
|
|
994
|
+
|------|---|---|---|
|
|
995
|
+
| 401 | 100 | `UNAUTHORIZED` | Reconnect LinkedIn in dashboard |
|
|
996
|
+
| 403 | — | `FORBIDDEN` | Token lacks scope or account role |
|
|
997
|
+
| 404 | 65604 | `NOT_FOUND` | Entity removed or not in scope |
|
|
998
|
+
| 410 | — | `GONE` | Entity deleted; URN no longer queryable |
|
|
999
|
+
| 426 | — | `INTERNAL_ERROR` | LinkedIn-Version deprecated; backend bump required |
|
|
1000
|
+
| 429 | 101 | `RATE_LIMITED` | Auto-backoff with Retry-After; if you see this, retry budget exhausted |
|
|
1001
|
+
| 400 | 65601 / 65603 | `VALIDATION_ERROR` | Fix request — see `error.fix.explanation` |
|
|
1002
|
+
|
|
1003
|
+
---
|
|
1004
|
+
|
|
787
1005
|
### Google Analytics 4 (`baker ga4`)
|
|
788
1006
|
|
|
789
1007
|
GA4 commands for multi-channel audits. Playbook-aligned presets, property health audits, and free-form Data API queries.
|
package/dist/cli.js
CHANGED
|
@@ -12,7 +12,7 @@ import { videosCommand } from "./commands/videos/index.js";
|
|
|
12
12
|
const main = defineCommand({
|
|
13
13
|
meta: {
|
|
14
14
|
name: "baker",
|
|
15
|
-
version: "0.
|
|
15
|
+
version: "0.27.0",
|
|
16
16
|
description: `AI-agent CLI for finding and managing images, videos, testimonials, action items, and ad platform data in Baker.
|
|
17
17
|
|
|
18
18
|
Auth: Set BAKER_API_KEY (starts with bk_) and BAKER_API_URL environment variables.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/ads/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/ads/index.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,UAAU,qDA2BrB,CAAC"}
|
|
@@ -1,25 +1,34 @@
|
|
|
1
1
|
import { defineCommand } from "citty";
|
|
2
2
|
import { googleCommand } from "./google/index.js";
|
|
3
|
+
import { linkedinCommand } from "./linkedin/index.js";
|
|
3
4
|
import { metaCommand } from "./meta/index.js";
|
|
5
|
+
import { xCommand } from "./x/index.js";
|
|
4
6
|
export const adsCommand = defineCommand({
|
|
5
7
|
meta: {
|
|
6
8
|
name: "ads",
|
|
7
9
|
description: `Ad platform commands. Each platform exposes its own native command surface — no forced parity.
|
|
8
10
|
|
|
9
11
|
Platforms:
|
|
10
|
-
google
|
|
11
|
-
meta
|
|
12
|
+
google — Google Ads (GAQL queries, keywords, accounts, ad library)
|
|
13
|
+
meta — Meta Ads (campaigns, adsets, ads, insights, previews)
|
|
14
|
+
linkedin — LinkedIn Ads (firmographic analytics — job-title × company × industry × seniority pivots)
|
|
15
|
+
x — X (Twitter) Ads (campaigns, line items, promoted tweets, analytics)
|
|
12
16
|
|
|
13
17
|
Examples:
|
|
14
18
|
baker ads google accounts
|
|
15
19
|
baker ads google query --preset campaign-performance --customer-id 1234567890
|
|
16
20
|
baker ads meta accounts
|
|
17
21
|
baker ads meta campaigns --account-id act_123 --effective-status ACTIVE
|
|
18
|
-
baker ads meta insights --object act_123 --level ad --date-preset last_7d --fields impressions,spend,ctr
|
|
22
|
+
baker ads meta insights --object act_123 --level ad --date-preset last_7d --fields impressions,spend,ctr
|
|
23
|
+
baker ads linkedin accounts
|
|
24
|
+
baker ads x accounts
|
|
25
|
+
baker ads x stats sync --preset campaign-engagement-7d --entity-ids abc,def`,
|
|
19
26
|
},
|
|
20
27
|
subCommands: {
|
|
21
28
|
google: googleCommand,
|
|
22
29
|
meta: metaCommand,
|
|
30
|
+
linkedin: linkedinCommand,
|
|
31
|
+
x: xCommand,
|
|
23
32
|
},
|
|
24
33
|
});
|
|
25
34
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/ads/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/ads/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,MAAM,CAAC,MAAM,UAAU,GAAG,aAAa,CAAC;IACtC,IAAI,EAAE;QACJ,IAAI,EAAE,KAAK;QACX,WAAW,EAAE;;;;;;;;;;;;;;;;8EAgB6D;KAC3E;IACD,WAAW,EAAE;QACX,MAAM,EAAE,aAAa;QACrB,IAAI,EAAE,WAAW;QACjB,QAAQ,EAAE,eAAe;QACzB,CAAC,EAAE,QAAQ;KACZ;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare const accountCommand: import("citty").CommandDef<{
|
|
2
|
+
readonly "account-id": {
|
|
3
|
+
readonly type: "string";
|
|
4
|
+
readonly description: "Numeric account ID or urn:li:sponsoredAccount:N";
|
|
5
|
+
};
|
|
6
|
+
readonly "account-urn": {
|
|
7
|
+
readonly type: "string";
|
|
8
|
+
readonly description: "Alias for --account-id";
|
|
9
|
+
};
|
|
10
|
+
readonly "skip-cache": {
|
|
11
|
+
readonly type: "boolean";
|
|
12
|
+
readonly description: "Bypass server-side cache";
|
|
13
|
+
};
|
|
14
|
+
readonly output: {
|
|
15
|
+
readonly type: "string";
|
|
16
|
+
readonly description: "json|csv|jsonl|md";
|
|
17
|
+
readonly default: "json";
|
|
18
|
+
};
|
|
19
|
+
}>;
|
|
20
|
+
//# sourceMappingURL=account.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/linkedin/account.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;EA+BzB,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { defineCommand } from "citty";
|
|
2
|
+
import { apiGet } from "../../../client.js";
|
|
3
|
+
import { writeAdsJson, writeAdsOutput } from "../output.js";
|
|
4
|
+
import { csvOrJson, handleLinkedinError, resolveAccountIdArg } from "./shared.js";
|
|
5
|
+
export const accountCommand = defineCommand({
|
|
6
|
+
meta: {
|
|
7
|
+
name: "account",
|
|
8
|
+
description: `Single LinkedIn ad account detail (currency, status, type).
|
|
9
|
+
|
|
10
|
+
Examples:
|
|
11
|
+
baker ads linkedin account --account-id 503001492
|
|
12
|
+
baker ads linkedin account --account-urn urn:li:sponsoredAccount:503001492 --output md`,
|
|
13
|
+
},
|
|
14
|
+
args: {
|
|
15
|
+
"account-id": { type: "string", description: "Numeric account ID or urn:li:sponsoredAccount:N" },
|
|
16
|
+
"account-urn": { type: "string", description: "Alias for --account-id" },
|
|
17
|
+
"skip-cache": { type: "boolean", description: "Bypass server-side cache" },
|
|
18
|
+
output: { type: "string", description: "json|csv|jsonl|md", default: "json" },
|
|
19
|
+
},
|
|
20
|
+
run: async ({ args }) => {
|
|
21
|
+
const accountId = resolveAccountIdArg(args);
|
|
22
|
+
try {
|
|
23
|
+
const params = { "account-id": accountId };
|
|
24
|
+
if (args["skip-cache"])
|
|
25
|
+
params["skip-cache"] = "true";
|
|
26
|
+
const data = await apiGet("/api/ads/linkedin/account", params);
|
|
27
|
+
const fmt = csvOrJson(args);
|
|
28
|
+
if (fmt !== "json") {
|
|
29
|
+
writeAdsOutput([data], fmt);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
writeAdsJson({ ok: true, data });
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
handleLinkedinError(err);
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
//# sourceMappingURL=account.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account.js","sourceRoot":"","sources":["../../../../src/commands/ads/linkedin/account.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAYlF,MAAM,CAAC,MAAM,cAAc,GAAG,aAAa,CAAC;IAC1C,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,WAAW,EAAE;;;;yFAIwE;KACtF;IACD,IAAI,EAAE;QACJ,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,iDAAiD,EAAE;QAChG,aAAa,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,wBAAwB,EAAE;QACxE,YAAY,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,0BAA0B,EAAE;QAC1E,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,EAAE;KAC9E;IACD,GAAG,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QACtB,MAAM,SAAS,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,CAAC;YACH,MAAM,MAAM,GAA2B,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC;YACnE,IAAI,IAAI,CAAC,YAAY,CAAC;gBAAE,MAAM,CAAC,YAAY,CAAC,GAAG,MAAM,CAAC;YACtD,MAAM,IAAI,GAAG,MAAM,MAAM,CAAsB,2BAA2B,EAAE,MAAM,CAAC,CAAC;YACpF,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAC5B,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;gBACnB,cAAc,CAAC,CAAC,IAAI,CAA8C,EAAE,GAAG,CAAC,CAAC;gBACzE,OAAO;YACT,CAAC;YACD,YAAY,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACnC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,mBAAmB,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare const accountsCommand: import("citty").CommandDef<{
|
|
2
|
+
readonly "include-all": {
|
|
3
|
+
readonly type: "boolean";
|
|
4
|
+
readonly description: "List all accessible accounts, ignoring picker scope";
|
|
5
|
+
};
|
|
6
|
+
readonly "no-cache": {
|
|
7
|
+
readonly type: "boolean";
|
|
8
|
+
readonly description: "Skip CLI-side cache";
|
|
9
|
+
};
|
|
10
|
+
readonly "skip-cache": {
|
|
11
|
+
readonly type: "boolean";
|
|
12
|
+
readonly description: "Bypass server-side cache (force re-fetch)";
|
|
13
|
+
};
|
|
14
|
+
readonly output: {
|
|
15
|
+
readonly type: "string";
|
|
16
|
+
readonly description: "Output format: json|csv|jsonl|md";
|
|
17
|
+
readonly default: "json";
|
|
18
|
+
};
|
|
19
|
+
}>;
|
|
20
|
+
//# sourceMappingURL=accounts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accounts.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/linkedin/accounts.ts"],"names":[],"mappings":"AAkBA,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;EA6C1B,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { defineCommand } from "citty";
|
|
2
|
+
import { apiGet } from "../../../client.js";
|
|
3
|
+
import { cacheGet, cacheSet } from "../cache.js";
|
|
4
|
+
import { writeAdsJson, writeAdsOutput } from "../output.js";
|
|
5
|
+
import { csvOrJson, handleLinkedinError } from "./shared.js";
|
|
6
|
+
const ACCOUNTS_TTL_MS = 60 * 60 * 1000;
|
|
7
|
+
export const accountsCommand = defineCommand({
|
|
8
|
+
meta: {
|
|
9
|
+
name: "accounts",
|
|
10
|
+
description: `List LinkedIn ad accounts in this company's connected scope.
|
|
11
|
+
|
|
12
|
+
Examples:
|
|
13
|
+
baker ads linkedin accounts
|
|
14
|
+
baker ads linkedin accounts --include-all # ignore picker scope, list every account the token can see
|
|
15
|
+
baker ads linkedin accounts --output csv`,
|
|
16
|
+
},
|
|
17
|
+
args: {
|
|
18
|
+
"include-all": { type: "boolean", description: "List all accessible accounts, ignoring picker scope" },
|
|
19
|
+
"no-cache": { type: "boolean", description: "Skip CLI-side cache" },
|
|
20
|
+
"skip-cache": { type: "boolean", description: "Bypass server-side cache (force re-fetch)" },
|
|
21
|
+
output: { type: "string", description: "Output format: json|csv|jsonl|md", default: "json" },
|
|
22
|
+
},
|
|
23
|
+
run: async ({ args }) => {
|
|
24
|
+
const includeAll = args["include-all"] === true;
|
|
25
|
+
const useCache = !args["no-cache"];
|
|
26
|
+
const cacheKey = `accounts:${includeAll ? "all" : "scoped"}`;
|
|
27
|
+
if (useCache) {
|
|
28
|
+
const cached = cacheGet("linkedin-accounts", cacheKey);
|
|
29
|
+
if (cached) {
|
|
30
|
+
writeAdsJson({ ok: true, data: cached.data, cached: true });
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
const params = {};
|
|
36
|
+
if (includeAll)
|
|
37
|
+
params["include-all"] = "true";
|
|
38
|
+
if (args["skip-cache"])
|
|
39
|
+
params["skip-cache"] = "true";
|
|
40
|
+
const data = await apiGet("/api/ads/linkedin/accounts", params);
|
|
41
|
+
if (useCache) {
|
|
42
|
+
cacheSet("linkedin-accounts", cacheKey, data, ACCOUNTS_TTL_MS);
|
|
43
|
+
}
|
|
44
|
+
const fmt = csvOrJson(args);
|
|
45
|
+
if (fmt !== "json") {
|
|
46
|
+
writeAdsOutput(data, fmt);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
writeAdsJson({ ok: true, data });
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
handleLinkedinError(err);
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
//# sourceMappingURL=accounts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accounts.js","sourceRoot":"","sources":["../../../../src/commands/ads/linkedin/accounts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAY7D,MAAM,eAAe,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEvC,MAAM,CAAC,MAAM,eAAe,GAAG,aAAa,CAAC;IAC3C,IAAI,EAAE;QACJ,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE;;;;;2CAK0B;KACxC;IACD,IAAI,EAAE;QACJ,aAAa,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,qDAAqD,EAAE;QACtG,UAAU,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,qBAAqB,EAAE;QACnE,YAAY,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,2CAA2C,EAAE;QAC3F,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kCAAkC,EAAE,OAAO,EAAE,MAAM,EAAE;KAC7F;IACD,GAAG,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QACtB,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC;QAChD,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACnC,MAAM,QAAQ,GAAG,YAAY,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC7D,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,MAAM,GAAG,QAAQ,CAAoB,mBAAmB,EAAE,QAAQ,CAAC,CAAC;YAC1E,IAAI,MAAM,EAAE,CAAC;gBACX,YAAY,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC5D,OAAO;YACT,CAAC;QACH,CAAC;QACD,IAAI,CAAC;YACH,MAAM,MAAM,GAA2B,EAAE,CAAC;YAC1C,IAAI,UAAU;gBAAE,MAAM,CAAC,aAAa,CAAC,GAAG,MAAM,CAAC;YAC/C,IAAI,IAAI,CAAC,YAAY,CAAC;gBAAE,MAAM,CAAC,YAAY,CAAC,GAAG,MAAM,CAAC;YACtD,MAAM,IAAI,GAAG,MAAM,MAAM,CAAoB,4BAA4B,EAAE,MAAM,CAAC,CAAC;YACnF,IAAI,QAAQ,EAAE,CAAC;gBACb,QAAQ,CAAC,mBAAmB,EAAE,QAAQ,EAAE,IAAI,EAAE,eAAe,CAAC,CAAC;YACjE,CAAC;YACD,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAC5B,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;gBACnB,cAAc,CAAC,IAAiD,EAAE,GAAG,CAAC,CAAC;gBACvE,OAAO;YACT,CAAC;YACD,YAAY,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACnC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,mBAAmB,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
export declare const analyticsCommand: import("citty").CommandDef<{
|
|
2
|
+
readonly level: {
|
|
3
|
+
readonly type: "string";
|
|
4
|
+
readonly description: "Object scope (default: account)";
|
|
5
|
+
};
|
|
6
|
+
readonly "account-id": {
|
|
7
|
+
readonly type: "string";
|
|
8
|
+
readonly description: "Account ID — numeric or urn:li:sponsoredAccount:N (level=account)";
|
|
9
|
+
};
|
|
10
|
+
readonly "account-urn": {
|
|
11
|
+
readonly type: "string";
|
|
12
|
+
readonly description: "Alias for --account-id (URN form)";
|
|
13
|
+
};
|
|
14
|
+
readonly "campaign-group-id": {
|
|
15
|
+
readonly type: "string";
|
|
16
|
+
readonly description: "Comma-separated IDs (level=campaign-group)";
|
|
17
|
+
};
|
|
18
|
+
readonly "campaign-id": {
|
|
19
|
+
readonly type: "string";
|
|
20
|
+
readonly description: "Comma-separated IDs (level=campaign)";
|
|
21
|
+
};
|
|
22
|
+
readonly "creative-id": {
|
|
23
|
+
readonly type: "string";
|
|
24
|
+
readonly description: "Comma-separated IDs (level=creative)";
|
|
25
|
+
};
|
|
26
|
+
readonly ids: {
|
|
27
|
+
readonly type: "string";
|
|
28
|
+
readonly description: "Generic CSV of IDs at the chosen level (alternative to per-level flags)";
|
|
29
|
+
};
|
|
30
|
+
readonly intent: {
|
|
31
|
+
readonly type: "string";
|
|
32
|
+
readonly description: "baseline|revenue|funnel|engagement|video|lead-gen|inmail|document|ranking|identity";
|
|
33
|
+
};
|
|
34
|
+
readonly pivot: {
|
|
35
|
+
readonly type: "string";
|
|
36
|
+
readonly description: "Pivot dim. Default: none. See `--list-pivots`.";
|
|
37
|
+
};
|
|
38
|
+
readonly metrics: {
|
|
39
|
+
readonly type: "string";
|
|
40
|
+
readonly description: "CSV metric override — bypass --intent's bundle";
|
|
41
|
+
};
|
|
42
|
+
readonly "list-intents": {
|
|
43
|
+
readonly type: "boolean";
|
|
44
|
+
readonly description: "Print intent definitions and exit";
|
|
45
|
+
};
|
|
46
|
+
readonly "list-pivots": {
|
|
47
|
+
readonly type: "boolean";
|
|
48
|
+
readonly description: "Print pivot slugs and exit";
|
|
49
|
+
};
|
|
50
|
+
readonly start: {
|
|
51
|
+
readonly type: "string";
|
|
52
|
+
readonly description: "Start date YYYY-MM-DD (overrides --last-days)";
|
|
53
|
+
};
|
|
54
|
+
readonly end: {
|
|
55
|
+
readonly type: "string";
|
|
56
|
+
readonly description: "End date YYYY-MM-DD";
|
|
57
|
+
};
|
|
58
|
+
readonly "last-days": {
|
|
59
|
+
readonly type: "string";
|
|
60
|
+
readonly description: "Window relative to today (default: 7)";
|
|
61
|
+
};
|
|
62
|
+
readonly granularity: {
|
|
63
|
+
readonly type: "string";
|
|
64
|
+
readonly description: "DAILY|MONTHLY|YEARLY|ALL (default: DAILY)";
|
|
65
|
+
};
|
|
66
|
+
readonly limit: {
|
|
67
|
+
readonly type: "string";
|
|
68
|
+
readonly description: "Max rows (default: 1000)";
|
|
69
|
+
};
|
|
70
|
+
readonly "no-sort": {
|
|
71
|
+
readonly type: "boolean";
|
|
72
|
+
readonly description: "Skip default sort by costInUsd desc";
|
|
73
|
+
};
|
|
74
|
+
readonly "skip-cache": {
|
|
75
|
+
readonly type: "boolean";
|
|
76
|
+
readonly description: "Bypass server-side cache";
|
|
77
|
+
};
|
|
78
|
+
readonly output: {
|
|
79
|
+
readonly type: "string";
|
|
80
|
+
readonly description: "Output format json|csv|jsonl|md";
|
|
81
|
+
readonly default: "json";
|
|
82
|
+
};
|
|
83
|
+
}>;
|
|
84
|
+
//# sourceMappingURL=analytics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/linkedin/analytics.ts"],"names":[],"mappings":"AAgKA,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmI3B,CAAC"}
|