@koda-sl/baker-cli 0.238.0-dev.7fb8e0c69 → 0.239.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 +4 -0
- package/dist/{chunk-CMPAHYLB.js → chunk-EKLAHWSF.js} +4 -4
- package/dist/chunk-EKLAHWSF.js.map +1 -0
- package/dist/cli.js +174 -47
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-CMPAHYLB.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-EKLAHWSF.js";
|
|
62
62
|
import {
|
|
63
63
|
csvOrJson,
|
|
64
64
|
daysAgoIso,
|
|
@@ -4461,24 +4461,6 @@ 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
|
-
},
|
|
4482
4464
|
eventSideEffect("posthog", "Captures a PostHog event.", { eventParams: [] }),
|
|
4483
4465
|
{
|
|
4484
4466
|
kind: "side-effect",
|
|
@@ -5920,8 +5902,7 @@ var TAG_TYPES = [
|
|
|
5920
5902
|
"posthog",
|
|
5921
5903
|
"datafast",
|
|
5922
5904
|
"recaptcha",
|
|
5923
|
-
"twitterAds"
|
|
5924
|
-
"microsoftAds"
|
|
5905
|
+
"twitterAds"
|
|
5925
5906
|
];
|
|
5926
5907
|
var tagTypeSchema = z19.enum(TAG_TYPES);
|
|
5927
5908
|
var TAG_IDENTIFYING_FIELD = {
|
|
@@ -5942,8 +5923,7 @@ var TAG_IDENTIFYING_FIELD = {
|
|
|
5942
5923
|
posthog: "projectToken",
|
|
5943
5924
|
datafast: "websiteId",
|
|
5944
5925
|
recaptcha: "siteKey",
|
|
5945
|
-
twitterAds: "pixelId"
|
|
5946
|
-
microsoftAds: "tagId"
|
|
5926
|
+
twitterAds: "pixelId"
|
|
5947
5927
|
};
|
|
5948
5928
|
var tagDraftOpKindSchema = z19.enum(["create", "update", "delete"]);
|
|
5949
5929
|
var tagDraftOpViewSchema = z19.object({
|
|
@@ -11922,19 +11902,22 @@ var analyticsBeaconPayloadSchema = z23.object({
|
|
|
11922
11902
|
});
|
|
11923
11903
|
|
|
11924
11904
|
// ../api/src/analytics/trackingTemplate.ts
|
|
11925
|
-
|
|
11926
|
-
|
|
11927
|
-
|
|
11928
|
-
|
|
11929
|
-
|
|
11930
|
-
|
|
11931
|
-
|
|
11932
|
-
|
|
11933
|
-
device: "device",
|
|
11934
|
-
product_id: "product_id",
|
|
11935
|
-
merchant_id: "product_id",
|
|
11936
|
-
product_partition_id: "product_id"
|
|
11905
|
+
function placeholderKey(raw) {
|
|
11906
|
+
return raw.replace(/[{}]/g, "").replace(/^_+|_+$/g, "").trim().toLowerCase();
|
|
11907
|
+
}
|
|
11908
|
+
var EXTRA_PLACEHOLDER_ROLES = {
|
|
11909
|
+
google: {
|
|
11910
|
+
merchant_id: "product_id",
|
|
11911
|
+
product_partition_id: "product_id"
|
|
11912
|
+
}
|
|
11937
11913
|
};
|
|
11914
|
+
function placeholderRoles(platform) {
|
|
11915
|
+
const roles = {};
|
|
11916
|
+
for (const dimension of AD_PLATFORM_DEFINITIONS[platform].dimensions) {
|
|
11917
|
+
roles[placeholderKey(dimension.macro)] = dimension.role;
|
|
11918
|
+
}
|
|
11919
|
+
return { ...roles, ...EXTRA_PLACEHOLDER_ROLES[platform] ?? {} };
|
|
11920
|
+
}
|
|
11938
11921
|
function paramsFromTemplate(template) {
|
|
11939
11922
|
const start = template.indexOf("?");
|
|
11940
11923
|
const query = start === -1 ? template : template.slice(start + 1);
|
|
@@ -11950,13 +11933,13 @@ function paramsFromTemplate(template) {
|
|
|
11950
11933
|
}
|
|
11951
11934
|
function proposeMappingFromTemplate(template, platform) {
|
|
11952
11935
|
const builtIn = builtinAdParamMapping(platform);
|
|
11936
|
+
const vocabulary = placeholderRoles(platform);
|
|
11953
11937
|
const proposed = {};
|
|
11954
11938
|
const unexplained = [];
|
|
11955
11939
|
for (const param of paramsFromTemplate(template)) {
|
|
11956
11940
|
if (RESERVED_PARAM_NAMES.includes(param.name)) continue;
|
|
11957
11941
|
if (param.name in builtIn) continue;
|
|
11958
|
-
const
|
|
11959
|
-
const role = VALUETRACK_ROLES[placeholder];
|
|
11942
|
+
const role = vocabulary[placeholderKey(param.value)];
|
|
11960
11943
|
if (role) {
|
|
11961
11944
|
proposed[param.name] = role;
|
|
11962
11945
|
continue;
|
|
@@ -12579,7 +12562,9 @@ var analyticsDimensionRowSchema = z24.object({
|
|
|
12579
12562
|
var analyticsFunnelStepSchema = z24.object({
|
|
12580
12563
|
stepId: z24.string(),
|
|
12581
12564
|
stepIndex: z24.number().int().nonnegative(),
|
|
12565
|
+
/** Visits that moved forward into this step. Never events — see `visits`. */
|
|
12582
12566
|
views: z24.number().int().nonnegative(),
|
|
12567
|
+
/** Visits that finished this step and moved on. */
|
|
12583
12568
|
completions: z24.number().int().nonnegative(),
|
|
12584
12569
|
/** Share of viewers who did not complete this step, 0–1. */
|
|
12585
12570
|
dropRate: z24.number().min(0).max(1).nullable(),
|
|
@@ -12591,13 +12576,37 @@ var analyticsFunnelStepSchema = z24.object({
|
|
|
12591
12576
|
* conversion, and knowing which step owns it is what stops a drop-off chart
|
|
12592
12577
|
* treating the booking widget's "profile viewed" as a funnel stage.
|
|
12593
12578
|
*/
|
|
12594
|
-
convertedSessions: z24.number().int().nonnegative()
|
|
12579
|
+
convertedSessions: z24.number().int().nonnegative(),
|
|
12580
|
+
/**
|
|
12581
|
+
* This step is where the Form ends — a confirmation screen, not a loss.
|
|
12582
|
+
*
|
|
12583
|
+
* Stated rather than left to be inferred. The dashboard used to read it off
|
|
12584
|
+
* `dropRate === null`, which is also how a step nobody viewed arrives, so a
|
|
12585
|
+
* converting link node in the middle of a Form was labelled its ending.
|
|
12586
|
+
*/
|
|
12587
|
+
isEnding: z24.boolean()
|
|
12595
12588
|
});
|
|
12596
12589
|
var analyticsFunnelSchema = z24.object({
|
|
12597
12590
|
flowSlug: z24.string(),
|
|
12591
|
+
/**
|
|
12592
|
+
* Visits that saw the Form at all — the denominator for every share here.
|
|
12593
|
+
*
|
|
12594
|
+
* Read this, not `starts`, whenever the question is "out of how many". A
|
|
12595
|
+
* start is recorded at the visitor's FIRST INTERACTION, so the two differ by
|
|
12596
|
+
* exactly the people who looked at the Form and never touched it — usually
|
|
12597
|
+
* most of them, and always the group a drop-off chart exists to find.
|
|
12598
|
+
*
|
|
12599
|
+
* Every count in this object is distinct visits, including each step's
|
|
12600
|
+
* `views` and `completions`. That is load-bearing rather than incidental:
|
|
12601
|
+
* the screen divides these by each other, and while the steps counted events
|
|
12602
|
+
* a Form four people had opened reported one step reached fifteen times and
|
|
12603
|
+
* fourteen people lost.
|
|
12604
|
+
*/
|
|
12605
|
+
visits: z24.number().int().nonnegative(),
|
|
12606
|
+
/** Visits that interacted with the Form at all — typed, picked, or advanced. */
|
|
12598
12607
|
starts: z24.number().int().nonnegative(),
|
|
12599
12608
|
submits: z24.number().int().nonnegative(),
|
|
12600
|
-
/**
|
|
12609
|
+
/** Conversions per visit that opened the Form, 0–1. */
|
|
12601
12610
|
completionRate: z24.number().min(0).max(1).nullable(),
|
|
12602
12611
|
/** The step losing the most people. The single most useful field here. */
|
|
12603
12612
|
worstStep: analyticsFunnelStepSchema.nullable(),
|
|
@@ -13171,10 +13180,74 @@ var analyticsMappingResponseSchema = z24.object({
|
|
|
13171
13180
|
* turn configuring `keyword` to mean keyword.
|
|
13172
13181
|
*/
|
|
13173
13182
|
builtIn: z24.array(z24.string()),
|
|
13183
|
+
/**
|
|
13184
|
+
* What the client's own ad account says about each parameter just staged.
|
|
13185
|
+
*
|
|
13186
|
+
* Present only when a Session staged a `set` on a platform whose tracking
|
|
13187
|
+
* configuration Baker can read. `contradicted` is the entry worth stopping
|
|
13188
|
+
* for: the account fills that name with a placeholder meaning something
|
|
13189
|
+
* else, so the answer just given would produce a report that is wrong and
|
|
13190
|
+
* looks entirely plausible.
|
|
13191
|
+
*/
|
|
13192
|
+
evidence: z24.record(
|
|
13193
|
+
z24.string(),
|
|
13194
|
+
z24.object({
|
|
13195
|
+
status: z24.enum(["confirmed", "contradicted", "unseen", "not_read"]),
|
|
13196
|
+
macro: z24.string().optional(),
|
|
13197
|
+
suggestedRole: adParamRoleSchema.optional(),
|
|
13198
|
+
source: z24.string().optional(),
|
|
13199
|
+
reason: z24.string().optional()
|
|
13200
|
+
})
|
|
13201
|
+
).optional(),
|
|
13174
13202
|
updatedAt: z24.number().nullable()
|
|
13175
13203
|
}),
|
|
13176
13204
|
hints: z24.array(z24.string()).optional()
|
|
13177
13205
|
});
|
|
13206
|
+
var analyticsTrackingRequestSchema = z24.object({
|
|
13207
|
+
platform: z24.enum(AD_PLATFORMS).optional(),
|
|
13208
|
+
days: z24.number().int().min(1).max(365).optional()
|
|
13209
|
+
});
|
|
13210
|
+
var trackingDimensionSchema = z24.object({
|
|
13211
|
+
role: adParamRoleSchema,
|
|
13212
|
+
/** The platform's own macro for it — what goes in the URL. */
|
|
13213
|
+
macro: z24.string(),
|
|
13214
|
+
/** The account's own spelling where it has one, else the canonical name. */
|
|
13215
|
+
name: z24.string(),
|
|
13216
|
+
/**
|
|
13217
|
+
* What has to happen for this dimension to reach a report.
|
|
13218
|
+
*
|
|
13219
|
+
* Four states rather than a boolean, because two of them need opposite fixes
|
|
13220
|
+
* and one of them is not a finding at all. `unmapped` is one
|
|
13221
|
+
* `baker analytics map` call and repairs the history with it; `missing` is a
|
|
13222
|
+
* change to the ad account and everything before it stays unattributable;
|
|
13223
|
+
* `unknown` means no visit arrived and the account could not be read, which
|
|
13224
|
+
* must never be reported as untagged.
|
|
13225
|
+
*/
|
|
13226
|
+
state: z24.enum(["covered", "unmapped", "missing", "unknown"]),
|
|
13227
|
+
evidence: z24.string().optional(),
|
|
13228
|
+
note: z24.string().optional()
|
|
13229
|
+
});
|
|
13230
|
+
var analyticsTrackingPlatformSchema = z24.object({
|
|
13231
|
+
platform: z24.enum(AD_PLATFORMS),
|
|
13232
|
+
label: z24.string(),
|
|
13233
|
+
sessions: z24.number(),
|
|
13234
|
+
/** Whether the ad account itself could be read, and why not when it could not. */
|
|
13235
|
+
account: z24.object({ read: z24.boolean(), templates: z24.number(), reason: z24.string().optional() }),
|
|
13236
|
+
dimensions: z24.array(trackingDimensionSchema),
|
|
13237
|
+
/** Names the URLs already carry that Baker does not read yet. */
|
|
13238
|
+
unmapped: z24.record(z24.string(), adParamRoleSchema),
|
|
13239
|
+
mapCommand: z24.string(),
|
|
13240
|
+
unexplained: z24.array(z24.object({ name: z24.string(), value: z24.string() })),
|
|
13241
|
+
/** The pairs to append to the account's tagging, or `""`. */
|
|
13242
|
+
suffix: z24.string(),
|
|
13243
|
+
whereItGoes: z24.string(),
|
|
13244
|
+
fix: z24.string().optional()
|
|
13245
|
+
});
|
|
13246
|
+
var analyticsTrackingResponseSchema = z24.object({
|
|
13247
|
+
ok: z24.literal(true),
|
|
13248
|
+
data: z24.object({ days: z24.number(), platforms: z24.array(analyticsTrackingPlatformSchema) }),
|
|
13249
|
+
hints: z24.array(z24.string()).optional()
|
|
13250
|
+
});
|
|
13178
13251
|
var submissionRecordRequestSchema = z24.object({
|
|
13179
13252
|
/** Injected by the Worker from the host or the site key. Never from the page. */
|
|
13180
13253
|
companyId: z24.string().min(1),
|
|
@@ -23707,7 +23780,7 @@ var funnelCommand = presetCommand({
|
|
|
23707
23780
|
var flowCommand = presetCommand({
|
|
23708
23781
|
name: "flow",
|
|
23709
23782
|
preset: "flow",
|
|
23710
|
-
description: "One Form in depth: how many people it converted, where they went between steps, the per-step table, and every trigger it raised. Read `flowSummary.convertedSessions`, not `submits` \u2014 a Form that books a call on a scheduling node in the MIDDLE of the flow never emits a submit, so it reports zero submits and every one of its real bookings as conversions. `flowPaths` is the flow as edges between steps, bracketed by __flow_start__, __flow_converted__ and __flow_exit__, which is how a branching Form is read at all: a per-step table cannot say that of the people who left step two, forty went to the booking branch and ninety went nowhere.",
|
|
23783
|
+
description: "One Form in depth: how many people it converted, where they went between steps, the per-step table, and every trigger it raised. Every count is DISTINCT VISITS, so quote shares against `funnels[].visits` \u2014 the visits that opened the Form \u2014 and never against `starts`, which is only the visits that touched it. The gap between the two is people who read the Form and left, and on most Forms it is the largest loss there is. Read `flowSummary.convertedSessions`, not `submits` \u2014 a Form that books a call on a scheduling node in the MIDDLE of the flow never emits a submit, so it reports zero submits and every one of its real bookings as conversions. `flowPaths` is the flow as edges between steps, bracketed by __flow_start__, __flow_converted__ and __flow_exit__, which is how a branching Form is read at all: a per-step table cannot say that of the people who left step two, forty went to the booking branch and ninety went nowhere.",
|
|
23711
23784
|
extraArgs: { flow: { type: "string", description: "Form slug (default: every Form)", required: false } },
|
|
23712
23785
|
resolve: (args) => ({ preset: "flow", flowSlug: args.flow ? String(args.flow) : void 0 })
|
|
23713
23786
|
});
|
|
@@ -23883,13 +23956,13 @@ var mapCommand = (() => {
|
|
|
23883
23956
|
};
|
|
23884
23957
|
registerSchema({
|
|
23885
23958
|
command: "analytics.map",
|
|
23886
|
-
description: "
|
|
23959
|
+
description: "Stage how this company's campaign URLs spell each ad dimension, applied on publish",
|
|
23887
23960
|
args
|
|
23888
23961
|
});
|
|
23889
23962
|
return defineCommand88({
|
|
23890
23963
|
meta: {
|
|
23891
23964
|
name: "map",
|
|
23892
|
-
description: "Teach Baker how this company's campaign URLs spell each ad dimension on one platform \u2014 `--platform google --set kw=keyword`. Run it with no flags to see the whole mapping. Mappings are always per platform, because the platforms do not describe the same world: `builtIn` in the response is what that platform is already understood to send, so you do not spend a turn mapping `keyword` to keyword.
|
|
23965
|
+
description: "Teach Baker how this company's campaign URLs spell each ad dimension on one platform \u2014 `--platform google --set kw=keyword`. Run it with no flags to see the whole mapping, including what this chat has already staged. STAGED, not applied: the answers are reviewed in the chat and take effect when it is published, so nothing you map here changes a report or what the edge stores until then; discarding the chat takes them all back. Mappings are always per platform, because the platforms do not describe the same world: `builtIn` in the response is what that platform is already understood to send, so you do not spend a turn mapping `keyword` to keyword. Each --set is checked against the client's OWN ad account \u2014 `evidence` in the response says whether their tracking template really fills that name with what you claimed. Read it: `contradicted` means the account disagrees, and mapping it your way would produce a report that is wrong and looks plausible. Renaming a parameter Baker already captured fixes the history too, because roles are applied when a report is read; naming one it never read only starts collecting it from the publish onward, since no value was stored. You do NOT need to have seen a parameter to map it: a name nobody has sent yet is a valid --set, which is how a tracking template gets configured before the campaign that uses it runs. To drop an answer, --remove takes it back to whatever Baker knows by itself, and --set <name>=ignore says it is not campaign information at all so it stops being listed."
|
|
23893
23966
|
},
|
|
23894
23967
|
args,
|
|
23895
23968
|
run: async ({ args: raw }) => {
|
|
@@ -23907,6 +23980,61 @@ var mapCommand = (() => {
|
|
|
23907
23980
|
}
|
|
23908
23981
|
});
|
|
23909
23982
|
})();
|
|
23983
|
+
var trackingCommand = (() => {
|
|
23984
|
+
const args = {
|
|
23985
|
+
platform: {
|
|
23986
|
+
type: "string",
|
|
23987
|
+
description: "One platform: google, meta, microsoft, linkedin, tiktok, reddit, pinterest, snapchat. Omit to check the ones worth checking \u2014 every platform sending visits, plus Google and Meta, whose accounts Baker can read directly",
|
|
23988
|
+
required: false
|
|
23989
|
+
},
|
|
23990
|
+
days: { type: "string", description: "Lookback window for the traffic half (default: 30)", required: false }
|
|
23991
|
+
};
|
|
23992
|
+
registerSchema({
|
|
23993
|
+
command: "analytics.tracking",
|
|
23994
|
+
description: "Check whether a platform's ad URLs carry the campaign, ad group and ad a report needs",
|
|
23995
|
+
args
|
|
23996
|
+
});
|
|
23997
|
+
return defineCommand88({
|
|
23998
|
+
meta: {
|
|
23999
|
+
name: "tracking",
|
|
24000
|
+
description: `Check whether this company's ad URLs carry the dimensions any budget decision needs \u2014 the campaign, the ad group, the ad, and the keyword where the platform has one.
|
|
24001
|
+
|
|
24002
|
+
Read this before auditing an ad account and before answering any "which ad performed best" question. Each dimension comes back in one of four states, and they need different things:
|
|
24003
|
+
covered \u2014 arriving and understood, nothing to do
|
|
24004
|
+
unmapped \u2014 the URLs carry it under a name Baker does not read yet. Free to fix, and it repairs the traffic already collected: run the \`mapCommand\` in the response
|
|
24005
|
+
missing \u2014 nothing carries it. Add \`suffix\` to the account's tagging (\`whereItGoes\` says where, \`fix\` says whether Baker can stage it). This one cannot be filled in later \u2014 a parameter's values are only stored once it starts arriving
|
|
24006
|
+
unknown \u2014 no visit arrived AND the account could not be read. Not a finding; do not report it as untagged
|
|
24007
|
+
|
|
24008
|
+
Baker reads the client's own Google tracking templates and Meta URL parameters, so a platform that has not run yet still gets a real answer.
|
|
24009
|
+
|
|
24010
|
+
Examples:
|
|
24011
|
+
baker analytics tracking
|
|
24012
|
+
baker analytics tracking --platform meta
|
|
24013
|
+
baker analytics tracking --platform google --days 90`
|
|
24014
|
+
},
|
|
24015
|
+
args,
|
|
24016
|
+
run: async ({ args: raw }) => {
|
|
24017
|
+
try {
|
|
24018
|
+
const platform = raw.platform === void 0 ? void 0 : String(raw.platform);
|
|
24019
|
+
if (platform !== void 0 && !isAdPlatform(platform)) {
|
|
24020
|
+
writeJsonEnvelope({
|
|
24021
|
+
ok: false,
|
|
24022
|
+
error: { code: "BAD_REQUEST", message: `Unknown platform "${platform}"` }
|
|
24023
|
+
});
|
|
24024
|
+
process.exit(1);
|
|
24025
|
+
}
|
|
24026
|
+
const days = raw.days === void 0 ? void 0 : Number(raw.days);
|
|
24027
|
+
const response = await apiPost("/api/analytics/tracking", {
|
|
24028
|
+
...platform ? { platform } : {},
|
|
24029
|
+
...days !== void 0 && Number.isFinite(days) ? { days } : {}
|
|
24030
|
+
});
|
|
24031
|
+
writeJsonEnvelope(response);
|
|
24032
|
+
} catch (err) {
|
|
24033
|
+
handleError(err);
|
|
24034
|
+
}
|
|
24035
|
+
}
|
|
24036
|
+
});
|
|
24037
|
+
})();
|
|
23910
24038
|
function parsePairs(raw) {
|
|
23911
24039
|
if (raw === void 0) return void 0;
|
|
23912
24040
|
const out = {};
|
|
@@ -23955,7 +24083,9 @@ Examples:
|
|
|
23955
24083
|
baker analytics ads --role keyword \u2014 keywords by conversions AND by how many bounced
|
|
23956
24084
|
baker analytics ads --platform google --role keyword \u2014 the same, in Google's vocabulary and from Google's traffic only
|
|
23957
24085
|
baker analytics overview --role keyword --value "solar panels" \u2014 the whole report for those visits only
|
|
23958
|
-
baker analytics
|
|
24086
|
+
baker analytics tracking \u2014 do the ad URLs carry the campaign, ad group and ad at all
|
|
24087
|
+
baker analytics tracking --platform meta \u2014 the same for one platform, read from their own ad account
|
|
24088
|
+
baker analytics map --platform google --set kw=keyword \u2014 stage a parameter name, seen or not yet
|
|
23959
24089
|
baker analytics map --platform google --remove kw \u2014 take that answer back
|
|
23960
24090
|
baker analytics delivery --page 2 --page-size 50 \u2014 the next page of a long list
|
|
23961
24091
|
baker analytics overview --compare \u2014 this window against the one before it
|
|
@@ -23980,6 +24110,7 @@ Full guide: __tooling__/docs/tools/baker/analytics.md`
|
|
|
23980
24110
|
devices: devicesCommand,
|
|
23981
24111
|
ads: adsCommand3,
|
|
23982
24112
|
map: mapCommand,
|
|
24113
|
+
tracking: trackingCommand,
|
|
23983
24114
|
presets: presetsCommand
|
|
23984
24115
|
}
|
|
23985
24116
|
});
|
|
@@ -33840,10 +33971,6 @@ var MAPPING_SLOTS = {
|
|
|
33840
33971
|
twitterAds: [
|
|
33841
33972
|
{ kind: "record", key: "userMatching", allowed: ["em", "ph"] },
|
|
33842
33973
|
{ kind: "scalar", keys: ["value", "currency"] }
|
|
33843
|
-
],
|
|
33844
|
-
microsoftAds: [
|
|
33845
|
-
{ kind: "record", key: "userMatching", allowed: ["em", "ph"] },
|
|
33846
|
-
{ kind: "scalar", keys: ["value", "currency", "transactionId"] }
|
|
33847
33974
|
]
|
|
33848
33975
|
};
|
|
33849
33976
|
var UNMAPPABLE = {
|