@koda-sl/baker-cli 0.16.0 → 0.19.0-dev.7ebf7748
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 +302 -2
- package/dist/cli.js +1 -1
- package/dist/client.d.ts +3 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +25 -5
- package/dist/client.js.map +1 -1
- package/dist/commands/ads/google/index.d.ts.map +1 -1
- package/dist/commands/ads/google/index.js +5 -1
- package/dist/commands/ads/google/index.js.map +1 -1
- package/dist/commands/ads/google/library/index.d.ts +2 -0
- package/dist/commands/ads/google/library/index.d.ts.map +1 -0
- package/dist/commands/ads/google/library/index.js +271 -0
- package/dist/commands/ads/google/library/index.js.map +1 -0
- package/dist/commands/research/index.d.ts.map +1 -1
- package/dist/commands/research/index.js +7 -5
- package/dist/commands/research/index.js.map +1 -1
- package/dist/commands/research/web.d.ts +19 -0
- package/dist/commands/research/web.d.ts.map +1 -0
- package/dist/commands/research/web.js +112 -0
- package/dist/commands/research/web.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -383,6 +383,260 @@ baker ads google keywords metrics --customer-id 1234567890 --keywords "running s
|
|
|
383
383
|
|
|
384
384
|
---
|
|
385
385
|
|
|
386
|
+
### Google Ads Library (`baker ads google library`)
|
|
387
|
+
|
|
388
|
+
Manage and search the Google Ads Transparency Center. Track competitor advertisers, browse their ad creatives, and discover who's bidding on keywords.
|
|
389
|
+
|
|
390
|
+
**Typical workflow:** `search-advertiser` → `track` → `search-ads`
|
|
391
|
+
|
|
392
|
+
---
|
|
393
|
+
|
|
394
|
+
### `baker ads google library search-advertiser "query"`
|
|
395
|
+
|
|
396
|
+
Search for an advertiser on the Google Ads Transparency Center.
|
|
397
|
+
|
|
398
|
+
```bash
|
|
399
|
+
baker ads google library search-advertiser "Nike"
|
|
400
|
+
baker ads google library search-advertiser "example.com"
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
**Response:**
|
|
404
|
+
|
|
405
|
+
```json
|
|
406
|
+
{
|
|
407
|
+
"ok": true,
|
|
408
|
+
"data": {
|
|
409
|
+
"results": [
|
|
410
|
+
{ "advertiserId": "AR12345678901234567", "name": "Nike, Inc.", "region": "US", "format": "TEXT_IMAGE_VIDEO" }
|
|
411
|
+
]
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
**Flags:**
|
|
417
|
+
|
|
418
|
+
| Flag | Description |
|
|
419
|
+
|------------|--------------------------------|
|
|
420
|
+
| `--output` | Format: `json` \| `csv` \| `md` |
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
|
|
424
|
+
### `baker ads google library track <id> <name>`
|
|
425
|
+
|
|
426
|
+
Track a new Google advertiser and wait for the initial ad sync to complete. Polls every 5 seconds with a 10-minute timeout. Progress is written to stderr.
|
|
427
|
+
|
|
428
|
+
```bash
|
|
429
|
+
baker ads google library track AR12345678901234567 "Nike, Inc."
|
|
430
|
+
baker ads google library track AR12345678901234567 "Nike, Inc." --json
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
**Response (with `--json`):**
|
|
434
|
+
|
|
435
|
+
```json
|
|
436
|
+
{
|
|
437
|
+
"ok": true,
|
|
438
|
+
"data": {
|
|
439
|
+
"advertiserId": "ar_abc123",
|
|
440
|
+
"accountId": "acc_def456",
|
|
441
|
+
"totalAdCount": 342,
|
|
442
|
+
"activeAdCount": 89
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
**Flags:**
|
|
448
|
+
|
|
449
|
+
| Flag | Description |
|
|
450
|
+
|----------|----------------------|
|
|
451
|
+
| `--json` | Output in JSON format |
|
|
452
|
+
|
|
453
|
+
---
|
|
454
|
+
|
|
455
|
+
### `baker ads google library list-advertisers`
|
|
456
|
+
|
|
457
|
+
List all tracked Google advertisers and their accounts.
|
|
458
|
+
|
|
459
|
+
```bash
|
|
460
|
+
baker ads google library list-advertisers
|
|
461
|
+
baker ads google library list-advertisers --output md
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
**Flags:**
|
|
465
|
+
|
|
466
|
+
| Flag | Description |
|
|
467
|
+
|------------|--------------------------------|
|
|
468
|
+
| `--output` | Format: `json` \| `csv` \| `md` |
|
|
469
|
+
|
|
470
|
+
---
|
|
471
|
+
|
|
472
|
+
### `baker ads google library sync-status <accountId>`
|
|
473
|
+
|
|
474
|
+
Check the sync status and ad counts of a tracked account.
|
|
475
|
+
|
|
476
|
+
```bash
|
|
477
|
+
baker ads google library sync-status acc_def456
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
**Response:**
|
|
481
|
+
|
|
482
|
+
```json
|
|
483
|
+
{
|
|
484
|
+
"ok": true,
|
|
485
|
+
"data": {
|
|
486
|
+
"syncStatus": null,
|
|
487
|
+
"totalAdCount": 342,
|
|
488
|
+
"activeAdCount": 89
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
`syncStatus` is `null` when idle, `"syncing"` during a sync, or `"error"` if the last sync failed.
|
|
494
|
+
|
|
495
|
+
---
|
|
496
|
+
|
|
497
|
+
### `baker ads google library search-ads <accountId>`
|
|
498
|
+
|
|
499
|
+
Search and filter ads for a tracked account. Supports pagination.
|
|
500
|
+
|
|
501
|
+
```bash
|
|
502
|
+
baker ads google library search-ads acc_def456
|
|
503
|
+
baker ads google library search-ads acc_def456 --search "summer sale" --isActive --mediaType image
|
|
504
|
+
baker ads google library search-ads acc_def456 --sort newest --limit 50
|
|
505
|
+
baker ads google library search-ads acc_def456 --cursor "eyJwYWdl..."
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
**Response:**
|
|
509
|
+
|
|
510
|
+
```json
|
|
511
|
+
{
|
|
512
|
+
"ok": true,
|
|
513
|
+
"data": {
|
|
514
|
+
"page": [
|
|
515
|
+
{
|
|
516
|
+
"_id": "abc123",
|
|
517
|
+
"platform": "google",
|
|
518
|
+
"externalId": "CR_1234567890",
|
|
519
|
+
"isActive": true,
|
|
520
|
+
"mediaType": "image",
|
|
521
|
+
"headline": "Summer Sale — 50% Off Everything",
|
|
522
|
+
"description": "Shop our biggest sale of the year. Free shipping on all orders.",
|
|
523
|
+
"destinationUrl": "https://example.com/summer-sale",
|
|
524
|
+
"bodyText": "Summer Sale — 50% Off Everything",
|
|
525
|
+
"pageName": "Example Store",
|
|
526
|
+
"impressionsMin": 100000,
|
|
527
|
+
"impressionsMax": 200000,
|
|
528
|
+
"startDate": "2025-06-01",
|
|
529
|
+
"endDate": "2025-06-30",
|
|
530
|
+
"firstSeenAt": 1717200000000,
|
|
531
|
+
"lastSeenAt": 1719792000000,
|
|
532
|
+
"publisherPlatforms": ["GOOGLE_ADS"],
|
|
533
|
+
"regionCodes": ["US", "GB"],
|
|
534
|
+
"variations": [
|
|
535
|
+
{
|
|
536
|
+
"headline": "Summer Sale — 50% Off",
|
|
537
|
+
"description": "Shop our biggest sale of the year.",
|
|
538
|
+
"destinationUrl": "https://example.com/summer-sale",
|
|
539
|
+
"imageUrl": "https://...",
|
|
540
|
+
"visibleUrl": "example.com"
|
|
541
|
+
}
|
|
542
|
+
],
|
|
543
|
+
"regions": [
|
|
544
|
+
{ "code": "US", "name": "United States" }
|
|
545
|
+
],
|
|
546
|
+
"analysisStatus": "completed",
|
|
547
|
+
"aiAnalysis": {
|
|
548
|
+
"aiSummary": "Promotional display ad for a seasonal sale with urgency-driven CTA",
|
|
549
|
+
"hookAngle": "Discount/Price",
|
|
550
|
+
"offerType": "Percentage Discount",
|
|
551
|
+
"ctaStrategy": "Shop Now",
|
|
552
|
+
"funnelStage": "Bottom",
|
|
553
|
+
"targetAudience": "Price-sensitive shoppers",
|
|
554
|
+
"adFormat": "responsive_display",
|
|
555
|
+
"tags": ["sale", "discount", "ecommerce"],
|
|
556
|
+
"trustSignals": ["Free shipping"],
|
|
557
|
+
"keyMessages": ["50% off", "Free shipping"],
|
|
558
|
+
"competitiveAngle": "Price leadership",
|
|
559
|
+
"dominantColors": ["#FF5733", "#FFFFFF"],
|
|
560
|
+
"analyzedAt": 1719792000000
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
],
|
|
564
|
+
"continueCursor": "eyJwYWdl...",
|
|
565
|
+
"isDone": false
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
**Key response fields:**
|
|
571
|
+
|
|
572
|
+
| Field | Description |
|
|
573
|
+
|-------|-------------|
|
|
574
|
+
| `headline`, `description` | Top-level ad copy (first variation) |
|
|
575
|
+
| `variations[]` | All ad variations with copy, images, videos, and URLs |
|
|
576
|
+
| `regions[]` | Geographic targeting regions |
|
|
577
|
+
| `impressionsMin/Max` | Estimated impression range (Google Ads Transparency data) |
|
|
578
|
+
| `publisherPlatforms` | Where the ad ran (GOOGLE_ADS, YOUTUBE, etc.) |
|
|
579
|
+
| `analysisStatus` | AI analysis state: `pending`, `processing`, `completed`, `failed` |
|
|
580
|
+
| `aiAnalysis` | AI-generated creative analysis (only present when `analysisStatus` is `completed`) |
|
|
581
|
+
| `aiAnalysis.aiSummary` | One-line AI summary of the ad |
|
|
582
|
+
| `aiAnalysis.hookAngle` | Creative hook (Discount, Fear, Social Proof, etc.) |
|
|
583
|
+
| `aiAnalysis.funnelStage` | Funnel position: Top, Middle, Bottom |
|
|
584
|
+
| `aiAnalysis.tags` | AI-generated tags for filtering |
|
|
585
|
+
|
|
586
|
+
**Flags:**
|
|
587
|
+
|
|
588
|
+
| Flag | Description |
|
|
589
|
+
|---------------|------------------------------------------------|
|
|
590
|
+
| `--search` | Search term for ad text |
|
|
591
|
+
| `--isActive` | Filter by active ads only |
|
|
592
|
+
| `--mediaType` | Filter by media type: `image`, `video`, `text` |
|
|
593
|
+
| `--sort` | Sort: `newest` or `oldest` |
|
|
594
|
+
| `--limit` | Max results per page (default 20, max 100) |
|
|
595
|
+
| `--cursor` | Pagination cursor from previous response |
|
|
596
|
+
| `--output` | Format: `json` \| `csv` \| `md` |
|
|
597
|
+
|
|
598
|
+
---
|
|
599
|
+
|
|
600
|
+
### `baker ads google library sync <accountId>`
|
|
601
|
+
|
|
602
|
+
Trigger an immediate re-sync for a tracked account. Polls every 5 seconds until complete (10-minute timeout). Progress is written to stderr.
|
|
603
|
+
|
|
604
|
+
```bash
|
|
605
|
+
baker ads google library sync acc_def456
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
**Response:**
|
|
609
|
+
|
|
610
|
+
```json
|
|
611
|
+
{
|
|
612
|
+
"ok": true,
|
|
613
|
+
"data": {
|
|
614
|
+
"totalAdCount": 350,
|
|
615
|
+
"activeAdCount": 92
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
---
|
|
621
|
+
|
|
622
|
+
### `baker ads google library search-competitors "keyword"`
|
|
623
|
+
|
|
624
|
+
Search for competitors running Google ads for a keyword. Uses DataForSEO (same data as `baker research advertisers`).
|
|
625
|
+
|
|
626
|
+
```bash
|
|
627
|
+
baker ads google library search-competitors "running shoes"
|
|
628
|
+
baker ads google library search-competitors "crm software" --location uk
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
**Flags:**
|
|
632
|
+
|
|
633
|
+
| Flag | Description |
|
|
634
|
+
|--------------|----------------------------|
|
|
635
|
+
| `--location` | Location name or code |
|
|
636
|
+
| `--json` | Output in JSON format |
|
|
637
|
+
|
|
638
|
+
---
|
|
639
|
+
|
|
386
640
|
### Caching
|
|
387
641
|
|
|
388
642
|
Google Ads data is cached at two levels:
|
|
@@ -587,9 +841,55 @@ baker gsc sitemaps --site-url "https://example.com/"
|
|
|
587
841
|
|
|
588
842
|
### Competitive Intelligence (`baker research`)
|
|
589
843
|
|
|
590
|
-
Market and competitor research powered by DataForSEO. Shows who's competing for keywords, search intent classification, competitor keyword strategies, keyword gaps,
|
|
844
|
+
Market and competitor research powered by DataForSEO and AI-powered Google Search grounding. Shows who's competing for keywords, search intent classification, competitor keyword strategies, keyword gaps, landing page performance, and open-ended AI research.
|
|
845
|
+
|
|
846
|
+
All DataForSEO research responses include a `note` field indicating that data is estimated from third-party SERP scraping and should be used for directional insights, not precise measurement.
|
|
847
|
+
|
|
848
|
+
---
|
|
849
|
+
|
|
850
|
+
### `baker research web "question"`
|
|
851
|
+
|
|
852
|
+
Search the web with AI to answer any open-ended marketing question — competitors, ICP, pricing, pain points, market trends. Uses live internet data via Google Search.
|
|
853
|
+
|
|
854
|
+
```bash
|
|
855
|
+
baker research web "Who are the main competitors of HubSpot CRM?"
|
|
856
|
+
baker research web "What are the top pain points for SMB CRM buyers?" --depth high
|
|
857
|
+
baker research web "Full competitive analysis of project management SaaS" --depth xhigh
|
|
858
|
+
baker research web "What is the pricing of monday.com?" --output md
|
|
859
|
+
```
|
|
860
|
+
|
|
861
|
+
**Depth levels:**
|
|
862
|
+
|
|
863
|
+
| Depth | Model | Use case | Timeout |
|
|
864
|
+
|-------|-------|----------|---------|
|
|
865
|
+
| `medium` (default) | Gemini Flash + minimal thinking | Quick lookups | 3m |
|
|
866
|
+
| `high` | Gemini Flash + deep thinking | Thorough answers | 6m |
|
|
867
|
+
| `xhigh` | Gemini Deep Research | Exhaustive research (use sparingly) | 15m |
|
|
868
|
+
|
|
869
|
+
**Response:**
|
|
870
|
+
|
|
871
|
+
```json
|
|
872
|
+
{
|
|
873
|
+
"ok": true,
|
|
874
|
+
"data": {
|
|
875
|
+
"answer": "## HubSpot CRM Competitors\n\n### 1. Salesforce\n...",
|
|
876
|
+
"sources": [
|
|
877
|
+
{ "title": "HubSpot vs Salesforce", "url": "https://..." }
|
|
878
|
+
]
|
|
879
|
+
},
|
|
880
|
+
"fields": {
|
|
881
|
+
"answer": "AI-generated research answer (markdown)",
|
|
882
|
+
"sources": "Array of {title, url} sources used for grounding"
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
```
|
|
886
|
+
|
|
887
|
+
**Flags:**
|
|
591
888
|
|
|
592
|
-
|
|
889
|
+
| Flag | Description |
|
|
890
|
+
|------------|------------------------------------------------------|
|
|
891
|
+
| `--depth` | Research depth: medium (default), high, xhigh |
|
|
892
|
+
| `--output` | Format: json (default), md (raw markdown + sources) |
|
|
593
893
|
|
|
594
894
|
---
|
|
595
895
|
|
package/dist/cli.js
CHANGED
|
@@ -11,7 +11,7 @@ import { videosCommand } from "./commands/videos/index.js";
|
|
|
11
11
|
const main = defineCommand({
|
|
12
12
|
meta: {
|
|
13
13
|
name: "baker",
|
|
14
|
-
version: "0.
|
|
14
|
+
version: "0.19.0",
|
|
15
15
|
description: `AI-agent CLI for finding and managing images, videos, testimonials, and ad platform data in Baker.
|
|
16
16
|
|
|
17
17
|
Auth: Set BAKER_API_KEY (starts with bk_) and BAKER_API_URL environment variables.
|
package/dist/client.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ export declare class ApiError extends Error {
|
|
|
5
5
|
}
|
|
6
6
|
export declare function validateConvexId(id: string): void;
|
|
7
7
|
export declare function apiGet<T>(path: string, params?: Record<string, string>): Promise<T>;
|
|
8
|
-
export declare function apiPost<T>(path: string, body: unknown
|
|
8
|
+
export declare function apiPost<T>(path: string, body: unknown, opts?: {
|
|
9
|
+
timeoutMs?: number;
|
|
10
|
+
}): Promise<T>;
|
|
9
11
|
export {};
|
|
10
12
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AA6BA,KAAK,SAAS,GACV,cAAc,GACd,WAAW,GACX,kBAAkB,GAClB,cAAc,GACd,gBAAgB,GAChB,eAAe,GACf,SAAS,CAAC;AAEd,qBAAa,QAAS,SAAQ,KAAK;IACjC,IAAI,EAAE,SAAS,CAAC;gBAEJ,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM;CAK7C;AAqBD,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAIjD;AAsDD,wBAAsB,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CA4BzF;AAED,wBAAsB,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAuBvG"}
|
package/dist/client.js
CHANGED
|
@@ -1,4 +1,23 @@
|
|
|
1
1
|
import { getEnv } from "./env.js";
|
|
2
|
+
const MAX_RATE_LIMIT_RETRIES = 3;
|
|
3
|
+
const MAX_TOTAL_WAIT_MS = 2 * 60 * 1000;
|
|
4
|
+
async function fetchWithRateLimitRetry(url, init) {
|
|
5
|
+
let totalWaited = 0;
|
|
6
|
+
for (let attempt = 0; attempt <= MAX_RATE_LIMIT_RETRIES; attempt++) {
|
|
7
|
+
const response = await fetch(url, init);
|
|
8
|
+
if (response.status !== 429 || attempt >= MAX_RATE_LIMIT_RETRIES) {
|
|
9
|
+
return response;
|
|
10
|
+
}
|
|
11
|
+
const retryAfterHeader = response.headers.get("Retry-After");
|
|
12
|
+
const waitMs = retryAfterHeader ? Number(retryAfterHeader) * 1000 : 2000 * 2 ** attempt;
|
|
13
|
+
if (totalWaited + waitMs > MAX_TOTAL_WAIT_MS) {
|
|
14
|
+
return response;
|
|
15
|
+
}
|
|
16
|
+
totalWaited += waitMs;
|
|
17
|
+
await new Promise((resolve) => setTimeout(resolve, waitMs));
|
|
18
|
+
}
|
|
19
|
+
return fetch(url, init);
|
|
20
|
+
}
|
|
2
21
|
export class ApiError extends Error {
|
|
3
22
|
code;
|
|
4
23
|
constructor(code, message) {
|
|
@@ -90,7 +109,7 @@ export async function apiGet(path, params) {
|
|
|
90
109
|
}
|
|
91
110
|
let response;
|
|
92
111
|
try {
|
|
93
|
-
response = await
|
|
112
|
+
response = await fetchWithRateLimitRetry(url.toString(), {
|
|
94
113
|
method: "GET",
|
|
95
114
|
headers: {
|
|
96
115
|
Authorization: `Bearer ${env.BAKER_API_KEY}`,
|
|
@@ -107,11 +126,12 @@ export async function apiGet(path, params) {
|
|
|
107
126
|
}
|
|
108
127
|
return handleResponse(response);
|
|
109
128
|
}
|
|
110
|
-
export async function apiPost(path, body) {
|
|
129
|
+
export async function apiPost(path, body, opts) {
|
|
111
130
|
const env = getEnv();
|
|
131
|
+
const timeoutMs = opts?.timeoutMs ?? 60_000;
|
|
112
132
|
let response;
|
|
113
133
|
try {
|
|
114
|
-
response = await
|
|
134
|
+
response = await fetchWithRateLimitRetry(new URL(path, env.BAKER_API_URL).toString(), {
|
|
115
135
|
method: "POST",
|
|
116
136
|
headers: {
|
|
117
137
|
Authorization: `Bearer ${env.BAKER_API_KEY}`,
|
|
@@ -119,12 +139,12 @@ export async function apiPost(path, body) {
|
|
|
119
139
|
Accept: "application/json",
|
|
120
140
|
},
|
|
121
141
|
body: JSON.stringify(body),
|
|
122
|
-
signal: AbortSignal.timeout(
|
|
142
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
123
143
|
});
|
|
124
144
|
}
|
|
125
145
|
catch (err) {
|
|
126
146
|
if (err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError")) {
|
|
127
|
-
throw new ApiError("TIMEOUT",
|
|
147
|
+
throw new ApiError("TIMEOUT", `Request timed out after ${Math.round(timeoutMs / 1000)} seconds`);
|
|
128
148
|
}
|
|
129
149
|
throw new ApiError("NETWORK_ERROR", `Request failed: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
130
150
|
}
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,MAAM,sBAAsB,GAAG,CAAC,CAAC;AACjC,MAAM,iBAAiB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAExC,KAAK,UAAU,uBAAuB,CAAC,GAAW,EAAE,IAAiB;IACnE,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,sBAAsB,EAAE,OAAO,EAAE,EAAE,CAAC;QACnE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAExC,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,OAAO,IAAI,sBAAsB,EAAE,CAAC;YACjE,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,MAAM,gBAAgB,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAC7D,MAAM,MAAM,GAAG,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,OAAO,CAAC;QAExF,IAAI,WAAW,GAAG,MAAM,GAAG,iBAAiB,EAAE,CAAC;YAC7C,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,WAAW,IAAI,MAAM,CAAC;QACtB,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IAC9D,CAAC;IAED,OAAO,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AAC1B,CAAC;AAWD,MAAM,OAAO,QAAS,SAAQ,KAAK;IACjC,IAAI,CAAY;IAEhB,YAAY,IAAe,EAAE,OAAe;QAC1C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED,MAAM,YAAY,GAAG,iBAAiB,CAAC;AAEvC,SAAS,oBAAoB,CAAC,KAAa;IACzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACjC,oDAAoD;QACpD,IAAI,IAAI,GAAG,EAAE,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,EAAE,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;YAC1D,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAa;IACxC,IAAI,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,QAAQ,CAAC,kBAAkB,EAAE,kDAAkD,CAAC,CAAC;IAC7F,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,EAAU;IACzC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,QAAQ,CAAC,kBAAkB,EAAE,uBAAuB,EAAE,kCAAkC,CAAC,CAAC;IACtG,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,MAA8B;IACpD,MAAM,SAAS,GAA2B,EAAE,CAAC;IAC7C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,mBAAmB,CAAC,KAAK,CAAC,CAAC;QAC3B,SAAS,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACzB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,YAAY,CAAC,MAAc;IAClC,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;QACrC,OAAO,cAAc,CAAC;IACxB,CAAC;IACD,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;QACnB,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;QACrC,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IACD,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;QACnB,OAAO,cAAc,CAAC;IACxB,CAAC;IACD,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED,KAAK,UAAU,cAAc,CAAI,QAAkB;IACjD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAEnC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,IAAI,OAAO,GAAG,QAAQ,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,UAAU,EAAE,CAAC;QAChE,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAgE,CAAC;YAC/F,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;gBACrC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC;YACzB,CAAC;iBAAM,IAAI,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC;gBACjC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC;YACjC,CAAC;iBAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBAC1B,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;YAC3B,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,sBAAsB;QACxB,CAAC;QACD,MAAM,IAAI,QAAQ,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;IAC7D,CAAC;IAED,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAM,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,QAAQ,CAAC,gBAAgB,EAAE,sCAAsC,CAAC,CAAC;IAC/E,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAI,IAAY,EAAE,MAA+B;IAC3E,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;IACrB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC;IAC7C,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,KAAK,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QACrC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACjD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAED,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,uBAAuB,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE;YACvD,MAAM,EAAE,KAAK;YACb,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,GAAG,CAAC,aAAa,EAAE;gBAC5C,MAAM,EAAE,kBAAkB;aAC3B;YACD,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;SACpC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,KAAK,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,cAAc,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,CAAC,EAAE,CAAC;YACvF,MAAM,IAAI,QAAQ,CAAC,SAAS,EAAE,oCAAoC,CAAC,CAAC;QACtE,CAAC;QACD,MAAM,IAAI,QAAQ,CAAC,eAAe,EAAE,mBAAmB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC;IACjH,CAAC;IAED,OAAO,cAAc,CAAI,QAAQ,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAAI,IAAY,EAAE,IAAa,EAAE,IAA6B;IACzF,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;IACrB,MAAM,SAAS,GAAG,IAAI,EAAE,SAAS,IAAI,MAAM,CAAC;IAC5C,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,uBAAuB,CAAC,IAAI,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC,QAAQ,EAAE,EAAE;YACpF,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,GAAG,CAAC,aAAa,EAAE;gBAC5C,cAAc,EAAE,kBAAkB;gBAClC,MAAM,EAAE,kBAAkB;aAC3B;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;YAC1B,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC;SACvC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,KAAK,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,cAAc,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,CAAC,EAAE,CAAC;YACvF,MAAM,IAAI,QAAQ,CAAC,SAAS,EAAE,2BAA2B,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;QACnG,CAAC;QACD,MAAM,IAAI,QAAQ,CAAC,eAAe,EAAE,mBAAmB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC;IACjH,CAAC;IAED,OAAO,cAAc,CAAI,QAAQ,CAAC,CAAC;AACrC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/google/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/google/index.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,aAAa,qDAyBxB,CAAC"}
|
|
@@ -3,6 +3,7 @@ import { accountsCommand } from "./accounts.js";
|
|
|
3
3
|
import { changesCommand } from "./changes.js";
|
|
4
4
|
import { currencyCommand } from "./currency.js";
|
|
5
5
|
import { keywordsCommand } from "./keywords/index.js";
|
|
6
|
+
import { library } from "./library/index.js";
|
|
6
7
|
import { queryCommand } from "./query.js";
|
|
7
8
|
export const googleCommand = defineCommand({
|
|
8
9
|
meta: {
|
|
@@ -12,12 +13,14 @@ export const googleCommand = defineCommand({
|
|
|
12
13
|
Start here:
|
|
13
14
|
baker ads google accounts — list accessible accounts
|
|
14
15
|
baker ads google query --list-presets — see available query templates
|
|
16
|
+
baker ads google library --help — manage and search the Google Ads Library
|
|
15
17
|
|
|
16
18
|
Examples:
|
|
17
19
|
baker ads google query "SELECT campaign.name, metrics.clicks FROM campaign WHERE segments.date DURING LAST_7_DAYS" --customer-id 1234567890
|
|
18
20
|
baker ads google query --preset campaign-performance --customer-id 1234567890
|
|
19
21
|
baker ads google currency --customer-id 1234567890
|
|
20
|
-
baker ads google keywords discover --customer-id 1234567890 --seeds "running shoes"
|
|
22
|
+
baker ads google keywords discover --customer-id 1234567890 --seeds "running shoes"
|
|
23
|
+
baker ads google library list-advertisers — list tracked Google advertisers`,
|
|
21
24
|
},
|
|
22
25
|
subCommands: {
|
|
23
26
|
accounts: accountsCommand,
|
|
@@ -25,6 +28,7 @@ Examples:
|
|
|
25
28
|
changes: changesCommand,
|
|
26
29
|
query: queryCommand,
|
|
27
30
|
keywords: keywordsCommand,
|
|
31
|
+
library: library,
|
|
28
32
|
},
|
|
29
33
|
});
|
|
30
34
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/commands/ads/google/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAAC;IACzC,IAAI,EAAE;QACJ,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/commands/ads/google/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAAC;IACzC,IAAI,EAAE;QACJ,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE;;;;;;;;;;;;iFAYgE;KAC9E;IACD,WAAW,EAAE;QACX,QAAQ,EAAE,eAAe;QACzB,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,cAAc;QACvB,KAAK,EAAE,YAAY;QACnB,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,OAAO;KACjB;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/commands/ads/google/library/index.ts"],"names":[],"mappings":"AA0RA,eAAO,MAAM,OAAO,qDAclB,CAAC"}
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import { defineCommand } from "citty";
|
|
2
|
+
import { apiGet, apiPost } from "../../../../client.js";
|
|
3
|
+
import { writeAdsJson, writeAdsOutput } from "../../output.js";
|
|
4
|
+
const listAdvertisers = defineCommand({
|
|
5
|
+
meta: {
|
|
6
|
+
name: "list-advertisers",
|
|
7
|
+
description: "List tracked Google advertisers and their accounts",
|
|
8
|
+
},
|
|
9
|
+
args: {
|
|
10
|
+
output: { type: "string", description: "Format: json|csv|md", default: "json" },
|
|
11
|
+
},
|
|
12
|
+
async run({ args }) {
|
|
13
|
+
const data = await apiGet("/api/ads/google/library/advertisers");
|
|
14
|
+
if (args.output !== "json") {
|
|
15
|
+
writeAdsOutput(data, args.output);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
writeAdsJson({ ok: true, data });
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
const syncStatus = defineCommand({
|
|
23
|
+
meta: {
|
|
24
|
+
name: "sync-status",
|
|
25
|
+
description: "Check the sync status and ad counts of a Google account",
|
|
26
|
+
},
|
|
27
|
+
args: {
|
|
28
|
+
accountId: {
|
|
29
|
+
type: "positional",
|
|
30
|
+
description: "Account ID to check",
|
|
31
|
+
required: true,
|
|
32
|
+
},
|
|
33
|
+
output: { type: "string", description: "Format: json", default: "json" },
|
|
34
|
+
},
|
|
35
|
+
async run({ args }) {
|
|
36
|
+
const data = await apiGet("/api/ads/google/library/account-status", {
|
|
37
|
+
accountId: args.accountId,
|
|
38
|
+
});
|
|
39
|
+
writeAdsJson({ ok: true, data });
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
const searchAds = defineCommand({
|
|
43
|
+
meta: {
|
|
44
|
+
name: "search-ads",
|
|
45
|
+
description: "Search and filter Google ads for an account",
|
|
46
|
+
},
|
|
47
|
+
args: {
|
|
48
|
+
accountId: {
|
|
49
|
+
type: "positional",
|
|
50
|
+
description: "Account ID to search in",
|
|
51
|
+
required: true,
|
|
52
|
+
},
|
|
53
|
+
search: {
|
|
54
|
+
type: "string",
|
|
55
|
+
description: "Search term for ad text",
|
|
56
|
+
},
|
|
57
|
+
isActive: {
|
|
58
|
+
type: "boolean",
|
|
59
|
+
description: "Filter by active ads only",
|
|
60
|
+
},
|
|
61
|
+
mediaType: {
|
|
62
|
+
type: "string",
|
|
63
|
+
description: "Filter by media type (image, video, text)",
|
|
64
|
+
},
|
|
65
|
+
sort: {
|
|
66
|
+
type: "string",
|
|
67
|
+
description: "Sort by newest or oldest",
|
|
68
|
+
},
|
|
69
|
+
limit: {
|
|
70
|
+
type: "string",
|
|
71
|
+
description: "Maximum number of ads to return (default 20)",
|
|
72
|
+
},
|
|
73
|
+
cursor: {
|
|
74
|
+
type: "string",
|
|
75
|
+
description: "Pagination cursor",
|
|
76
|
+
},
|
|
77
|
+
output: { type: "string", description: "Format: json|csv|md", default: "json" },
|
|
78
|
+
},
|
|
79
|
+
async run({ args }) {
|
|
80
|
+
const data = await apiPost("/api/ads/google/library/ads/search", {
|
|
81
|
+
accountId: args.accountId,
|
|
82
|
+
search: args.search,
|
|
83
|
+
isActive: args.isActive,
|
|
84
|
+
mediaType: args.mediaType,
|
|
85
|
+
sort: args.sort,
|
|
86
|
+
numItems: args.limit ? Number.parseInt(args.limit, 10) : undefined,
|
|
87
|
+
cursor: args.cursor,
|
|
88
|
+
});
|
|
89
|
+
if (args.output !== "json" && Array.isArray(data.page)) {
|
|
90
|
+
writeAdsOutput(data.page, args.output);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
writeAdsJson({ ok: true, data });
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
const searchAdvertiser = defineCommand({
|
|
98
|
+
meta: {
|
|
99
|
+
name: "search-advertiser",
|
|
100
|
+
description: "Search for an advertiser on the Google Ads Transparency Center",
|
|
101
|
+
},
|
|
102
|
+
args: {
|
|
103
|
+
query: {
|
|
104
|
+
type: "positional",
|
|
105
|
+
description: "Company name or domain to search for",
|
|
106
|
+
required: true,
|
|
107
|
+
},
|
|
108
|
+
output: { type: "string", description: "Format: json|csv|md", default: "json" },
|
|
109
|
+
},
|
|
110
|
+
async run({ args }) {
|
|
111
|
+
const data = await apiPost("/api/ads/google/library/search-advertiser", {
|
|
112
|
+
query: args.query,
|
|
113
|
+
});
|
|
114
|
+
if (args.output !== "json" && Array.isArray(data.results)) {
|
|
115
|
+
writeAdsOutput(data.results, args.output);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
writeAdsJson({ ok: true, data });
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
function sleep(ms) {
|
|
123
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
124
|
+
}
|
|
125
|
+
const track = defineCommand({
|
|
126
|
+
meta: {
|
|
127
|
+
name: "track",
|
|
128
|
+
description: "Track a new Google advertiser (from search results). Waits for initial sync to complete before returning.",
|
|
129
|
+
},
|
|
130
|
+
args: {
|
|
131
|
+
id: {
|
|
132
|
+
type: "positional",
|
|
133
|
+
description: "Google Advertiser ID (e.g. AR123...)",
|
|
134
|
+
required: true,
|
|
135
|
+
},
|
|
136
|
+
name: {
|
|
137
|
+
type: "positional",
|
|
138
|
+
description: "Display name for the advertiser",
|
|
139
|
+
required: true,
|
|
140
|
+
},
|
|
141
|
+
json: {
|
|
142
|
+
type: "boolean",
|
|
143
|
+
description: "Output in JSON format",
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
async run({ args }) {
|
|
147
|
+
const data = await apiPost("/api/ads/google/library/track", {
|
|
148
|
+
id: args.id,
|
|
149
|
+
name: args.name,
|
|
150
|
+
});
|
|
151
|
+
process.stderr.write(`Tracking "${args.name}" (${args.id}). Syncing ads...\n`);
|
|
152
|
+
const deadline = Date.now() + 600_000;
|
|
153
|
+
while (Date.now() < deadline) {
|
|
154
|
+
await sleep(5_000);
|
|
155
|
+
const status = await apiGet("/api/ads/google/library/account-status", {
|
|
156
|
+
accountId: data.accountId,
|
|
157
|
+
});
|
|
158
|
+
if (!status.syncStatus) {
|
|
159
|
+
process.stderr.write(`Sync complete. ${status.totalAdCount ?? 0} ads (${status.activeAdCount ?? 0} active)\n`);
|
|
160
|
+
if (args.json) {
|
|
161
|
+
writeAdsJson({ ok: true, data: { ...data, ...status } });
|
|
162
|
+
}
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
if (status.syncStatus === "error") {
|
|
166
|
+
process.stderr.write("Sync failed.\n");
|
|
167
|
+
writeAdsJson({ ok: false, error: { code: "SYNC_ERROR", message: "Initial sync failed" } });
|
|
168
|
+
process.exit(1);
|
|
169
|
+
}
|
|
170
|
+
process.stderr.write(` syncing...\n`);
|
|
171
|
+
}
|
|
172
|
+
process.stderr.write("Sync timed out after 10 minutes.\n");
|
|
173
|
+
writeAdsJson({
|
|
174
|
+
ok: false,
|
|
175
|
+
error: { code: "TIMEOUT", message: "Sync did not complete within 10 minutes" },
|
|
176
|
+
});
|
|
177
|
+
process.exit(1);
|
|
178
|
+
},
|
|
179
|
+
});
|
|
180
|
+
const sync = defineCommand({
|
|
181
|
+
meta: {
|
|
182
|
+
name: "sync",
|
|
183
|
+
description: "Trigger an immediate sync for a Google account. Waits for completion before returning.",
|
|
184
|
+
},
|
|
185
|
+
args: {
|
|
186
|
+
accountId: {
|
|
187
|
+
type: "positional",
|
|
188
|
+
description: "Account ID to sync",
|
|
189
|
+
required: true,
|
|
190
|
+
},
|
|
191
|
+
output: { type: "string", description: "Format: json", default: "json" },
|
|
192
|
+
},
|
|
193
|
+
async run({ args }) {
|
|
194
|
+
await apiPost("/api/ads/google/library/sync", {
|
|
195
|
+
accountId: args.accountId,
|
|
196
|
+
});
|
|
197
|
+
process.stderr.write("Sync started. Polling...\n");
|
|
198
|
+
const deadline = Date.now() + 600_000;
|
|
199
|
+
while (Date.now() < deadline) {
|
|
200
|
+
await sleep(5_000);
|
|
201
|
+
const status = await apiGet("/api/ads/google/library/account-status", {
|
|
202
|
+
accountId: args.accountId,
|
|
203
|
+
});
|
|
204
|
+
if (!status.syncStatus) {
|
|
205
|
+
process.stderr.write(`Sync complete. ${status.totalAdCount ?? 0} ads (${status.activeAdCount ?? 0} active)\n`);
|
|
206
|
+
if (args.output === "json") {
|
|
207
|
+
writeAdsJson({ ok: true, data: status });
|
|
208
|
+
}
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
if (status.syncStatus === "error") {
|
|
212
|
+
process.stderr.write("Sync failed.\n");
|
|
213
|
+
writeAdsJson({ ok: false, error: { code: "SYNC_ERROR", message: "Sync failed" } });
|
|
214
|
+
process.exit(1);
|
|
215
|
+
}
|
|
216
|
+
process.stderr.write(" syncing...\n");
|
|
217
|
+
}
|
|
218
|
+
process.stderr.write("Sync timed out after 10 minutes.\n");
|
|
219
|
+
writeAdsJson({ ok: false, error: { code: "TIMEOUT", message: "Sync did not complete within 10 minutes" } });
|
|
220
|
+
process.exit(1);
|
|
221
|
+
},
|
|
222
|
+
});
|
|
223
|
+
const searchCompetitors = defineCommand({
|
|
224
|
+
meta: {
|
|
225
|
+
name: "search-competitors",
|
|
226
|
+
description: "Search for competitors running Google ads for a keyword (DataForSEO)",
|
|
227
|
+
},
|
|
228
|
+
args: {
|
|
229
|
+
keyword: {
|
|
230
|
+
type: "positional",
|
|
231
|
+
description: "Keyword to search for",
|
|
232
|
+
required: true,
|
|
233
|
+
},
|
|
234
|
+
location: {
|
|
235
|
+
type: "string",
|
|
236
|
+
description: "Location (name or code)",
|
|
237
|
+
},
|
|
238
|
+
json: {
|
|
239
|
+
type: "boolean",
|
|
240
|
+
description: "Output in JSON format",
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
async run({ args }) {
|
|
244
|
+
const data = await apiPost("/api/research/advertisers", {
|
|
245
|
+
keyword: args.keyword,
|
|
246
|
+
location: args.location,
|
|
247
|
+
});
|
|
248
|
+
if (args.json) {
|
|
249
|
+
writeAdsJson({ ok: true, data });
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
writeAdsOutput(data, "md");
|
|
253
|
+
}
|
|
254
|
+
},
|
|
255
|
+
});
|
|
256
|
+
export const library = defineCommand({
|
|
257
|
+
meta: {
|
|
258
|
+
name: "library",
|
|
259
|
+
description: "Manage and search the Google Ads Library",
|
|
260
|
+
},
|
|
261
|
+
subCommands: {
|
|
262
|
+
"list-advertisers": listAdvertisers,
|
|
263
|
+
"sync-status": syncStatus,
|
|
264
|
+
"search-ads": searchAds,
|
|
265
|
+
"search-advertiser": searchAdvertiser,
|
|
266
|
+
"search-competitors": searchCompetitors,
|
|
267
|
+
track: track,
|
|
268
|
+
sync: sync,
|
|
269
|
+
},
|
|
270
|
+
});
|
|
271
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/commands/ads/google/library/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/research/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/research/index.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,eAAe,qDAqC1B,CAAC"}
|
|
@@ -8,12 +8,14 @@ import { keywordsForSiteCommand } from "./keywords-for-site.js";
|
|
|
8
8
|
import { languagesCommand } from "./languages.js";
|
|
9
9
|
import { lighthouseCommand } from "./lighthouse.js";
|
|
10
10
|
import { relevantPagesCommand } from "./relevant-pages.js";
|
|
11
|
+
import { webCommand } from "./web.js";
|
|
11
12
|
export const researchCommand = defineCommand({
|
|
12
13
|
meta: {
|
|
13
14
|
name: "research",
|
|
14
|
-
description: `Competitive intelligence
|
|
15
|
+
description: `Competitive intelligence and AI-powered research commands.
|
|
15
16
|
|
|
16
17
|
Commands:
|
|
18
|
+
web — Search the web with AI (ask any question)
|
|
17
19
|
advertisers — Who's bidding on a keyword?
|
|
18
20
|
autocomplete — Google Autocomplete suggestions
|
|
19
21
|
intent — Google Search intent classification
|
|
@@ -25,15 +27,15 @@ Commands:
|
|
|
25
27
|
languages — List supported language codes
|
|
26
28
|
|
|
27
29
|
Examples:
|
|
30
|
+
baker research web "Who are the main competitors of HubSpot?"
|
|
31
|
+
baker research web "What is the ICP for CRM buyers?" --depth high
|
|
28
32
|
baker research advertisers "running shoes"
|
|
29
|
-
baker research autocomplete "running shoes"
|
|
30
33
|
baker research intent "buy running shoes,best running shoes 2026"
|
|
31
34
|
baker research keywords-for-site "competitor.com"
|
|
32
|
-
baker research keyword-gap "them.com" "us.com"
|
|
33
|
-
baker research relevant-pages "competitor.com"
|
|
34
|
-
baker research lighthouse "https://example.com/landing"`,
|
|
35
|
+
baker research keyword-gap "them.com" "us.com"`,
|
|
35
36
|
},
|
|
36
37
|
subCommands: {
|
|
38
|
+
web: webCommand,
|
|
37
39
|
advertisers: advertisersCommand,
|
|
38
40
|
autocomplete: autocompleteCommand,
|
|
39
41
|
countries: countriesCommand,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/research/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/research/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,MAAM,CAAC,MAAM,eAAe,GAAG,aAAa,CAAC;IAC3C,IAAI,EAAE;QACJ,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;iDAoBgC;KAC9C;IACD,WAAW,EAAE;QACX,GAAG,EAAE,UAAU;QACf,WAAW,EAAE,kBAAkB;QAC/B,YAAY,EAAE,mBAAmB;QACjC,SAAS,EAAE,gBAAgB;QAC3B,MAAM,EAAE,aAAa;QACrB,mBAAmB,EAAE,sBAAsB;QAC3C,aAAa,EAAE,iBAAiB;QAChC,SAAS,EAAE,gBAAgB;QAC3B,UAAU,EAAE,iBAAiB;QAC7B,gBAAgB,EAAE,oBAAoB;KACvC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare const webCommand: import("citty").CommandDef<{
|
|
2
|
+
readonly question: {
|
|
3
|
+
readonly type: "positional";
|
|
4
|
+
readonly description: "The research question";
|
|
5
|
+
readonly required: true;
|
|
6
|
+
};
|
|
7
|
+
readonly depth: {
|
|
8
|
+
readonly type: "string";
|
|
9
|
+
readonly description: "Research depth: medium|high|xhigh (default: medium)";
|
|
10
|
+
readonly required: false;
|
|
11
|
+
};
|
|
12
|
+
readonly output: {
|
|
13
|
+
readonly type: "string";
|
|
14
|
+
readonly description: "Format: json|md (default: json)";
|
|
15
|
+
readonly required: false;
|
|
16
|
+
readonly default: "json";
|
|
17
|
+
};
|
|
18
|
+
}>;
|
|
19
|
+
//# sourceMappingURL=web.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../../src/commands/research/web.ts"],"names":[],"mappings":"AAsEA,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;EA6DrB,CAAC"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { defineCommand } from "citty";
|
|
2
|
+
import { apiGet, apiPost } from "../../client.js";
|
|
3
|
+
import { registerSchema } from "../../schemas.js";
|
|
4
|
+
import { handleResearchError, writeResearchJson } from "./output.js";
|
|
5
|
+
registerSchema({
|
|
6
|
+
command: "research.web",
|
|
7
|
+
description: "Search the web with AI to answer marketing questions — competitors, ICP, pricing, pain points, market trends. Three depth levels: medium (quick, default), high (thorough), xhigh (exhaustive deep research).",
|
|
8
|
+
args: {
|
|
9
|
+
question: {
|
|
10
|
+
type: "string",
|
|
11
|
+
description: "The research question to answer using live web data",
|
|
12
|
+
required: true,
|
|
13
|
+
},
|
|
14
|
+
depth: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "Research depth: medium (quick), high (thorough), xhigh (exhaustive). Default: medium",
|
|
17
|
+
required: false,
|
|
18
|
+
enum: ["medium", "high", "xhigh"],
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
const TIMEOUT_MS = {
|
|
23
|
+
medium: 180_000,
|
|
24
|
+
high: 360_000,
|
|
25
|
+
xhigh: 900_000,
|
|
26
|
+
};
|
|
27
|
+
const FIELDS = {
|
|
28
|
+
answer: "AI-generated research answer (markdown)",
|
|
29
|
+
sources: "Array of {title, url} sources used for grounding",
|
|
30
|
+
};
|
|
31
|
+
function sleep(ms) {
|
|
32
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
33
|
+
}
|
|
34
|
+
async function runDeepResearch(question) {
|
|
35
|
+
const { interactionId } = await apiPost("/api/research/deep-research/start", { question });
|
|
36
|
+
process.stderr.write(`Deep research started (${interactionId}). Polling...\n`);
|
|
37
|
+
const deadline = Date.now() + TIMEOUT_MS.xhigh;
|
|
38
|
+
while (Date.now() < deadline) {
|
|
39
|
+
await sleep(10_000);
|
|
40
|
+
const poll = await apiGet("/api/research/deep-research/poll", {
|
|
41
|
+
id: interactionId,
|
|
42
|
+
});
|
|
43
|
+
if (poll.status === "completed" && poll.result) {
|
|
44
|
+
return poll.result;
|
|
45
|
+
}
|
|
46
|
+
if (poll.status === "failed" || poll.status === "cancelled") {
|
|
47
|
+
throw new Error(`Deep research ${poll.status}`);
|
|
48
|
+
}
|
|
49
|
+
process.stderr.write(` status: ${poll.status}\n`);
|
|
50
|
+
}
|
|
51
|
+
throw new Error("Deep research timed out");
|
|
52
|
+
}
|
|
53
|
+
export const webCommand = defineCommand({
|
|
54
|
+
meta: {
|
|
55
|
+
name: "web",
|
|
56
|
+
description: `Search the web with AI to answer any open-ended marketing question. Uses live internet data via Google Search.
|
|
57
|
+
|
|
58
|
+
Depth levels:
|
|
59
|
+
medium — Quick lookup using Gemini Flash with minimal thinking (default)
|
|
60
|
+
high — Thorough answer using Gemini Flash with deep thinking
|
|
61
|
+
xhigh — Exhaustive deep research using Gemini Deep Research (slow, use sparingly)
|
|
62
|
+
|
|
63
|
+
Examples:
|
|
64
|
+
baker research web "Who are the main competitors of HubSpot CRM?"
|
|
65
|
+
baker research web "What are the top pain points for SMB CRM buyers?" --depth high
|
|
66
|
+
baker research web "Full competitive analysis of project management SaaS" --depth xhigh`,
|
|
67
|
+
},
|
|
68
|
+
args: {
|
|
69
|
+
question: { type: "positional", description: "The research question", required: true },
|
|
70
|
+
depth: { type: "string", description: "Research depth: medium|high|xhigh (default: medium)", required: false },
|
|
71
|
+
output: { type: "string", description: "Format: json|md (default: json)", required: false, default: "json" },
|
|
72
|
+
},
|
|
73
|
+
run: async ({ args }) => {
|
|
74
|
+
const question = args.question;
|
|
75
|
+
if (question.length < 5) {
|
|
76
|
+
writeResearchJson({
|
|
77
|
+
ok: false,
|
|
78
|
+
error: { code: "VALIDATION_ERROR", message: "Question must be at least 5 characters" },
|
|
79
|
+
});
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
const depth = (args.depth || "medium");
|
|
83
|
+
if (!["medium", "high", "xhigh"].includes(depth)) {
|
|
84
|
+
writeResearchJson({
|
|
85
|
+
ok: false,
|
|
86
|
+
error: { code: "VALIDATION_ERROR", message: "Depth must be one of: medium, high, xhigh" },
|
|
87
|
+
});
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
const data = depth === "xhigh"
|
|
92
|
+
? await runDeepResearch(question)
|
|
93
|
+
: await apiPost("/api/research/explore", { question, depth }, { timeoutMs: TIMEOUT_MS[depth] });
|
|
94
|
+
const format = args.output || "json";
|
|
95
|
+
if (format === "md") {
|
|
96
|
+
process.stdout.write(`${data.answer}\n`);
|
|
97
|
+
if (data.sources.length > 0) {
|
|
98
|
+
process.stdout.write("\n## Sources\n");
|
|
99
|
+
for (const s of data.sources) {
|
|
100
|
+
process.stdout.write(`- [${s.title}](${s.url})\n`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
writeResearchJson({ ok: true, data, fields: FIELDS });
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
handleResearchError(err);
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
//# sourceMappingURL=web.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../../src/commands/research/web.ts"],"names":[],"mappings":"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"}
|