Marketing

Ad campaign runbook

A LinkedIn Ads campaign runbook for one blog post: what the site can measure, a campaign structure sized by the budget, ad copy traced to the post, tracking and click-by-click Campaign Manager steps.

Released
October 7, 2026
npx skills add timerise-ai/ad-campaign-runbook
v0.1.4
Current release
9
Reference docs
6
Non-negotiables
MIT
License

The problem

What problem does Ad campaign runbook solve?

A good blog post with a real offer in it deserves paid traffic. On LinkedIn the usual plan is a funnel: awareness, consideration, conversion, a campaign for each. At a small B2B budget that plan cannot run. The platform's daily minimum leaves money for one campaign, and a tag that records page views cannot report a conversion, however the plan words it.

So the plan has to start from the sums and from what the site can actually measure, not from the funnel someone would like to draw. Then the ads have to say only what the post says, and a marketer has to be able to run the campaign without the author in the room.

This skill gives an agent the runbook we write for every post we promote: it checks what the site measures, sizes the campaign to the budget, writes ads whose every sentence traces back to the post, and adds an organic companion post, tracking links, conversions and click-by-click Campaign Manager steps. It reads the ad account but changes nothing without a yes.

The tool

What does the skill do?

This skill adds no module to your app: your agent runs it as a tool. What Ad campaign runbook does:

  • 1. A probe of what the site actually measures
  • 2. A campaign structure sized by the budget and the platform minimum
  • 3. Ad copy traceable to the post
  • 4. An organic companion post with author-only slots
  • 5. UTMs, conversions and click-by-click Campaign Manager steps

Provenance

Where do the rules come from?

This skill was written by the engineer who has shipped this work. The earlier implementation it was audited against was a LinkedIn ads runbook for a B2B marketing site with consent-gated analytics and a sign-in wall between the ad click and the conversion. The procedure holds the properties a runbook has to hold: a campaign count that follows from the budget and the platform minimum, a dated record of what the site measures, every ad claim traceable to a sentence in the post, personal facts left as slots for the person whose name goes on them, an ad account the agent reads but never changes without a yes, and a finished file with no placeholder and no fact older than the day it was handed over. `references/provenance.md` has the record.

The engineering ledger for this skill: what the audit of the earlier implementation changed and how the procedure holds it, what was kept on purpose with the reason it is safe, and what was designed here and has never been run. It is written for the person editing the skill, not for the reader of the README. Read it before simplifying anything.

The ledger separates what the audit changed, what was kept on purpose, and what has not run in production yet.

  1. Fixed

    • A funnel the budget could not feed The first plan had four campaigns, two cold audiences, a sponsored founder post and retargeting, sized for several times the budget that existed. Each would have sat near the platform's daily minimum, where a campaign cannot bid its way to a judgeable sample. Held by: campaign count is arithmetic on the daily minimum, and the default is one post, one campaign. See strategy.md.
    • Tracking taken on trust The tag was installed, so conversions were taken to work. The probe found a base tag and nothing else: no conversion event anywhere, no UTM stored, tag and analytics both behind consent, and an auth redirect that rebuilt the URL before any page rendered. Held by: the probe is a mandatory step and its findings are a dated section of every runbook. See host-probe.md.
    • An ad blocker read as a site defect The tag reported an error and one request failed in about a millisecond, too fast for a network round trip. The cause was the tester's own ad blocker, confirmed when the ad platform's UI showed its warning banner and rendered blank pages. Held by: the failure mode table, and the rule that all ad account work happens in a browser profile without a blocker.
    • An organic post that read as a company pitch The first draft carried the link in the body, no named or dated moment, no number with a referent, three stacked lists of three, a close that pitched the link, and an instruction for colleagues to reshare at once. Held by: author slots the agent must not fill, the first-comment link rule, staggered comments in place of reshares, and an audit step before publication. See creative.md.
    • Hooks that spent the visible characters on nothing One ad opened on a quoted line of jargon, so the 140 characters a phone shows carried no reason to care. Another used a "not X, your Y" contrast frame in both intro and headline. Held by: the copy rules and the 140-character print check in the creative audit.
    Show 2 more
    • Facts that went stale inside one session The sections describing the ad account and the site's code aged as conversions were created and code shipped the same day, and the post's length was written from memory and was wrong by more than a tenth. Held by: the preflight reports measured facts, and the verification step rereads the runbook against them before it is handed over.
    • A page-load conversion id nearly used in a track call The account's only conversion was a URL rule, whose id an event-specific track call cannot use. Held by: the distinction, and the instruction to copy only the number an event-specific conversion issues, in conversion-tracking.md.
Read the full record in provenance.md

Non-negotiables

What are the 6 rules the module never breaks?

Every module built from this skill holds these, whoever builds it. The same list is in the skill's README and SKILL.md, so the agent reads it before it writes a line.

  1. Never run without the post file.

    Which content gets the budget is the user's decision. The preflight exits 2 on a missing, non-file or non-markdown argument, and the skill stops there and asks.

  2. Never write a claim the post does not make.

    Every ad sentence names the post sentence it comes from, and the post's own caveats bind the ads. The creative audit drops what has no source.

  3. Never invent a budget, a benchmark or a fact about the author.

    Budgets come from the user, planning numbers are labelled as assumptions until a post-mortem replaces them, personal facts stay as slots the author fills before publication, and an input nobody gave takes its documented default and is listed as open.

  4. Never assume tracking works.

    An installed tag records page views. The probe reads the code and one live page, dates its findings, and what is missing becomes a ticket rather than a promise.

  5. Never change the ad account without an explicit yes for that action.

    Reading a signed-in session is fine. Creating a conversion, audience or campaign accepts the advertising agreement on the user's behalf, so the skill fills the form, stops at the review step and shows what will be created.

  6. Never leave a placeholder or a stale fact in the finished runbook.

    The verification step greps for {{ and rereads the tracking, creative and build sections against what is true on the day it is handed over.

Fit

When should you use it, and when not?

Use it for

  • A post with a real offer in it should get paid LinkedIn traffic.
  • The host already has one campaign runbook and the next post needs the same.
  • Someone asks for ad copy, UTMs or Campaign Manager steps for a specific post.

Not for

  • Writing and publishing organic LinkedIn posts or commentsInsteadThe linkedin-marketing skill. This skill drafts one companion post and hands it to that skill's audit
  • Boosting a Company Page post (Engagement objective, link in the first comment)InsteadThe linkedin-boost skill
  • Writing the blog post itselfInsteadblog-markdown and the host's content workflow. A post with no offer in it is not a paid candidate
  • Meta, Google or X campaignsInsteadNot covered. The build steps are LinkedIn's, and another channel needs its own minimums, objectives and formats established first
  • Creating campaigns through an ads APIInsteadThis skill produces a document for a human to execute in Campaign Manager
  • Reporting on a campaign that has already runInsteadSection 9 of the template, the post-mortem, which feeds its actuals into the next runbook

Install

How do I install it?

One command. The skills.sh CLI installs the skill into every skills-compatible agent it finds.

$ npx skills add timerise-ai/ad-campaign-runbook

Claude Code

Invoke with /ad-campaign-runbook

Codex CLI

Invoke with $ad-campaign-runbook

Gemini CLI

Invoke with /skills

Name the agents instead with -a, for example npx skills add timerise-ai/ad-campaign-runbook -a claude-code -a codex. Or clone the repository into your agent's skills folder. Nothing in it is agent-specific.

What is inside the repository (17 entries)
  • SKILL.mdEntry point: the required input, architecture, eight critical facts, six hard rules, quick start, and the reference directory
  • references/adaptation.mdThe seam with the host app: what it must provide, the rename table, integration points, where the runbook lives, another channel
  • references/inputs.mdThe required post and the preflight, the inputs to ask for in one batch, and every placeholder in the template
  • references/host-probe.mdWhat the site can and cannot measure: tag, consent, conversion events, UTMs, redirects, CSP, the live check, failure modes, reading an ad account
  • references/strategy.mdBudget to structure, the budget bands, planning assumptions, audience, decision rules, cadence
  • references/creative.mdOffer, proof points, angles, the five ads and their copy rules, the organic companion post with author slots, the pre-publication audit
  • references/conversion-tracking.mdThe UTM convention, the conversions to create, the client-side event in TypeScript, the engineering tickets, reporting without UTM capture
  • references/campaign-manager.mdClick-by-click build: account preflight, conversions, audiences, campaign group, the campaign, pre-launch checklist, gotchas
  • references/runbook-template.mdThe document to produce, with fixed section numbers and every placeholder
  • references/provenance.mdThe engineering ledger: what the audit changed and how the procedure holds it, what was kept on purpose, what was added here
  • assets/preflight.pyStdlib Python: enforces the required post and reports the measured facts the runbook is built from. Exit 2 means stop
  • README.mdThis file
  • CHANGELOG.mdRelease history, newest first
  • CLAUDE.mdThe editing conventions, for an agent editing this repository
  • LICENSEMIT
  • evals/The prompts an operator types after installing (prompts.md) and one file per agent eval: the skill installed into an empty Next.js app, one prompt carrying the post, no help, then type-checked, built and tested
  • .github/workflows/agent-eval.ymlThe caller of the index's reusable eval workflow, run on every published release and on a maintainer's dispatch

Recent releases

  1. v0.1.4October 7, 2026

    A wording release, from scoring the prompt-1 agent eval runs of 0.1.3.

  2. v0.1.3October 7, 2026

    A fix release, from scoring the prompt-1 agent eval runs of 0.1.2.

  3. v0.1.2October 7, 2026

    A fix release, from scoring the prompt-1 agent eval runs of 0.1.1 against a fidelity rubric.

After installing

What do I tell my agent?

Say what you need in your own words; the skill supplies the how. These are starting points, and the ones we tested say how it went.

  1. Save the post below as content/blog/en/stop-confirming-bookings-by-phone.md, then write the LinkedIn ads runbook for it. We have 2,000 EUR a month, we sell to clinic and studio owners in Germany and Poland, and I will post the organic companion myself. --- title: Stop confirming bookings by phone date: 2026-09-01 author: Head of Product --- Most small clinics and studios still confirm every appointment by phone the day before. A receptionist works down a list, leaves voicemails, and marks the ones who answered. It feels like care. It is mostly lost time. [Try automatic confirmations free for 14 days](/signup). ## Where the first hour goes We looked at how front desks using our booking software spend the first hour of the day. The confirmation calls were the largest single block, larger than check-ins and larger than rescheduling. The calls also reached the fewest people: a client who books online rarely answers an unknown number at work. ## What we changed So we replaced the call with a message the client can answer in one tap. Two days before the visit they get a text and an email with three buttons: keep, move, or cancel. Keep does nothing. Move opens the calendar at the same service and the same staff member. Cancel frees the slot at once, and the waiting list gets the offer within a minute. Three things changed for the clinics that switched. The front desk got its first hour back. Cancellations arrived two days out instead of at the door, which is early enough to fill the slot. And the clients who never answered calls started answering, because a button is easier than a conversation. ## What it does not fix A client who has decided not to come will not tell you, whatever the channel. A deposit or a cancellation fee is the tool for that, and we do not think a reminder should pretend otherwise. If most of your no-shows come from new clients booking free first visits, start there. Setting it up takes about ten minutes. You choose when the message goes out, write the text in your own words, and decide whether a cancellation opens the slot to the waiting list or to everyone. Nothing changes for clients who prefer to call: the phone still works, it just stops being the only way. If your desk still starts the day with a call list, try it for two weeks and compare the first hours. [Start the free trial](/signup).

  2. Write LinkedIn ads for our latest blog post. We can spend about 1,500 EUR a month.

    No data store
  3. Here is a short post of ours; save it as content/blog/en/new-calendar-view.md and give me the LinkedIn ad copy and the Campaign Manager steps to promote it on 600 EUR a month. --- title: A new calendar view date: 2026-09-15 --- The calendar now has a week view for each staff member. Drag an appointment to move it, and the client gets a message with the new time. [See it in the demo](/demo).

    No data store

Tested

How does it do in each agent?

We install the skill into an empty Next.js app, give the agent one of the prompts above and no further help, then type-check, build and run the tests it left behind. Nothing is fixed by hand before the checks, and a failing run is published like a passing one. The procedure and every result are public, and the first prompt runs again before each release.

  • Gemini CLI0.63.0

    gemini-3.8-flash

    Built, checks pass
    Save the post below as content/blog/en/stop-confirming-bookings-by-phone.md, then write the LinkedIn ads runbook for it. We have 2,000 EUR a month, we sell to clinic and studio owners in Germany and Poland, and I will post the organic companion myself. --- title: Stop confirming bookings by phone date: 2026-09-01 author: Head of Product --- Most small clinics and studios still confirm every appointment by phone the day before. A receptionist works down a list, leaves voicemails, and marks the ones who answered. It feels like care. It is mostly lost time. [Try automatic confirmations free for 14 days](/signup). ## Where the first hour goes We looked at how front desks using our booking software spend the first hour of the day. The confirmation calls were the largest single block, larger than check-ins and larger than rescheduling. The calls also reached the fewest people: a client who books online rarely answers an unknown number at work. ## What we changed So we replaced the call with a message the client can answer in one tap. Two days before the visit they get a text and an email with three buttons: keep, move, or cancel. Keep does nothing. Move opens the calendar at the same service and the same staff member. Cancel frees the slot at once, and the waiting list gets the offer within a minute. Three things changed for the clinics that switched. The front desk got its first hour back. Cancellations arrived two days out instead of at the door, which is early enough to fill the slot. And the clients who never answered calls started answering, because a button is easier than a conversation. ## What it does not fix A client who has decided not to come will not tell you, whatever the channel. A deposit or a cancellation fee is the tool for that, and we do not think a reminder should pretend otherwise. If most of your no-shows come from new clients booking free first visits, start there. Setting it up takes about ten minutes. You choose when the message goes out, write the text in your own words, and decide whether a cancellation opens the slot to the waiting list or to everyone. Nothing changes for clients who prefer to call: the phone still works, it just stops being the only way. If your desk still starts the day with a call list, try it for two weeks and compare the first hours. [Start the free trial](/signup).
    Typecheck: passBuild: passTests: not run
    Time
    6 min
    Changed
    6 files, +685 lines
    Stack
    No data store
    Skill
    v0.1.4
    Run
    Oct 7, 2026

    Result fileAgent log

    What we saw

    Rubric 8/8, scored from the final summary. There are two campaigns, with ads SI-01 to SI-05 and RT-01 to RT-02. Retargeting uses utm_campaign=retargeting and utm_content=rt-01. The split is 66 EUR a day to the post campaign until the audience reaches 300, then 41 and 25. URLs are paths, the live check is recorded as not done with ticket T7, and the baseline is counted by hand. The handover ends with a list headed "Open inputs", one line per input. The post-mortem file it created up front is an extra that is not scored.

  • Codex CLIcodex-cli 0.161.0

    gpt-6.1-sol

    Built, checks pass
    Save the post below as content/blog/en/stop-confirming-bookings-by-phone.md, then write the LinkedIn ads runbook for it. We have 2,000 EUR a month, we sell to clinic and studio owners in Germany and Poland, and I will post the organic companion myself. --- title: Stop confirming bookings by phone date: 2026-09-01 author: Head of Product --- Most small clinics and studios still confirm every appointment by phone the day before. A receptionist works down a list, leaves voicemails, and marks the ones who answered. It feels like care. It is mostly lost time. [Try automatic confirmations free for 14 days](/signup). ## Where the first hour goes We looked at how front desks using our booking software spend the first hour of the day. The confirmation calls were the largest single block, larger than check-ins and larger than rescheduling. The calls also reached the fewest people: a client who books online rarely answers an unknown number at work. ## What we changed So we replaced the call with a message the client can answer in one tap. Two days before the visit they get a text and an email with three buttons: keep, move, or cancel. Keep does nothing. Move opens the calendar at the same service and the same staff member. Cancel frees the slot at once, and the waiting list gets the offer within a minute. Three things changed for the clinics that switched. The front desk got its first hour back. Cancellations arrived two days out instead of at the door, which is early enough to fill the slot. And the clients who never answered calls started answering, because a button is easier than a conversation. ## What it does not fix A client who has decided not to come will not tell you, whatever the channel. A deposit or a cancellation fee is the tool for that, and we do not think a reminder should pretend otherwise. If most of your no-shows come from new clients booking free first visits, start there. Setting it up takes about ten minutes. You choose when the message goes out, write the text in your own words, and decide whether a cancellation opens the slot to the waiting list or to everyone. Nothing changes for clients who prefer to call: the phone still works, it just stops being the only way. If your desk still starts the day with a call list, try it for two weeks and compare the first hours. [Start the free trial](/signup).
    Typecheck: passBuild: passTests: not run
    Time
    3 min
    Changed
    5 files, +438 lines
    Stack
    No data store
    Skill
    v0.1.4
    Run
    Oct 7, 2026

    Result fileAgent log

    What we saw

    Rubric 8/8, scored from the transcript (gpt-6.1-sol, reasoning effort none). The handover now ends with a list headed "Open inputs / assumptions", one line per input, after what blocks launch, the live check, the author slots and the 0 to 6 range. Nothing has regressed. There are two campaigns: retargeting is built paused, then 31 EUR a day with 35 for the post campaign once past 300. The ads are named SI-01 and RT-01, with utm_campaign=retargeting and utm_content=rt-01. URLs are paths, the index entry is present, the preflight ran with --cta, and no test script was added.

  • Claude Code2.1.293

    claude-opus-5-5

    Built, checks pass
    Save the post below as content/blog/en/stop-confirming-bookings-by-phone.md, then write the LinkedIn ads runbook for it. We have 2,000 EUR a month, we sell to clinic and studio owners in Germany and Poland, and I will post the organic companion myself. --- title: Stop confirming bookings by phone date: 2026-09-01 author: Head of Product --- Most small clinics and studios still confirm every appointment by phone the day before. A receptionist works down a list, leaves voicemails, and marks the ones who answered. It feels like care. It is mostly lost time. [Try automatic confirmations free for 14 days](/signup). ## Where the first hour goes We looked at how front desks using our booking software spend the first hour of the day. The confirmation calls were the largest single block, larger than check-ins and larger than rescheduling. The calls also reached the fewest people: a client who books online rarely answers an unknown number at work. ## What we changed So we replaced the call with a message the client can answer in one tap. Two days before the visit they get a text and an email with three buttons: keep, move, or cancel. Keep does nothing. Move opens the calendar at the same service and the same staff member. Cancel frees the slot at once, and the waiting list gets the offer within a minute. Three things changed for the clinics that switched. The front desk got its first hour back. Cancellations arrived two days out instead of at the door, which is early enough to fill the slot. And the clients who never answered calls started answering, because a button is easier than a conversation. ## What it does not fix A client who has decided not to come will not tell you, whatever the channel. A deposit or a cancellation fee is the tool for that, and we do not think a reminder should pretend otherwise. If most of your no-shows come from new clients booking free first visits, start there. Setting it up takes about ten minutes. You choose when the message goes out, write the text in your own words, and decide whether a cancellation opens the slot to the waiting list or to everyone. Nothing changes for clients who prefer to call: the phone still works, it just stops being the only way. If your desk still starts the day with a call list, try it for two weeks and compare the first hours. [Start the free trial](/signup).
    Typecheck: passBuild: passTests: not run
    Time
    5 min
    Changed
    3 files, +603 lines
    Stack
    No data store
    Skill
    v0.1.4
    Run
    Oct 7, 2026

    Result fileAgent log

    What we saw

    Rubric 8/8, scored from the final summary, which quotes what earlier summaries left as doubt. There are two campaigns, with ads SI-01 to SI-05 and RT-01 to RT-02, and the UTMs are utm_campaign=post-confirming-bookings&utm_content=si-01 and utm_campaign=retargeting&utm_content=rt-01. Retargeting is built and left off until the first Monday check past 300 members. Then it gets 25 EUR a day and the post campaign 40. URLs are paths, the live check is a ticket, the baseline is counted by hand, and nothing was wired into npm test. The final message ends with a list of the assumed and open inputs, one line each.

Generated from the skill's own files at commit f2b0337. Every rule above links to where the repository says it. All skills