@koda-sl/baker-cli 0.396.0 → 0.397.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 CHANGED
@@ -3465,7 +3465,7 @@ baker scheduled-agents templates --delete weekly-posthog-check
3465
3465
 
3466
3466
  ### Marketing Tags (`baker tags`)
3467
3467
 
3468
- Read the client's marketing/analytics tags (Meta pixel, GA4, Google Ads, GTM, Clarity, Hotjar, PostHog, …) — production tags overlaid with the changes staged in this chat.
3468
+ Read the client's marketing/analytics tags (Meta pixel, ChatGPT Ads pixel, GA4, Google Ads, GTM, Clarity, Hotjar, PostHog, …) — production tags overlaid with the changes staged in this chat.
3469
3469
 
3470
3470
  **The CLI is read-only.** Every tag change (create, edit, delete) goes through the `request_tag_input` tool (`baker_ui` MCP server): the agent proposes one or more changes — each becomes a tab in one blocking approval form — pre-filling the non-secret fields it knows; the user reviews, edits, fills secret fields, and approves or skips each tab. Approved changes stage on the chat and apply when the chat is published; discarding the chat drops them.
3471
3471
 
@@ -3481,6 +3481,7 @@ Notes:
3481
3481
  - **Both reads restate the write path, on stderr.** `list` and `draft` end with the two lines that say the approval form is the only way to change a tag, that it rides on every turn, and that a tag change is never a Task. They are there because a chat concluded from its tool list alone that the form did not exist, never called it, and filed the change as a Task for the user to carry out by hand. stdout stays the list, so piping it is unaffected; `--json` carries the same lines in the envelope's `hints`.
3482
3482
  - **`list` prints each tag's full readable config.** Every non-secret field is shown in full under the tag — the Clarity `projectId`, GA4 `measurementId`, the entire custom `code` snippet, etc. — so the agent reuses a stored value to pre-fill a follow-up change instead of asking the user for something already installed. Secrets are never among these fields. (`--json` emits the same data as the raw envelope.)
3483
3483
  - **Secrets never travel through this CLI or the chat.** Secret fields (`accessToken`, `apiSecret`, `authorizationToken`, `apiKey`, `conversionToken`, `oauthProviderId`) are entered only in the dashboard's secure tag form and flow straight into the staged draft; tool responses only ever name which secret fields are set/pending.
3484
+ - A `chatgptAds` tag takes a Pixel ID. Its optional `apiKey` is the Conversions API key and enables the server copy of page and Form events; the key stays out of the CLI and published page.
3484
3485
  - Staged creates get a server-generated `tag_temp_*` ref (returned in the tool result and printed by `list`). Use it (or a real tag id) as flow side-effect `tagIds` — the published tag keeps resolving under the temp ref.
3485
3486
  - Proposing a delete on a `tag_temp_*` ref drops the staged create instead.
3486
3487
  - Single-instance types (`code`, `posthog`, `datafast`) reject a second instance against the chat's effective view.
@@ -3490,6 +3491,8 @@ Notes:
3490
3491
 
3491
3492
  Read and shape this workspace's Forms (flows). Operates on the local `_data.json` files only; no secret values are ever decrypted or printed.
3492
3493
 
3494
+ For ChatGPT Ads conversions, add a `chatgptAds` side effect to the Form step, choose a supported event name, and use `baker flows map` to map `advancedMatching` and optional `eventParams` (`value` and `currency`).
3495
+
3493
3496
  **A Form has two halves, split by a trust boundary.** Its *structure* — steps, conditions, side effects, field mappings — is yours, and the write subcommands below edit exactly that. Its *confidential* half — connection secrets, OAuth accounts, third-party field definitions (HubSpot, Calendly, HighLevel, SavvyCal) — is configured through the `request_flow_input` tool (`baker_ui` MCP server): the agent authors the surrounding structure and references it by `nodeId`/`sideEffectId`, and the user enters secrets, connects accounts, and picks resources in the dashboard. Those values are written (encrypted, where a secret) into the Form on the chat's branch and go live when the chat is published. Nothing any of these commands does touches a live system.
3494
3497
 
3495
3498
  ```bash
package/dist/cli.js CHANGED
@@ -27117,6 +27117,16 @@ var FLOW_SIDE_EFFECT_CATALOG = [
27117
27117
  },
27118
27118
  "`advancedMatching` is how Meta re-identifies the visitor, and it is the difference between a matched conversion and a discarded one. Fill at least `em` and `ph` from the form: `baker flows map <slug> --map em=email --map ph=phone`."
27119
27119
  ),
27120
+ eventSideEffect(
27121
+ "chatgptAds",
27122
+ "Fires a ChatGPT Ads pixel conversion and mirrors it through the Conversions API when a key is configured.",
27123
+ {
27124
+ eventType: "standard",
27125
+ eventParams: [],
27126
+ advancedMatching: matchingSlots("em", "ph", "fn", "ln", "external_id", "ct", "st", "zp", "country")
27127
+ },
27128
+ "Use ChatGPT Ads event names such as lead_created, order_created or appointment_scheduled. For a custom event use a lowercase name of 1\u201364 letters, digits, underscores or dashes. Only value (major currency units) and currency are supported in eventParams. Map em from the form to improve conversion matching."
27129
+ ),
27120
27130
  eventSideEffect("googleAnalytics", "Fires a GA4 event.", { eventType: "custom", eventParams: [] }),
27121
27131
  {
27122
27132
  kind: "side-effect",
@@ -30032,6 +30042,7 @@ var studioImproveResponseSchema = z32.object({ prompt: z32.string(), original: z
30032
30042
  import { z as z33 } from "zod";
30033
30043
  var TAG_TYPES = [
30034
30044
  "meta",
30045
+ "chatgptAds",
30035
30046
  "amplitude",
30036
30047
  "googleAds",
30037
30048
  "tiktok",
@@ -30053,6 +30064,7 @@ var TAG_TYPES = [
30053
30064
  var tagTypeSchema = z33.enum(TAG_TYPES);
30054
30065
  var TAG_IDENTIFYING_FIELD = {
30055
30066
  meta: "pixelId",
30067
+ chatgptAds: "pixelId",
30056
30068
  googleAds: "conversionID",
30057
30069
  tiktok: "pixelCode",
30058
30070
  pinterest: "tagId",
@@ -41395,7 +41407,8 @@ var INGEST_CLICK_ID_PARAMS = [
41395
41407
  "msclkid",
41396
41408
  "rdt_cid",
41397
41409
  "epik",
41398
- "sccid"
41410
+ "sccid",
41411
+ "oppref"
41399
41412
  ];
41400
41413
 
41401
41414
  // ../api/src/event-sources/fields.ts
@@ -41421,7 +41434,8 @@ var CLICK_LABELS = {
41421
41434
  msclkid: "Microsoft click id",
41422
41435
  rdt_cid: "Reddit click id",
41423
41436
  epik: "Pinterest click id",
41424
- sccid: "Snapchat click id"
41437
+ sccid: "Snapchat click id",
41438
+ oppref: "ChatGPT Ads click id"
41425
41439
  };
41426
41440
  var SOURCE_FIELDS = [
41427
41441
  { field: "event_name", label: "What happened", group: "event" },
@@ -41518,7 +41532,14 @@ function parseEventKey(key) {
41518
41532
  }
41519
41533
 
41520
41534
  // ../api/src/analytics/sends.ts
41521
- var SEND_PLATFORMS = ["meta", "googleAds", "linkedinInsightTag", "twitterAds", "googleAnalytics"];
41535
+ var SEND_PLATFORMS = [
41536
+ "meta",
41537
+ "chatgptAds",
41538
+ "googleAds",
41539
+ "linkedinInsightTag",
41540
+ "twitterAds",
41541
+ "googleAnalytics"
41542
+ ];
41522
41543
  function isSendPlatform(value2) {
41523
41544
  return SEND_PLATFORMS.includes(value2);
41524
41545
  }
@@ -41530,6 +41551,13 @@ var SEND_PLATFORM_SPECS = {
41530
41551
  credentialFields: ["accessToken"],
41531
41552
  setupHint: "Add the Conversions API access token to the Meta pixel in Tracking"
41532
41553
  },
41554
+ chatgptAds: {
41555
+ title: "ChatGPT Ads",
41556
+ eventMeans: "A ChatGPT Ads event \u2014 lead_created, order_created, or a custom name",
41557
+ eventKind: "name",
41558
+ credentialFields: ["apiKey"],
41559
+ setupHint: "Add the Conversions API key to the ChatGPT Ads pixel in Tracking"
41560
+ },
41533
41561
  googleAds: {
41534
41562
  title: "Google Ads",
41535
41563
  eventMeans: "One of the account's conversion actions, picked from its list",
@@ -41580,6 +41608,7 @@ function isConversionSend(type) {
41580
41608
  }
41581
41609
  var SERVER_SIDE_SENDER_TAG = {
41582
41610
  metaCapi: "meta",
41611
+ chatgptAdsCapi: "chatgptAds",
41583
41612
  googleAdsCapi: "googleAds",
41584
41613
  linkedinCapi: "linkedinInsightTag",
41585
41614
  twitterAdsCapi: "twitterAds",
@@ -41784,7 +41813,8 @@ var analyticsBeaconClickIdsSchema = z40.object({
41784
41813
  msclkid: z40.string().max(255).optional(),
41785
41814
  rdtCid: z40.string().max(255).optional(),
41786
41815
  epik: z40.string().max(255).optional(),
41787
- sccid: z40.string().max(255).optional()
41816
+ sccid: z40.string().max(255).optional(),
41817
+ oppref: z40.string().max(255).optional()
41788
41818
  });
41789
41819
  var analyticsBeaconIdentitySchema = z40.object({
41790
41820
  /** Lowercase hex SHA-256. Anything else is dropped rather than stored. */
@@ -42062,6 +42092,7 @@ var IDENTITY_KEY_KINDS = [
42062
42092
  "rdt_cid",
42063
42093
  "epik",
42064
42094
  "sccid",
42095
+ "oppref",
42065
42096
  "fbp",
42066
42097
  "fbc"
42067
42098
  ];
@@ -42087,6 +42118,7 @@ var MATCH_KEY_LABELS = {
42087
42118
  rdt_cid: "Reddit click",
42088
42119
  epik: "Pinterest click",
42089
42120
  sccid: "Snapchat click",
42121
+ oppref: "ChatGPT Ads click",
42090
42122
  fbp: "Meta browser cookie",
42091
42123
  fbc: "Meta click cookie"
42092
42124
  };
@@ -42122,6 +42154,7 @@ var VERBATIM_KINDS = [
42122
42154
  "rdt_cid",
42123
42155
  "epik",
42124
42156
  "sccid",
42157
+ "oppref",
42125
42158
  "fbp",
42126
42159
  "fbc"
42127
42160
  ];
@@ -42264,7 +42297,8 @@ var CLICK_LABELS2 = {
42264
42297
  msclkid: "Microsoft click id",
42265
42298
  rdt_cid: "Reddit click id",
42266
42299
  epik: "Pinterest click id",
42267
- sccid: "Snapchat click id"
42300
+ sccid: "Snapchat click id",
42301
+ oppref: "ChatGPT Ads click id"
42268
42302
  };
42269
42303
  var PERSON_FIELDS = MATCH_FIELD_FORWARDING.map((row) => ({
42270
42304
  name: row.field,
@@ -44077,7 +44111,7 @@ var analyticsVisitorRowSchema = z44.object({
44077
44111
  /**
44078
44112
  * The click ids this person arrived on, by their own names — `gclid`,
44079
44113
  * `fbclid`, `msclkid`, `li_fat_id`, `ttclid`, `twclid`, `wbraid`, `gbraid`,
44080
- * `dclid`, `rdt_cid`, `epik`, `sccid`.
44114
+ * `dclid`, `rdt_cid`, `epik`, `sccid`, `oppref`.
44081
44115
  *
44082
44116
  * Only the ones that were present. The endpoint has always returned all eight
44083
44117
  * columns and nothing above it carried them, so the one screen whose subject
@@ -58183,7 +58217,7 @@ var EVENT_FIELDS = [
58183
58217
  name: "the ad click ids",
58184
58218
  need: "optional",
58185
58219
  under: true,
58186
- takes: "The click id that brought them, if you kept it, under the name the platform stamps on the link: gclid, wbraid, gbraid, dclid, fbclid, ttclid, twclid, li_fat_id, msclkid, rdt_cid, epik, sccid (Snapchat's ScCid, in any case).",
58220
+ takes: "The click id that brought them, if you kept it, under the name the platform stamps on the link: gclid, wbraid, gbraid, dclid, fbclid, ttclid, twclid, li_fat_id, msclkid, rdt_cid, epik, sccid (Snapchat's ScCid, in any case), oppref (ChatGPT Ads).",
58187
58221
  note: "A click id names a person too \u2014 it is enough on its own, and it attributes the event to the campaign that earned it."
58188
58222
  },
58189
58223
  {
@@ -78807,6 +78841,14 @@ var MAPPING_SLOTS = {
78807
78841
  code: [PAYLOAD("eventProperties")],
78808
78842
  datafast: [PAYLOAD("goalParams")],
78809
78843
  meta: [PAYLOAD("eventParams"), { kind: "record", key: "advancedMatching", allowed: META_MATCHING }],
78844
+ chatgptAds: [
78845
+ PAYLOAD("eventParams"),
78846
+ {
78847
+ kind: "record",
78848
+ key: "advancedMatching",
78849
+ allowed: ["em", "ph", "fn", "ln", "external_id", "ct", "st", "zp", "country"]
78850
+ }
78851
+ ],
78810
78852
  tiktok: [
78811
78853
  PAYLOAD("eventParams"),
78812
78854
  { kind: "record", key: "identify", allowed: ["email", "phone_number", "external_id"] }