Launch

Launch something new — a Meta campaign, a social post or schedule, a blog post, email or ad copy.

Everything here is draft first, human second. The drafting tools are low tier and write immediately; every tool that reaches the outside world is high tier and only files an approval. Get the draft right — that is the part you control.

Prerequisite: the marketing-os foundation skill.

Before anything: the voice is not yours

get_brand_profile      # voice, audience, offerings, AI always/never rules,
                       # banned words, required mentions
search_knowledge       # their real offers, pricing, policies, proof

The banned-word and always/never rules are enforcement, not style notes — a blocked angle is refused by the blocked_angle guardrail, and the refusal names the phrase it matched. Read them before writing, not after being refused.

Cite the business's own facts. If search_knowledge cannot support a claim, either leave it out or ask the user to confirm it. Never invent a statistic, a testimonial, a guarantee, a price or a delivery promise.


Launching a Meta campaign

Six steps, two approvals, nothing live by accident.

1  meta_list_pages                     # which Page the ads run under
2  list_media_files                    # the creative that actually exists
3  meta_draft_campaign_plan     (low)  # structure, targeting, budget, creatives
4  meta_set_campaign_plan_budget/_page (low)  # tune the draft
   meta_approve_campaign_plan   (low)  # mark it ready — still creates nothing
5  meta_deploy_campaign_plan    (HIGH) # creates it on Meta, PAUSED
6  meta_activate_campaign_plan  (HIGH) # the call that starts spend

Show the user the plan before step 5. Structure, targeting, daily budget and every piece of ad copy, in the message — not a summary of it.

meta_draft_campaign_plan arguments, and where each comes from:

ArgumentSource
businessModelecommerce or lead_gen — from get_business_context's goal
monthlyBudgetCentsthe user, checked against monthlyBudgetCents and the spend caps
aovCents, breakEvenRoasget_business_context (ecommerce)
targetCplCentsget_business_context (lead gen)
dealValueCents, closeRatePercentlead gen: get_business_context, else ask; saved to the business
emailListSize, socialFollowingask — none / under_1k / 1k_to_10k / over_10k
creativeAssetsproduct_photos, videos, ugc, testimonials, brand_assets
creativeAssetIdsreal ids from list_media_files, never invented
countriesISO-3166-1 alpha-2, checked against the geo guardrails first
pixelInstalledomit. The server reads the synced ad account's pixel; only a demo account uses it

Check the daily budget against get_guardrails before drafting: dailySpendCapCents, monthlySpendCapCents, and Meta's 100 cents/day floor.

Deploy and activate are two approvals because a deployed campaign sits paused until somebody says otherwise. After step 5, tell the user exactly that: it exists on Meta, it is paused, it is spending nothing.

Launching a promo-code / collaboration campaign

"Set up a campaign for our collaboration with Tory Media — 10% off everything with code TORY10."

A promotion is a saved object the campaign and the posts are built around, so the code, the discount link and the utm_campaign all come from one row.

1  promotions_list                     # does the code already exist? (unique per business)
2  promotions_create_draft      (low)  # only if it does not — the code the user gave
3  promotions_publish_to_store  (HIGH) # only with a Shopify store: puts the code on it
4  meta_draft_campaign_plan     (low)  # with promotionId; leave offer + landingUrl out
5  show the plan                       # before any deploy — same rule as above
6  meta_deploy_campaign_plan    (HIGH) → meta_activate_campaign_plan (HIGH)
7  social_create_post           (HIGH) # with the same promotionId

Never invent a code. The code comes from promotions_list or from the user's own words — if neither gives one, ask. The same goes for the discount: "a discount for their followers" is not a number, so ask for it.

promotions_create_draft arguments:

ArgumentSource
partnerNamethe user — the collaborator, creator or partner
codethe user, exactly as given (upper-cased by the server); never made up
discountType, discountValuethe user — percent (10 = 10% off) or fixed (10 = 10.00 off in the store currency)
scopeall, or { productIds } with real ids from commerce_list_products — a product needs a store
startsAt, endsAtthe user; ISO-8601 with an offset. Omitted = starts when live, no end
landingPathoptional storefront path, never a full URL; one product in scope defaults to its page

The code, discount and scope cannot be changed after creation — read them back to the user before calling it.

With a store connected the promotion is saved as a draft and the code does not exist on the store until step 3 is approved. Say so: an ad quoting a code the checkout rejects is worse than no ad. Without a store it is saved active and step 3 is skipped (and refused if called).

Step 4 can run before step 3 is approved — the plan re-reads the promotion at deploy, so it links to the discount once the code is on the store. Passing promotionId fills the offer, the landing link and the ads' utm_campaign; typing the code into offer yourself loses all three.

Show the user the plan before step 6, the code included, exactly as for any Meta campaign. For posts, pass the same promotionId: the caption gets a "Use code …" line unless it already contains the code — do not type a code promotions_list did not return.

Afterwards, promotions_performance reads the orders that used the code and their revenue. It needs a store — source none means zeros, not "no sales".

Launching a social post

1  social_list_accounts   # ids + status. An expired account cannot publish.
2  list_media_files       # the media ids, by their real ids
3  get_brand_profile      # voice and the platform posting rules
4  social_create_post  (HIGH)

social_create_post is always high — it reaches a real audience and there is no undo worth the name. It files an approval; it does not post.

Media rules the call validates, so check them first: Facebook Page 0–1 image or video · Instagram exactly 1 image or video · TikTok exactly 1 video · YouTube exactly 1 video. A caption is ≤5,000 characters, up to 10 media ids, 1–20 targets.

Scheduling: scheduledAt is ISO-8601; omit it to publish on approval. Write one caption per platform rather than one caption for all of them — the same words rarely work on a Facebook Page and on TikTok — by filing separate posts when the copy genuinely differs.

If the platform the user named is not connected, say so and stop. Do not retarget the post to a platform they did not ask for.

Launching content

1  get_brand_profile + search_knowledge
2  create_marketing_asset_draft  (low)   # blog_post | email | ad_copy |
                                         # landing_page | social_post
3  update_marketing_asset        (low)   # revisions, with a note saying why

Body fields: title, bodyMarkdown, and optionally metaDescription, targetKeywords, category, heroImageAssetId.

A draft is inert. No tool can set published — publishing is its own gated path in Marketing OS. Say that: "the draft is saved; publishing is a step you take in the app."

For anything meant to rank, pull targetKeywords from the brand profile's SEO keyword profile and from google_search_performance's top queries — the queries the site already shows up for beat keywords chosen from intuition.

After the launch

Tell the user, in plain words:

  1. What actually exists now — the draft, the plan, the paused campaign.
  2. What is waiting in their approvals inbox, itemised.
  3. What has not happened, in as many words. This is the sentence that stops a high tier call being misread as done.
  4. When to check back — an ad set needs 50 conversions in 7 days to leave the learning phase, so do not promise a verdict before then.

Do not

  • Report a high-tier call as done. It is filed.
  • Activate a campaign in the same breath as deploying it, unless the user explicitly asked for both.
  • Invent an asset id, a Page id, a socialAccountId or a businessId.
  • Write copy before reading the brand profile.
  • Set a budget without checking it against the guardrails.
  • Invent a promo code or a discount, or type a code into copy that promotions_list did not return.

Something wrong or missing on this page? Tell us and we will fix it.