@koda-sl/baker-cli 0.236.0 → 0.238.0-dev.7fb8e0c69
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 +2 -0
- package/dist/{chunk-EKLAHWSF.js → chunk-CMPAHYLB.js} +4 -4
- package/dist/chunk-CMPAHYLB.js.map +1 -0
- package/dist/cli.js +134 -9
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-EKLAHWSF.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -58,7 +58,7 @@ import {
|
|
|
58
58
|
ulid,
|
|
59
59
|
validateCanvasDeep,
|
|
60
60
|
ytDlpBlockSignal
|
|
61
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-CMPAHYLB.js";
|
|
62
62
|
import {
|
|
63
63
|
csvOrJson,
|
|
64
64
|
daysAgoIso,
|
|
@@ -4461,6 +4461,24 @@ var FLOW_SIDE_EFFECT_CATALOG = [
|
|
|
4461
4461
|
gotcha: "`eventTagId` comes from X Events Manager and is passed verbatim. `eventName` is an optional label only.",
|
|
4462
4462
|
reference: TAGS_REF
|
|
4463
4463
|
},
|
|
4464
|
+
{
|
|
4465
|
+
kind: "side-effect",
|
|
4466
|
+
type: "microsoftAds",
|
|
4467
|
+
summary: "Fires a Microsoft Ads (UET) conversion event.",
|
|
4468
|
+
skeleton: {
|
|
4469
|
+
...SIDE_EFFECT_ENVELOPE,
|
|
4470
|
+
type: "microsoftAds",
|
|
4471
|
+
tagIds: TAG_REF_SLOT,
|
|
4472
|
+
eventName: "<UET event action, e.g. lead_submitted>",
|
|
4473
|
+
userMatching: matchingSlots("em", "ph"),
|
|
4474
|
+
value: null,
|
|
4475
|
+
currency: null,
|
|
4476
|
+
transactionId: null
|
|
4477
|
+
},
|
|
4478
|
+
owners: { tagIds: "tags" },
|
|
4479
|
+
gotcha: "`eventName` is the UET *event action*, and it only counts as a conversion once someone creates a matching custom-event conversion goal in Microsoft Advertising \u2014 the tag alone records nothing. `page_view` is refused outright (UET reserves it for SPA navigation), so pick any other action. `eventCategory` and `eventLabel` are optional plain strings (not mapped slots) \u2014 add them only when the goal filters on them. `userMatching` needs Enhanced conversions turned on for that goal, and `ph` must carry a country code (`+34\u2026`/`0034\u2026`) \u2014 map it from a phone field with the country picker, not a plain text field, or it is dropped rather than guessed at.",
|
|
4480
|
+
reference: TAGS_REF
|
|
4481
|
+
},
|
|
4464
4482
|
eventSideEffect("posthog", "Captures a PostHog event.", { eventParams: [] }),
|
|
4465
4483
|
{
|
|
4466
4484
|
kind: "side-effect",
|
|
@@ -5902,7 +5920,8 @@ var TAG_TYPES = [
|
|
|
5902
5920
|
"posthog",
|
|
5903
5921
|
"datafast",
|
|
5904
5922
|
"recaptcha",
|
|
5905
|
-
"twitterAds"
|
|
5923
|
+
"twitterAds",
|
|
5924
|
+
"microsoftAds"
|
|
5906
5925
|
];
|
|
5907
5926
|
var tagTypeSchema = z19.enum(TAG_TYPES);
|
|
5908
5927
|
var TAG_IDENTIFYING_FIELD = {
|
|
@@ -5923,7 +5942,8 @@ var TAG_IDENTIFYING_FIELD = {
|
|
|
5923
5942
|
posthog: "projectToken",
|
|
5924
5943
|
datafast: "websiteId",
|
|
5925
5944
|
recaptcha: "siteKey",
|
|
5926
|
-
twitterAds: "pixelId"
|
|
5945
|
+
twitterAds: "pixelId",
|
|
5946
|
+
microsoftAds: "tagId"
|
|
5927
5947
|
};
|
|
5928
5948
|
var tagDraftOpKindSchema = z19.enum(["create", "update", "delete"]);
|
|
5929
5949
|
var tagDraftOpViewSchema = z19.object({
|
|
@@ -11347,6 +11367,62 @@ var AD_PARAM_ROLES = [
|
|
|
11347
11367
|
"other",
|
|
11348
11368
|
"ignore"
|
|
11349
11369
|
];
|
|
11370
|
+
var AD_PARAM_ROLE_SPECS = {
|
|
11371
|
+
campaign_id: { role: "campaign_id", label: "Campaign ID", description: "The top level of this account's structure." },
|
|
11372
|
+
campaign_name: { role: "campaign_name", label: "Campaign name", description: "The campaign's name." },
|
|
11373
|
+
adgroup_id: { role: "adgroup_id", label: "Ad group ID", description: "The targeting container inside a campaign." },
|
|
11374
|
+
adgroup_name: { role: "adgroup_name", label: "Ad group name", description: "The ad group's name." },
|
|
11375
|
+
ad_id: { role: "ad_id", label: "Ad ID", description: "The individual ad that was clicked." },
|
|
11376
|
+
ad_name: { role: "ad_name", label: "Ad name", description: "The individual ad's name." },
|
|
11377
|
+
keyword: {
|
|
11378
|
+
role: "keyword",
|
|
11379
|
+
label: "Keyword",
|
|
11380
|
+
description: "The keyword that matched, as it is written in the account \u2014 not what the visitor typed."
|
|
11381
|
+
},
|
|
11382
|
+
match_type: {
|
|
11383
|
+
role: "match_type",
|
|
11384
|
+
label: "Match type",
|
|
11385
|
+
description: "How loosely the keyword matched: broad, phrase or exact."
|
|
11386
|
+
},
|
|
11387
|
+
search_query: { role: "search_query", label: "Search query", description: "What the visitor actually typed." },
|
|
11388
|
+
audience: {
|
|
11389
|
+
role: "audience",
|
|
11390
|
+
label: "Audience",
|
|
11391
|
+
description: "The remarketing list or interest segment the visitor was in."
|
|
11392
|
+
},
|
|
11393
|
+
placement: {
|
|
11394
|
+
role: "placement",
|
|
11395
|
+
label: "Placement",
|
|
11396
|
+
description: "Where the ad appeared \u2014 a feed, a story, a site on the display network."
|
|
11397
|
+
},
|
|
11398
|
+
network: {
|
|
11399
|
+
role: "network",
|
|
11400
|
+
label: "Network",
|
|
11401
|
+
description: "Which network served it: search, a search partner, display, or a video surface."
|
|
11402
|
+
},
|
|
11403
|
+
site_source: {
|
|
11404
|
+
role: "site_source",
|
|
11405
|
+
label: "App",
|
|
11406
|
+
description: "Which app the click came from, on platforms that span several."
|
|
11407
|
+
},
|
|
11408
|
+
device: { role: "device", label: "Device", description: "Mobile, tablet or desktop, as the platform saw it." },
|
|
11409
|
+
product_id: { role: "product_id", label: "Product ID", description: "The shopping item that was clicked." },
|
|
11410
|
+
account_name: {
|
|
11411
|
+
role: "account_name",
|
|
11412
|
+
label: "Account name",
|
|
11413
|
+
description: "Which ad account paid for the click, where an agency runs several."
|
|
11414
|
+
},
|
|
11415
|
+
other: {
|
|
11416
|
+
role: "other",
|
|
11417
|
+
label: "Something else",
|
|
11418
|
+
description: "Keep the values and let me filter by this name, without saying what it means."
|
|
11419
|
+
},
|
|
11420
|
+
ignore: {
|
|
11421
|
+
role: "ignore",
|
|
11422
|
+
label: "Ignore it",
|
|
11423
|
+
description: "Not campaign information. Baker stops storing it and stops asking about it."
|
|
11424
|
+
}
|
|
11425
|
+
};
|
|
11350
11426
|
var RESERVED_PARAM_NAMES = [
|
|
11351
11427
|
"utm_source",
|
|
11352
11428
|
"utm_medium",
|
|
@@ -11365,6 +11441,9 @@ var AD_PLATFORMS = [
|
|
|
11365
11441
|
"pinterest",
|
|
11366
11442
|
"snapchat"
|
|
11367
11443
|
];
|
|
11444
|
+
function isAdPlatform(value) {
|
|
11445
|
+
return AD_PLATFORMS.includes(value);
|
|
11446
|
+
}
|
|
11368
11447
|
var GOOGLE = {
|
|
11369
11448
|
platform: "google",
|
|
11370
11449
|
label: "Google Ads",
|
|
@@ -11557,6 +11636,10 @@ var AD_PLATFORM_DEFINITIONS = {
|
|
|
11557
11636
|
pinterest: PINTEREST,
|
|
11558
11637
|
snapchat: SNAPCHAT
|
|
11559
11638
|
};
|
|
11639
|
+
var ESSENTIAL_ROLES = ["campaign_id", "adgroup_id", "ad_id", "keyword", "match_type"];
|
|
11640
|
+
function essentialAdDimensions(platform) {
|
|
11641
|
+
return AD_PLATFORM_DEFINITIONS[platform].dimensions.filter((entry) => ESSENTIAL_ROLES.includes(entry.role));
|
|
11642
|
+
}
|
|
11560
11643
|
function normalizeAdParamName(raw) {
|
|
11561
11644
|
return raw.trim().toLowerCase().slice(0, 64);
|
|
11562
11645
|
}
|
|
@@ -12361,10 +12444,19 @@ var analyticsLandingRowSchema = z24.object({
|
|
|
12361
12444
|
*
|
|
12362
12445
|
* Derived from the click ids a visit arrived with, never from `utm_source`:
|
|
12363
12446
|
* a label is whatever somebody typed into a tracking template, a `gclid` is a
|
|
12364
|
-
* click.
|
|
12365
|
-
* page as advertised.
|
|
12447
|
+
* click. Ordered by traffic, busiest first.
|
|
12366
12448
|
*/
|
|
12367
|
-
channels: z24.array(z24.string())
|
|
12449
|
+
channels: z24.array(z24.string()),
|
|
12450
|
+
/**
|
|
12451
|
+
* Visits per entry of {@link channels}, in the same order.
|
|
12452
|
+
*
|
|
12453
|
+
* The half that makes a mark readable. A mark on its own says "advertised
|
|
12454
|
+
* here", which is why it used to be withheld until three visits had arrived —
|
|
12455
|
+
* and withholding it is what made a page whose whole day was five Meta clicks
|
|
12456
|
+
* show nothing at all. The count says how much, so one test click and a live
|
|
12457
|
+
* campaign are distinguishable by reading rather than by absence.
|
|
12458
|
+
*/
|
|
12459
|
+
channelSessions: z24.array(z24.number().int().nonnegative())
|
|
12368
12460
|
});
|
|
12369
12461
|
var analyticsTagRowSchema = z24.object({
|
|
12370
12462
|
tag: z24.string(),
|
|
@@ -12923,7 +13015,14 @@ var analyticsVisitProfileSchema = z24.object({
|
|
|
12923
13015
|
utmSource: z24.string(),
|
|
12924
13016
|
utmMedium: z24.string(),
|
|
12925
13017
|
utmCampaign: z24.string(),
|
|
12926
|
-
/**
|
|
13018
|
+
/**
|
|
13019
|
+
* Which platform the click id proves, in the `AD_PLATFORMS` vocabulary —
|
|
13020
|
+
* `google` | `meta` | `tiktok` | `x` | `linkedin` | `microsoft` | `""`.
|
|
13021
|
+
*
|
|
13022
|
+
* The same spelling every mark, mapping and report uses. It briefly said
|
|
13023
|
+
* `google_ads` / `meta_ads` here alone, which meant every logo lookup on the
|
|
13024
|
+
* People screen missed and a paid visit drew a neutral globe.
|
|
13025
|
+
*/
|
|
12927
13026
|
clickPlatform: z24.string(),
|
|
12928
13027
|
/** Every ValueTrack-style parameter the URL carried, unresolved. */
|
|
12929
13028
|
campaignParams: z24.record(z24.string(), z24.string()),
|
|
@@ -23060,7 +23159,22 @@ function shapeHints(data) {
|
|
|
23060
23159
|
}
|
|
23061
23160
|
return hints;
|
|
23062
23161
|
}
|
|
23063
|
-
function
|
|
23162
|
+
function adHierarchyHints(data, platform) {
|
|
23163
|
+
if (platform === void 0) return [];
|
|
23164
|
+
const traffic = (data.adPlatformTraffic ?? []).find((entry) => entry.platform === platform);
|
|
23165
|
+
if (traffic === void 0 || traffic.sessions < MIN_SESSIONS_FOR_TAGGING_CLAIM) return [];
|
|
23166
|
+
if (traffic.taggedSessions === 0) return [];
|
|
23167
|
+
const carried = new Set(
|
|
23168
|
+
(data.adParams ?? []).filter((row) => row.role !== void 0 && row.awaitingTraffic !== true).map((row) => row.role)
|
|
23169
|
+
);
|
|
23170
|
+
const missing = essentialAdDimensions(platform).filter((entry) => !carried.has(entry.role));
|
|
23171
|
+
if (missing.length === 0) return [];
|
|
23172
|
+
const suffix = missing.map((entry) => `${entry.names[0] ?? entry.role}=${entry.macro}`).join("&");
|
|
23173
|
+
return [
|
|
23174
|
+
`${platform} traffic carries no ${missing.map((entry) => AD_PARAM_ROLE_SPECS[entry.role].label.toLowerCase()).join(", ")}, so no report can say which ad sent a visit \u2014 only which platform. Add \`${suffix}\` to that account's tracking template. This cannot be backfilled: a parameter's values are only stored once it starts arriving.`
|
|
23175
|
+
];
|
|
23176
|
+
}
|
|
23177
|
+
function buildAnalyticsHints(data, platform) {
|
|
23064
23178
|
const hints = [];
|
|
23065
23179
|
for (const funnel of data.funnels ?? []) {
|
|
23066
23180
|
const worst = funnel.worstStep;
|
|
@@ -23086,6 +23200,7 @@ function buildAnalyticsHints(data) {
|
|
|
23086
23200
|
);
|
|
23087
23201
|
}
|
|
23088
23202
|
hints.push(...shapeHints(data));
|
|
23203
|
+
hints.push(...adHierarchyHints(data, platform));
|
|
23089
23204
|
if ((data.topCampaigns ?? []).length === 0 && (data.topSources ?? []).length > 0) {
|
|
23090
23205
|
hints.push(
|
|
23091
23206
|
"No campaign tagging on any traffic \u2014 ad clicks cannot be attributed to a campaign until the destination URLs carry utm parameters."
|
|
@@ -23514,6 +23629,8 @@ function requestBody(args, options) {
|
|
|
23514
23629
|
async function runPreset(args, options) {
|
|
23515
23630
|
try {
|
|
23516
23631
|
const response = await apiPost("/api/analytics/query", requestBody(args, options));
|
|
23632
|
+
const requestedPlatform = args.platform === void 0 ? "" : String(args.platform);
|
|
23633
|
+
const adPlatformScope = isAdPlatform(requestedPlatform) ? requestedPlatform : void 0;
|
|
23517
23634
|
const format = args.output === void 0 ? "json" : String(args.output);
|
|
23518
23635
|
if (!isAnalyticsOutputFormat(format)) {
|
|
23519
23636
|
writeJsonEnvelope({
|
|
@@ -23527,7 +23644,11 @@ async function runPreset(args, options) {
|
|
|
23527
23644
|
}
|
|
23528
23645
|
const data = pruneForAgent(response.data, args.full === true);
|
|
23529
23646
|
const hints = [
|
|
23530
|
-
|
|
23647
|
+
// The platform the ad blocks were scoped to, so the tagging hint can
|
|
23648
|
+
// only speak about the inventory it was actually given. `adParams` is one
|
|
23649
|
+
// platform's list; a hint drawn from it without knowing which platform
|
|
23650
|
+
// would be a claim about Meta made from Google's URLs.
|
|
23651
|
+
...buildAnalyticsHints(response.data, adPlatformScope),
|
|
23531
23652
|
...missingBreakdownHint(response.data, {
|
|
23532
23653
|
eventName: options.eventName,
|
|
23533
23654
|
property: options.property
|
|
@@ -33719,6 +33840,10 @@ var MAPPING_SLOTS = {
|
|
|
33719
33840
|
twitterAds: [
|
|
33720
33841
|
{ kind: "record", key: "userMatching", allowed: ["em", "ph"] },
|
|
33721
33842
|
{ kind: "scalar", keys: ["value", "currency"] }
|
|
33843
|
+
],
|
|
33844
|
+
microsoftAds: [
|
|
33845
|
+
{ kind: "record", key: "userMatching", allowed: ["em", "ph"] },
|
|
33846
|
+
{ kind: "scalar", keys: ["value", "currency", "transactionId"] }
|
|
33722
33847
|
]
|
|
33723
33848
|
};
|
|
33724
33849
|
var UNMAPPABLE = {
|