@koda-sl/baker-cli 0.137.0 → 0.138.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 +7 -1
- package/dist/cli.js +96 -21
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -168,9 +168,12 @@ Run arbitrary GAQL queries. The most powerful command.
|
|
|
168
168
|
# Raw GAQL
|
|
169
169
|
baker ads google query "SELECT campaign.name, metrics.clicks, metrics.cost_micros FROM campaign WHERE segments.date DURING LAST_7_DAYS AND campaign.status = 'ENABLED' ORDER BY metrics.cost_micros DESC" --customer-id 1234567890
|
|
170
170
|
|
|
171
|
-
# Use a preset (saves tokens)
|
|
171
|
+
# Use a preset (saves tokens) — returns only actually-serving entities by default
|
|
172
172
|
baker ads google query --preset campaign-performance --customer-id 1234567890
|
|
173
173
|
|
|
174
|
+
# Include paused entities too (default is serving-only)
|
|
175
|
+
baker ads google query --preset ad-copy-performance --customer-id 1234567890 --include-paused
|
|
176
|
+
|
|
174
177
|
# Export to CSV
|
|
175
178
|
baker ads google query --preset search-terms --customer-id 1234567890 --out results.csv
|
|
176
179
|
|
|
@@ -226,6 +229,7 @@ baker ads google query --list-presets
|
|
|
226
229
|
| `--customer-id` | Google Ads customer ID (10 digits, no dashes). Falls back to `BAKER_GOOGLE_ADS_CUSTOMER_ID` env var. |
|
|
227
230
|
| `--preset` | Named query template (see presets below) |
|
|
228
231
|
| `--date-range` | Override preset date range (LAST_7_DAYS, LAST_30_DAYS, etc.) |
|
|
232
|
+
| `--include-paused` | Include paused entities in preset results. Off by default: presets return only actually-serving entities (enabled campaign **and** ad group **and** ad). Google Ads has no single serving flag, so the whole chain must be `ENABLED` for an entity to serve. |
|
|
229
233
|
| `--limit` | Max rows per page (default 200) |
|
|
230
234
|
| `--cursor` | Pagination cursor from previous response |
|
|
231
235
|
| `--all` | Auto-paginate all results |
|
|
@@ -251,6 +255,8 @@ baker ads google query --list-presets
|
|
|
251
255
|
| `shopping-products` | Product-level shopping metrics | LAST_30_DAYS |
|
|
252
256
|
| `account-summary` | Account-level totals | LAST_30_DAYS |
|
|
253
257
|
|
|
258
|
+
Every preset except the negatives lists and `account-summary` filters to **actually-serving entities** by default — the full status chain (`campaign.status = 'ENABLED' AND ad_group.status = 'ENABLED' AND ad_group_ad.status = 'ENABLED'`, as applicable) — and selects the status columns so you can see them. Pass `--include-paused` to widen to `!= 'REMOVED'` (keeps paused, still drops removed). Raw GAQL (no `--preset`) has no such default: a query over a serving-hierarchy resource without a status filter emits a `SERVING_SCOPE` warning reminding you to add the chain, because Google Ads has no single serving flag.
|
|
259
|
+
|
|
254
260
|
**Pre-flight checks and auto-fixes:**
|
|
255
261
|
|
|
256
262
|
The CLI rejects or automatically corrects common GAQL mistakes before hitting the API:
|
package/dist/cli.js
CHANGED
|
@@ -3814,6 +3814,7 @@ var FIELD_DESCRIPTIONS = {
|
|
|
3814
3814
|
// Keywords
|
|
3815
3815
|
"ad_group_criterion.keyword.text": "The keyword text",
|
|
3816
3816
|
"ad_group_criterion.keyword.match_type": "EXACT, PHRASE, or BROAD",
|
|
3817
|
+
"ad_group_criterion.status": "ENABLED, PAUSED, or REMOVED",
|
|
3817
3818
|
"ad_group_criterion.quality_info.quality_score": "Quality score 1-10 (higher is better)",
|
|
3818
3819
|
// Search terms
|
|
3819
3820
|
"search_term_view.search_term": "Actual user search query that triggered the ad",
|
|
@@ -3850,6 +3851,7 @@ var FIELD_DESCRIPTIONS = {
|
|
|
3850
3851
|
"asset.youtube_video_asset.youtube_video_id": "YouTube video ID",
|
|
3851
3852
|
"asset.youtube_video_asset.youtube_video_title": "YouTube video title",
|
|
3852
3853
|
"asset_group.name": "Asset group display name",
|
|
3854
|
+
"asset_group.status": "ENABLED, PAUSED, or REMOVED",
|
|
3853
3855
|
"asset_group_asset.field_type": "Where the asset is used (HEADLINE, DESCRIPTION, LOGO, etc.)",
|
|
3854
3856
|
"asset_group_asset.performance_label": "Performance rating: BEST, GOOD, LOW, LEARNING",
|
|
3855
3857
|
// Change events
|
|
@@ -6267,10 +6269,10 @@ function applyAutoFixes(query, limit) {
|
|
|
6267
6269
|
warnings.push({ code: "FIELD_RENAMED", message: "asset.<type>_asset.final_urls \u2192 asset.final_urls" });
|
|
6268
6270
|
}
|
|
6269
6271
|
if (/FROM\s+campaign_budget\b/i.test(corrected)) {
|
|
6270
|
-
const
|
|
6272
|
+
const whereClause2 = corrected.split(/\bWHERE\b/i)[1] ?? "";
|
|
6271
6273
|
const selectClause = corrected.split(/\bFROM\b/i)[0] ?? "";
|
|
6272
6274
|
const selectFields = new Set(selectClause.match(/campaign\.[\w.]+/g) ?? []);
|
|
6273
|
-
const missing = [...new Set(
|
|
6275
|
+
const missing = [...new Set(whereClause2.match(/campaign\.[\w.]+/g) ?? [])].filter(
|
|
6274
6276
|
(field) => !selectFields.has(field)
|
|
6275
6277
|
);
|
|
6276
6278
|
if (missing.length > 0) {
|
|
@@ -6405,23 +6407,26 @@ var PRESETS = [
|
|
|
6405
6407
|
{
|
|
6406
6408
|
name: "campaign-performance",
|
|
6407
6409
|
description: "Campaign-level metrics overview",
|
|
6408
|
-
gaqlTemplate: `SELECT campaign.id, campaign.name, campaign.status, campaign.advertising_channel_type, metrics.impressions, metrics.clicks, metrics.cost_micros, metrics.conversions, metrics.conversions_value, metrics.ctr, metrics.average_cpc FROM campaign WHERE segments.date DURING {dateRange}
|
|
6410
|
+
gaqlTemplate: `SELECT campaign.id, campaign.name, campaign.status, campaign.advertising_channel_type, metrics.impressions, metrics.clicks, metrics.cost_micros, metrics.conversions, metrics.conversions_value, metrics.ctr, metrics.average_cpc FROM campaign WHERE segments.date DURING {dateRange}{statusScope} ORDER BY metrics.cost_micros DESC LIMIT {limit}`,
|
|
6409
6411
|
defaultDateRange: "LAST_30_DAYS",
|
|
6410
|
-
defaultLimit: 200
|
|
6412
|
+
defaultLimit: 200,
|
|
6413
|
+
statusFields: ["campaign.status"]
|
|
6411
6414
|
},
|
|
6412
6415
|
{
|
|
6413
6416
|
name: "keyword-analysis",
|
|
6414
6417
|
description: "Keyword performance with match type and quality",
|
|
6415
|
-
gaqlTemplate: `SELECT campaign.id, campaign.name, ad_group.name, ad_group_criterion.keyword.text, ad_group_criterion.keyword.match_type, metrics.impressions, metrics.clicks, metrics.cost_micros, metrics.conversions, metrics.ctr FROM keyword_view WHERE segments.date DURING {dateRange}
|
|
6418
|
+
gaqlTemplate: `SELECT campaign.id, campaign.name, campaign.status, ad_group.name, ad_group.status, ad_group_criterion.keyword.text, ad_group_criterion.keyword.match_type, ad_group_criterion.status, metrics.impressions, metrics.clicks, metrics.cost_micros, metrics.conversions, metrics.ctr FROM keyword_view WHERE segments.date DURING {dateRange}{statusScope} ORDER BY metrics.impressions DESC LIMIT {limit}`,
|
|
6416
6419
|
defaultDateRange: "LAST_30_DAYS",
|
|
6417
|
-
defaultLimit: 200
|
|
6420
|
+
defaultLimit: 200,
|
|
6421
|
+
statusFields: ["campaign.status", "ad_group.status", "ad_group_criterion.status"]
|
|
6418
6422
|
},
|
|
6419
6423
|
{
|
|
6420
6424
|
name: "positive-keywords",
|
|
6421
6425
|
description: "Positive (targeting) keywords only \u2014 excludes negatives",
|
|
6422
|
-
gaqlTemplate: `SELECT campaign.id, campaign.name, ad_group.name, ad_group_criterion.keyword.text, ad_group_criterion.keyword.match_type, ad_group_criterion.status, ad_group_criterion.negative FROM ad_group_criterion WHERE ad_group_criterion.type = 'KEYWORD' AND ad_group_criterion.negative = FALSE
|
|
6426
|
+
gaqlTemplate: `SELECT campaign.id, campaign.name, campaign.status, ad_group.name, ad_group.status, ad_group_criterion.keyword.text, ad_group_criterion.keyword.match_type, ad_group_criterion.status, ad_group_criterion.negative FROM ad_group_criterion WHERE ad_group_criterion.type = 'KEYWORD' AND ad_group_criterion.negative = FALSE{statusScope} ORDER BY campaign.name LIMIT {limit}`,
|
|
6423
6427
|
defaultDateRange: "ALL_TIME",
|
|
6424
|
-
defaultLimit: 500
|
|
6428
|
+
defaultLimit: 500,
|
|
6429
|
+
statusFields: ["campaign.status", "ad_group.status", "ad_group_criterion.status"]
|
|
6425
6430
|
},
|
|
6426
6431
|
{
|
|
6427
6432
|
name: "negative-keywords",
|
|
@@ -6447,30 +6452,34 @@ var PRESETS = [
|
|
|
6447
6452
|
{
|
|
6448
6453
|
name: "search-terms",
|
|
6449
6454
|
description: "Actual user search queries triggering ads",
|
|
6450
|
-
gaqlTemplate: `SELECT campaign.id, campaign.name, ad_group.name, search_term_view.search_term, metrics.impressions, metrics.clicks, metrics.cost_micros, metrics.conversions FROM search_term_view WHERE segments.date DURING {dateRange}
|
|
6455
|
+
gaqlTemplate: `SELECT campaign.id, campaign.name, campaign.status, ad_group.name, ad_group.status, search_term_view.search_term, metrics.impressions, metrics.clicks, metrics.cost_micros, metrics.conversions FROM search_term_view WHERE segments.date DURING {dateRange}{statusScope} ORDER BY metrics.impressions DESC LIMIT {limit}`,
|
|
6451
6456
|
defaultDateRange: "LAST_7_DAYS",
|
|
6452
|
-
defaultLimit: 200
|
|
6457
|
+
defaultLimit: 200,
|
|
6458
|
+
statusFields: ["campaign.status", "ad_group.status"]
|
|
6453
6459
|
},
|
|
6454
6460
|
{
|
|
6455
6461
|
name: "ad-copy-performance",
|
|
6456
6462
|
description: "Ad headline and description effectiveness",
|
|
6457
|
-
gaqlTemplate: `SELECT campaign.id, campaign.name, ad_group_ad.ad.responsive_search_ad.headlines, ad_group_ad.ad.responsive_search_ad.descriptions, ad_group_ad.ad.final_urls, metrics.impressions, metrics.clicks, metrics.conversions, metrics.ctr FROM ad_group_ad WHERE segments.date DURING {dateRange}
|
|
6463
|
+
gaqlTemplate: `SELECT campaign.id, campaign.name, campaign.status, ad_group.status, ad_group_ad.status, ad_group_ad.ad.responsive_search_ad.headlines, ad_group_ad.ad.responsive_search_ad.descriptions, ad_group_ad.ad.final_urls, metrics.impressions, metrics.clicks, metrics.conversions, metrics.ctr FROM ad_group_ad WHERE segments.date DURING {dateRange}{statusScope} ORDER BY metrics.impressions DESC LIMIT {limit}`,
|
|
6458
6464
|
defaultDateRange: "LAST_30_DAYS",
|
|
6459
|
-
defaultLimit: 200
|
|
6465
|
+
defaultLimit: 200,
|
|
6466
|
+
statusFields: ["campaign.status", "ad_group.status", "ad_group_ad.status"]
|
|
6460
6467
|
},
|
|
6461
6468
|
{
|
|
6462
6469
|
name: "asset-performance",
|
|
6463
6470
|
description: "Performance Max asset performance labels",
|
|
6464
|
-
gaqlTemplate: `SELECT campaign.id, campaign.name, asset_group.name, asset_group_asset.field_type, asset_group_asset.performance_label, asset.type, asset.text_asset.text, asset.image_asset.full_size.url FROM asset_group_asset WHERE campaign.advertising_channel_type = 'PERFORMANCE_MAX' AND segments.date DURING {dateRange} LIMIT {limit}`,
|
|
6471
|
+
gaqlTemplate: `SELECT campaign.id, campaign.name, campaign.status, asset_group.name, asset_group.status, asset_group_asset.field_type, asset_group_asset.performance_label, asset.type, asset.text_asset.text, asset.image_asset.full_size.url FROM asset_group_asset WHERE campaign.advertising_channel_type = 'PERFORMANCE_MAX' AND segments.date DURING {dateRange}{statusScope} LIMIT {limit}`,
|
|
6465
6472
|
defaultDateRange: "LAST_30_DAYS",
|
|
6466
|
-
defaultLimit: 200
|
|
6473
|
+
defaultLimit: 200,
|
|
6474
|
+
statusFields: ["campaign.status", "asset_group.status"]
|
|
6467
6475
|
},
|
|
6468
6476
|
{
|
|
6469
6477
|
name: "shopping-products",
|
|
6470
6478
|
description: "Product-level shopping performance metrics",
|
|
6471
|
-
gaqlTemplate: `SELECT campaign.id, campaign.name, segments.product_title, segments.product_item_id, segments.product_brand, segments.product_type_l1, metrics.clicks, metrics.impressions, metrics.cost_micros, metrics.conversions FROM shopping_performance_view WHERE segments.date DURING {dateRange} ORDER BY metrics.cost_micros DESC LIMIT {limit}`,
|
|
6479
|
+
gaqlTemplate: `SELECT campaign.id, campaign.name, campaign.status, segments.product_title, segments.product_item_id, segments.product_brand, segments.product_type_l1, metrics.clicks, metrics.impressions, metrics.cost_micros, metrics.conversions FROM shopping_performance_view WHERE segments.date DURING {dateRange}{statusScope} ORDER BY metrics.cost_micros DESC LIMIT {limit}`,
|
|
6472
6480
|
defaultDateRange: "LAST_30_DAYS",
|
|
6473
|
-
defaultLimit: 200
|
|
6481
|
+
defaultLimit: 200,
|
|
6482
|
+
statusFields: ["campaign.status"]
|
|
6474
6483
|
},
|
|
6475
6484
|
{
|
|
6476
6485
|
name: "account-summary",
|
|
@@ -6483,6 +6492,11 @@ var PRESETS = [
|
|
|
6483
6492
|
function getPreset(name) {
|
|
6484
6493
|
return PRESETS.find((p) => p.name === name);
|
|
6485
6494
|
}
|
|
6495
|
+
function buildStatusScope(statusFields, includePaused) {
|
|
6496
|
+
if (!statusFields || statusFields.length === 0) return "";
|
|
6497
|
+
const predicate = includePaused ? "!= 'REMOVED'" : "= 'ENABLED'";
|
|
6498
|
+
return statusFields.map((field) => ` AND ${field} ${predicate}`).join("");
|
|
6499
|
+
}
|
|
6486
6500
|
function expandPreset(preset, params) {
|
|
6487
6501
|
const dateRange = params.dateRange ?? preset.defaultDateRange;
|
|
6488
6502
|
const limit = params.limit ?? preset.defaultLimit;
|
|
@@ -6492,7 +6506,8 @@ function expandPreset(preset, params) {
|
|
|
6492
6506
|
dateRangeError: `Invalid date range: "${dateRange}". Use a GAQL date literal (e.g. LAST_30_DAYS, TODAY) or BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD'.`
|
|
6493
6507
|
};
|
|
6494
6508
|
}
|
|
6495
|
-
const
|
|
6509
|
+
const statusScope = buildStatusScope(preset.statusFields, params.includePaused ?? false);
|
|
6510
|
+
const query = preset.gaqlTemplate.replace(/\{dateRange\}/g, dateRange).replace(/\{limit\}/g, String(limit)).replace(/\{statusScope\}/g, statusScope);
|
|
6496
6511
|
return { query };
|
|
6497
6512
|
}
|
|
6498
6513
|
|
|
@@ -6509,7 +6524,7 @@ registerSchema({
|
|
|
6509
6524
|
},
|
|
6510
6525
|
preset: {
|
|
6511
6526
|
type: "string",
|
|
6512
|
-
description: "Named query preset (campaign-performance, keyword-analysis, search-terms, ad-copy-performance, asset-performance, shopping-products, account-summary)",
|
|
6527
|
+
description: "Named query preset. Reads (campaign-performance, keyword-analysis, positive-keywords, negative-keywords, negative-keyword-lists, negative-list-attachments, search-terms, ad-copy-performance, asset-performance, shopping-products, account-summary). Presets return only actually-serving entities (enabled campaign AND ad group AND ad) by default \u2014 pass --include-paused to include paused ones.",
|
|
6513
6528
|
required: false
|
|
6514
6529
|
},
|
|
6515
6530
|
"date-range": {
|
|
@@ -6517,6 +6532,11 @@ registerSchema({
|
|
|
6517
6532
|
description: "Date range for presets (LAST_7_DAYS, LAST_30_DAYS, LAST_90_DAYS, or BETWEEN 'X' AND 'Y')",
|
|
6518
6533
|
required: false
|
|
6519
6534
|
},
|
|
6535
|
+
"include-paused": {
|
|
6536
|
+
type: "boolean",
|
|
6537
|
+
description: "Include paused entities in preset results. Off by default: presets return only actually-serving entities. Google Ads has no single serving flag \u2014 an entity serves only when its whole chain (campaign, ad group, ad) is ENABLED, so recommendations should target serving entities unless the user asks about paused ones.",
|
|
6538
|
+
required: false
|
|
6539
|
+
},
|
|
6520
6540
|
limit: { type: "number", description: "Max rows (default 200)", required: false, default: 200 },
|
|
6521
6541
|
"list-presets": { type: "boolean", description: "List all available query presets", required: false },
|
|
6522
6542
|
cursor: { type: "string", description: "Pagination cursor from previous response", required: false },
|
|
@@ -6625,7 +6645,11 @@ function resolveGaql(args, limit) {
|
|
|
6625
6645
|
});
|
|
6626
6646
|
return null;
|
|
6627
6647
|
}
|
|
6628
|
-
const expanded = expandPreset(preset, {
|
|
6648
|
+
const expanded = expandPreset(preset, {
|
|
6649
|
+
dateRange: args["date-range"],
|
|
6650
|
+
limit,
|
|
6651
|
+
includePaused: Boolean(args["include-paused"])
|
|
6652
|
+
});
|
|
6629
6653
|
if (expanded.dateRangeError) {
|
|
6630
6654
|
writeAdsJson({
|
|
6631
6655
|
ok: false,
|
|
@@ -6648,6 +6672,51 @@ function resolveGaql(args, limit) {
|
|
|
6648
6672
|
}
|
|
6649
6673
|
return gaql;
|
|
6650
6674
|
}
|
|
6675
|
+
var SERVING_HIERARCHY_RESOURCES = [
|
|
6676
|
+
"campaign",
|
|
6677
|
+
"ad_group",
|
|
6678
|
+
"ad_group_ad",
|
|
6679
|
+
"ad_group_criterion",
|
|
6680
|
+
"keyword_view",
|
|
6681
|
+
"search_term_view",
|
|
6682
|
+
"shopping_performance_view",
|
|
6683
|
+
"asset_group_asset"
|
|
6684
|
+
];
|
|
6685
|
+
function whereClause(upperQuery) {
|
|
6686
|
+
const whereIdx = upperQuery.indexOf(" WHERE ");
|
|
6687
|
+
if (whereIdx === -1) return "";
|
|
6688
|
+
let rest = upperQuery.slice(whereIdx + 7);
|
|
6689
|
+
for (const trailing of [" ORDER BY ", " GROUP BY ", " LIMIT ", " PARAMETERS "]) {
|
|
6690
|
+
const idx = rest.indexOf(trailing);
|
|
6691
|
+
if (idx !== -1) rest = rest.slice(0, idx);
|
|
6692
|
+
}
|
|
6693
|
+
return rest;
|
|
6694
|
+
}
|
|
6695
|
+
function servingScopeWarnings(args, finalQuery) {
|
|
6696
|
+
if (args.preset) {
|
|
6697
|
+
if (!args["include-paused"]) return [];
|
|
6698
|
+
return [
|
|
6699
|
+
{
|
|
6700
|
+
code: "SERVING_SCOPE",
|
|
6701
|
+
message: "Paused entities are included (--include-paused). Only recommend changes for actually-serving entities (enabled campaign, ad group, and ad) unless the user asked about paused ones."
|
|
6702
|
+
}
|
|
6703
|
+
];
|
|
6704
|
+
}
|
|
6705
|
+
const upper2 = finalQuery.toUpperCase();
|
|
6706
|
+
const fromMatch = upper2.match(/\bFROM\s+([A-Z_]+)/);
|
|
6707
|
+
const resource = fromMatch?.[1]?.toLowerCase();
|
|
6708
|
+
const hierarchical = resource ? SERVING_HIERARCHY_RESOURCES.includes(resource) : false;
|
|
6709
|
+
const filtersStatus = whereClause(upper2).includes(".STATUS");
|
|
6710
|
+
if (hierarchical && !filtersStatus) {
|
|
6711
|
+
return [
|
|
6712
|
+
{
|
|
6713
|
+
code: "SERVING_SCOPE",
|
|
6714
|
+
message: "This query has no status filter, so it may return paused entities that aren't actually serving. Google Ads has no single serving flag \u2014 an entity serves only when its whole chain is ENABLED. Add campaign.status = 'ENABLED' AND ad_group.status = 'ENABLED' AND ad_group_ad.status = 'ENABLED' (as applicable), or use a --preset, unless you intend to include paused entities."
|
|
6715
|
+
}
|
|
6716
|
+
];
|
|
6717
|
+
}
|
|
6718
|
+
return [];
|
|
6719
|
+
}
|
|
6651
6720
|
async function fetchAllPages(body, args) {
|
|
6652
6721
|
let allRows = [];
|
|
6653
6722
|
let pageToken = args.cursor;
|
|
@@ -6706,7 +6775,7 @@ async function validateArgs(args) {
|
|
|
6706
6775
|
customerId,
|
|
6707
6776
|
limit,
|
|
6708
6777
|
finalQuery,
|
|
6709
|
-
warnings: preflight.warnings,
|
|
6778
|
+
warnings: [...preflight.warnings, ...servingScopeWarnings(args, finalQuery)],
|
|
6710
6779
|
useCache: !args["no-cache"],
|
|
6711
6780
|
cacheKey: buildQueryCacheKey(customerId, finalQuery)
|
|
6712
6781
|
};
|
|
@@ -6746,6 +6815,11 @@ Examples:
|
|
|
6746
6815
|
"customer-id": { type: "string", description: "Google Ads customer ID (10 digits, no dashes)", required: false },
|
|
6747
6816
|
preset: { type: "string", description: "Named query preset", required: false },
|
|
6748
6817
|
"date-range": { type: "string", description: "Date range override for presets", required: false },
|
|
6818
|
+
"include-paused": {
|
|
6819
|
+
type: "boolean",
|
|
6820
|
+
description: "Include paused entities in preset results (default: serving entities only)",
|
|
6821
|
+
required: false
|
|
6822
|
+
},
|
|
6749
6823
|
limit: { type: "string", description: "Max rows (default 200)", required: false },
|
|
6750
6824
|
"list-presets": { type: "boolean", description: "List available presets", required: false },
|
|
6751
6825
|
cursor: { type: "string", description: "Pagination cursor", required: false },
|
|
@@ -6763,7 +6837,8 @@ Examples:
|
|
|
6763
6837
|
name: p.name,
|
|
6764
6838
|
description: p.description,
|
|
6765
6839
|
defaultDateRange: p.defaultDateRange,
|
|
6766
|
-
|
|
6840
|
+
servingOnly: (p.statusFields?.length ?? 0) > 0,
|
|
6841
|
+
gaql: expandPreset(p, {}).query
|
|
6767
6842
|
}))
|
|
6768
6843
|
});
|
|
6769
6844
|
return;
|