Universal Campaign Architecture property-agnostic master template
01 TEMPLATE 02 CONFIG/API OS 03 CREATIVE BOARD
U-00 · Template
Variable Registry
Every {{PLACEHOLDER}} in this template resolves here. The instruction column tells you exactly what belongs in the slot; the example column shows the Smithville instance. Fill a value and toggle “View: Filled” — every schema in every module renders with it.
IDENTITY
VARIABLE
INSTRUCTION — what goes in this slot
YOUR VALUE (example shown as ghost)
{{PROPERTY_NAME}}
Marketing name of the asset exactly as it appears on the flyer.
{{PROPERTY_CODE}}
3–5 char code. Prefixes every campaign, segment, UTM, and file name. Never change mid-flight.
{{ADDRESS}}
Street address / range.
{{CITY_STATE_ZIP}}
City, ST ZIP.
{{CORRIDOR}}
The artery you sell. Appears in headlines.
{{METRO_GEO}}
Geo the targeting actually uses (metro, not the small town — audience floor is 300, recommended 50K+).
{{TOTAL_SF}}
Total center SF with (±) if flyer says so.
{{AVAILABLE_SF_TOTAL}}
Sum of available SF only.
{{DELIVERY_TIMEFRAME}}
ONLY a verified date. If the source contradicts itself, use the safest broad claim and register an open item.
{{CONDITION_CLAIM}}
The one true renovation/condition sentence, verified against the flyer.
{{CO_TENANCY_LIST}}
Anchor names, comma-separated, exactly as brandable in ads (no logos without permission).
{{TERMINAL_METRIC}}
The single number the whole campaign answers to.
MARKET
VARIABLE
INSTRUCTION — what goes in this slot
YOUR VALUE (example shown as ghost)
{{RADIUS_A}}
Inner demographic radius label.
{{POP_A}}
Population inside RADIUS_A (cite source + year internally).
{{HHI_A}}
Avg household income inside RADIUS_A.
{{RADIUS_B}}
Primary trade-area radius used in most ads.
{{POP_B}}
Population inside RADIUS_B.
{{HHI_B}}
Avg household income inside RADIUS_B — usually your strongest stat.
{{HOME_VALUE}}
Avg home value (wealth proxy for professional-services ads).
TEAM
VARIABLE
INSTRUCTION — what goes in this slot
YOUR VALUE (example shown as ghost)
{{BROKER_1_NAME}}
Lead broker full name + designation.
{{BROKER_1_TITLE}}
Title as licensed.
{{BROKER_2_NAME}}
Second broker — the Thought Leader Ads author.
{{BROKER_2_TITLE}}
Title.
{{BROKERAGE_NAME}}
Brokerage of record + affiliation.
{{BROKERAGE_PHONE}}
Office line on every ad that allows it.
{{SITE_BASE_URL}}
Root of the property microsite. All landing URLs derive from it.
SPACES
VARIABLE
INSTRUCTION — what goes in this slot
YOUR VALUE (example shown as ghost)
{{SPACE_1_LABEL}}
Smallest space label.
{{SPACE_1_SF}}
SF.
{{SPACE_1_USE}}
Primary use thesis — drives which segments target it.
{{SPACE_2_LABEL}}
As labeled.
{{SPACE_2_SF}}
As labeled.
{{SPACE_2_USE}}
As labeled.
{{SPACE_3_LABEL}}
As labeled.
{{SPACE_3_SF}}
As labeled.
{{SPACE_3_USE}}
As labeled.
{{SPACE_4_LABEL}}
Marquee space.
{{SPACE_4_SF}}
As labeled.
{{SPACE_4_USE}}
As labeled.
SEGMENTS
VARIABLE
INSTRUCTION — what goes in this slot
YOUR VALUE (example shown as ghost)
{{SEG_A_NAME}}
Priority-1 audience. Highest rent tolerance first.
{{SEG_B_NAME}}
As labeled.
{{SEG_C_NAME}}
As labeled.
{{SEG_D_NAME}}
As labeled.
{{SEG_E_NAME}}
As labeled.
{{SEG_F_NAME}}
The amplifier segment — brokers. Compressed 3-stage funnel.
{{SEG_G_NAME}}
As labeled.
BUDGET
VARIABLE
INSTRUCTION — what goes in this slot
YOUR VALUE (example shown as ghost)
{{TOTAL_BUDGET}}
Campaign-group totalBudget.amount (USD).
{{DAILY_AWARENESS}}
dailyBudget for stage 00–03 video campaigns.
{{DAILY_CONVERSION}}
dailyBudget for stage 04 lead-gen campaigns.
{{FLIGHT_START}}
ISO date the group runSchedule.start converts from.
{{FLIGHT_WEEKS}}
Planned flight length. Drives the cadence view.
API
VARIABLE
INSTRUCTION — what goes in this slot
YOUR VALUE (example shown as ghost)
{{AD_ACCOUNT_ID}}
Numeric sponsoredAccount id.
{{ORG_ID}}
Numeric organization (Page) id — the dark-post author.
{{LI_VERSION}}
LinkedIn-Version header. Bump monthly.
{{PARTNER_ID}}
Insight Tag partner id.
TRACKING
VARIABLE
INSTRUCTION — what goes in this slot
YOUR VALUE (example shown as ghost)
{{UTM_SOURCE}}
Fixed.
{{UTM_MEDIUM}}
Fixed.
{{PRIMARY_CONVERSION}}
conversions.type for the terminal action. LEAD supports a 365-day window — use it for CRE.
{{CDP_HOST}}
Server-side CDP endpoint (Surfside / Segment-spec) receiving track() calls.
{{GA4_MEASUREMENT_ID}}
GA4 property for Measurement Protocol events.
{{CALL_TRACKING_NUMBER}}
Tracked line that attributes inbound calls to the campaign.
{{SCORE_ROUTE_THRESHOLD}}
Engagement score at which a prospect routes to a broker, with the SLA.
LEGAL
VARIABLE
INSTRUCTION — what goes in this slot
YOUR VALUE (example shown as ghost)
{{RATE_LANGUAGE}}
What you may say about rent. If no published rate: exactly this.
{{DISCLAIMER}}
Verbatim broker disclaimer required on gated collateral.
{{PROHIBITED_CLAIMS}}
Claims never allowed in any creative for this asset (unverified specs, zoning, traffic counts…).
PROSPECT
VARIABLE
INSTRUCTION — what goes in this slot
YOUR VALUE (example shown as ghost)
{{VERIFICATION_POLICY}}
When scraped data may be used. State the handoff rule verbatim.
{{TYPE_TAGS}}
The prospect-type taxonomy for this asset class.
COMPETITOR
VARIABLE
INSTRUCTION — what goes in this slot
YOUR VALUE (example shown as ghost)
{{COMP_SEARCH_KEYWORDS}}
Ad Library search strings monitored weekly (no official API — manual/scraper).
{{PRICE_COMPETITOR_PATTERN}}
The price-led rival you refuse to race, and the identity counter.
{{PROOF_ASSETS}}
The proof that beats competitor promises (photos, commitments, dates).
FEED
VARIABLE
INSTRUCTION — what goes in this slot
YOUR VALUE (example shown as ghost)
{{AUTOPILOT_DEFAULT}}
Whether due actions fire without a human. Approval classes always hold.
{{APPROVAL_CLASSES}}
Action classes that never auto-run.
{{FEED_HORIZON_DAYS}}
How far ahead the action queue schedules.
Registry contract: variables are UPPER_SNAKE inside double braces. A template ships with zero resolved variables; an instance (like the Smithville OS) is this template with every slot resolved and the {RESOLVE:} URN tokens swapped for real URNs.
U-01 · Template
Naming System
One grammar across the API, analytics, files, and CRM. If a name can’t be parsed back into property / segment / stage / format by a script, it’s wrong.

Entity name patterns

campaign group {{PROPERTY_CODE}} | {{PROPERTY_NAME}} | Pre-Leasing {{DELIVERY_TIMEFRAME}} campaign {{PROPERTY_CODE}}|{SEG}|{STAGE_ID}-{STAGE_KEY}|{FMT} e.g. {{PROPERTY_CODE}}|A|03-PRODUCT|VID creative (name) {{PROPERTY_CODE}}_{SEG}_{STAGE_ID}_{FMT}_{VARIANT} e.g. {{PROPERTY_CODE}}_A_03_IMG_dentist-suite600-v2 dmp segment {{PROPERTY_CODE}}_{SEG|ALL}_{SIGNAL}_{LOOKBACK} e.g. {{PROPERTY_CODE}}_A_VID_MIDPOINT_90D conversion rule {{PROPERTY_CODE}} {action} ({{PRIMARY_CONVERSION}}) utm_campaign {{PROPERTY_CODE|lowercase}}_{seg}_{stage} utm_id {{PROPERTY_CODE|lowercase}}_{seg}_{stage}_{variant} ← the join key across LinkedIn ↔ GA4 ↔ CRM asset file {{PROPERTY_CODE}}_{SEG}_{STAGE_ID}_{FMT}_{WxH}_{v#}.{ext}

Grammar tokens

{SEG}
A–G single letter. A={{SEG_A_NAME}} … G={{SEG_G_NAME}}
{STAGE_ID}-{STAGE_KEY}
00-UNAWARE · 01-PROBLEM · 02-SOLUTION · 03-PRODUCT · 04-CONVERSION · 05-NURTURE · 06-LOYALTY
{FMT}
VID · IMG · CAR · DOC · TXT · SPT · CNV · TLA · EVT
{SIGNAL}
VID_FIRSTQ / VID_MIDPOINT / VID_THIRDQ / VID_FULL · IMG_CLICK · LGF_OPEN / LGF_SUBMIT · SITE · PAGE_VIEW · ABM
{LOOKBACK}
30D / 60D / 90D / 180D / 365D — engagement max 365, website segments never expire
U-02 · Template
Campaign Schemas
The property-agnostic object tree: one group per property, one campaign per segment × stage. Payloads are exact API shapes with template slots; instructions ride on every placeholder (hover).

adCampaignGroups — POST /rest/adAccounts/{{AD_ACCOUNT_ID}}/adCampaignGroups

{ "account": "urn:li:sponsoredAccount:{{AD_ACCOUNT_ID}}", "name": "{{PROPERTY_CODE}} | {{PROPERTY_NAME}} | Pre-Leasing {{DELIVERY_TIMEFRAME}}", "status": "DRAFT", "runSchedule": { "start": /* epoch ms of {{FLIGHT_START}} */ 0 }, "totalBudget": { "amount": "{{TOTAL_BUDGET}}", "currencyCode": "USD" } }

adCampaigns — one per segment × stage

{ "account": "urn:li:sponsoredAccount:{{AD_ACCOUNT_ID}}", "campaignGroup": "urn:li:sponsoredCampaignGroup:{CG_ID from x-restli-id}", "name": "{{PROPERTY_CODE}}|{SEG}|{STAGE_ID}-{STAGE_KEY}|{FMT}", "type": "SPONSORED_UPDATES", "format": "{stage table below}", "objectiveType": "{stage table below}", "optimizationTargetType": "{stage table below}", "costType": "{stage table below}", "dailyBudget": { "amount": "{{DAILY_AWARENESS}} | {{DAILY_CONVERSION}}", "currencyCode": "USD" }, "creativeSelection": "OPTIMIZED", /* 3–5 creatives rotate INSIDE the campaign — this is where niche messaging lives */ "audienceExpansionEnabled": false, "offsiteDeliveryEnabled": false, /* must be false for LEAD_GENERATION */ "locale": { "country": "US", "language": "en" }, "runSchedule": { "start": 0 }, "status": "DRAFT", "targetingCriteria": { /* U-04 */ } }

Stage matrix — objective, optimization, format, audience source, message job

stageobjectiveTypeoptimizationcostTypeformataudience sourcemessage job
00 UNAWAREVIDEO_VIEWMAX_VIDEO_VIEWCPVSINGLE_VIDEOCold {SEG} audience, {{METRO_GEO}}15s pattern-break video; no ask
01 PROBLEMVIDEO_VIEWMAX_VIDEO_VIEWCPVSINGLE_VIDEO≥25% viewers of 00 (VID_FIRSTQ segment)Name the site-selection problem
02 SOLUTIONVIDEO_VIEWMAX_VIDEO_VIEWCPVSINGLE_VIDEO≥50% viewers of 01 (VID_MIDPOINT)Corridor + co-tenancy case
03 PRODUCTENGAGEMENTMAX_CLICKCPCSTANDARD_UPDATE / CAROUSEL / DOCUMENT≥50% of 02 + site retargetThe spaces themselves — {{SPACE_1_LABEL}}{{SPACE_4_LABEL}}
04 CONVERSIONLEAD_GENERATIONMAX_LEADCPMSTANDARD_UPDATE + Lead Gen Form / CONVERSATION_ADEngagers of 03 + LGF_OPEN + high-intent pagesTour request. One field past name/email max
05 NURTUREENGAGEMENTMAX_CLICKCPCDOCUMENT / EVENTLeads not yet toured (CRM list, streamed)Proof: leasing momentum, delivery progress
06 LOYALTYENGAGEMENTMAX_CLICKCPCTLA / ORGANICSigned tenants + their networksAnnouncement posts; referral loop
Segment F (brokers) compresses to 02 → 03 → 04: they don’t need problem education — lead with the {{PROPERTY_CODE}} document ad and co-brokerage terms.
Hyper-segmentation rule baked into this template: split campaigns by SEGMENT, never by sub-specialty. Sub-specialty messaging = a creative variant inside the segment campaign (creativeSelection OPTIMIZED) + warm retargeting. Only promote a sub-audience to its own campaign when it independently clears ~10,000 metro-wide.
U-03 · Template
Creative Templates
Each format = a content contract: the API payload shape, the hard character limits, and per-slot instructions for what the copy must do. The visual layer for these slots lives in the Creative Board file.
SINGLE IMAGE — dark post via creatives?action=createInlinecommentary ≤600 (150 shown) · headline ≤200 (70 shown)
slotinstruction — what content goes here
{{IMG_COMMENTARY}}Lead with the segment’s strongest verified stat ({{HHI_B}} income / {{POP_B}} within {{RADIUS_B}}) in the first 150 chars, then the inventory fact. Never {{PROHIBITED_CLAIMS}}. Rate language: {{RATE_LANGUAGE}}.
{{IMG_HEADLINE}}Use-case + corridor + timeframe. Pattern: “{use}-Ready Space on {{CORRIDOR}} | {{DELIVERY_TIMEFRAME}}”. First 70 chars carry it.
{{IMG_ALT}}Literal description of the graphic for accessibility.
{ "creative": { "campaign": "urn:li:sponsoredCampaign:{ID}", "intendedStatus": "DRAFT", "inlineContent": { "post": { "author": "urn:li:organization:{{ORG_ID}}", "commentary": "{{IMG_COMMENTARY}}", "distribution": { "feedDistribution": "NONE" }, /* dark post */ "content": { "media": { "id": "urn:li:image:{ID}", "title": "{{IMG_HEADLINE}}", "altText": "{{IMG_ALT}}" }, "landingPage": { "url": "{{SITE_BASE_URL}}/{space-slug}?{utm}" } }, "lifecycleState": "PUBLISHED", "adContext": { "dscAdAccount": "urn:li:sponsoredAccount:{{AD_ACCOUNT_ID}}", "dscStatus": "ACTIVE" } } } } }
VIDEO — stages 00–0315–30s · captions mandatory (85% watch muted) · thumb 1:1 or 16:9
slotinstruction — what content goes here
{{VID_HOOK_0_3S}}Frame 1 must work silent + thumb-stopped: the property’s single most surprising verified number over motion.
{{VID_BODY_4_12S}}Stage job from U-02 matrix. 00: pattern break. 01: name the problem. 02: corridor proof. 03: walk the actual spaces.
{{VID_CTA_LAST_3S}}Stage 00–02: none (view-optimized). Stage 03: “See the plan” → {{SITE_BASE_URL}}.
{ "content": { "media": { "id": "urn:li:video:{ID}", "title": "{{VID_HEADLINE}}" } } } /* upload: POST /rest/videos?action=initializeUpload → uploadUrl → PUT bytes → urn:li:video:{ID} */
CAROUSEL — stage 03 inventory walkintro ≤255 · card headline ≤45 · 2–10 cards
slotinstruction — what content goes here
{{CARD_1_HEADLINE}}Card 1 = the property at a glance: {{PROPERTY_NAME}} | {{CORRIDOR}}.
{{CARD_N_HEADLINE}}One card per space: {label} | {SF} | {use}. Deep-link each card to its own space page — carousel cards are your only per-space link targets in one ad.
{ "content": { "carousel": { "cards": [ { "media": { "id": "urn:li:image:{ID}", "title": "{{CARD_1_HEADLINE}}" }, "landingPage": { "url": "{{SITE_BASE_URL}}?{utm}" } }, { "media": { "id": "urn:li:image:{ID}", "title": "{{CARD_N_HEADLINE}}" }, "landingPage": { "url": "{{SITE_BASE_URL}}/{space-slug}?{utm}" } } ] } } }
DOCUMENT — the flyer as a lead magnet (Segment F opener)commentary ≤600 · PDF ≤300 pages/100MB · gate with Lead Gen Form
slotinstruction — what content goes here
{{DOC_TITLE}}{{PROPERTY_NAME}} | Complete Leasing Package | {{CORRIDOR}}” — brokers search by corridor.
{{DOC_COMMENTARY}}Inventory line ({N} spaces, {min}{max} SF), condition claim, co-brokerage welcome. No teaser withholding — brokers bounce off gated fluff; the gate is the form, the doc must be the full package.
{ "creative": { "campaign": "urn:li:sponsoredCampaign:{ID}", "inlineContent": { "post": { … "content": { "media": { "id": "urn:li:document:{ID}", "title": "{{DOC_TITLE}}" } }} }, "leadgenCallToAction": { "adForm": "urn:li:adForm:{FORM_ID}", "label": "DOWNLOAD" } } }
THOUGHT LEADER AD — broker’s own post, sponsoredauthor approval required in Campaign Manager → Partnerships · objective BRAND_AWARENESS or ENGAGEMENT only
slotinstruction — what content goes here
{{TLA_POST_BODY}}Written in {{BROKER_2_NAME}}’s first person. Walk-the-property narrative: co-tenancy list, the four spaces, the two strongest stats, “happy to walk it with anyone”. Zero ad-speak — it must read like a post, because it is one. Benchmark: TLAs run ~2.68% median CTR vs 0.42% single-image.
{ "creative": { "campaign": "urn:li:sponsoredCampaign:{ID}", "content": { "reference": "urn:li:ugcPost:{MEMBER_POST_ID}" } } }
CONVERSATION AD — stage 04 warm onlyintro ≤500 · buttons ≤25 chars, max 5 · excl. EU members
slotinstruction — what content goes here
{{CNV_INTRO}}From {{BROKER_2_NAME}}. One sentence of context, one inventory line, then the question “What’s the right fit?”
{{CNV_BUTTONS}}One button per space, labeled by SF ({{SPACE_1_SF}} SF … {{SPACE_4_SF}} SF) + “Just send the flyer”. Every button deep-links its space page with utm.
{ "content": { "reference": "urn:li:sponsoredConversation:{ID}" } } /* build messages+buttons in the Sponsored Messaging flow, then reference */

Lead Gen Form template — /rest/leadForms

{ "owner": { "sponsoredAccount": "urn:li:sponsoredAccount:{{AD_ACCOUNT_ID}}" }, "name": "{{PROPERTY_CODE}} Tour Request", "content": { "headline": "{{LGF_HEADLINE}}", /* ≤ what fits: verify limit in Campaign Manager */ "description": "{{LGF_DESC}}", "questions": [ FIRST_NAME, LAST_NAME, WORK_EMAIL, PHONE_NUMBER, COMPANY_NAME, { custom multiple-choice: "Which space?" → {{SPACE_1_LABEL}}  {{SPACE_4_LABEL}} } ], "legalInfo": { "privacyPolicyUrl": "{{SITE_BASE_URL}}/privacy", "legalDisclaimer": "{{DISCLAIMER}}" }, "postSubmissionInfo": { "message": "{{LGF_THANKYOU}}", "callToAction": { "callToActionLabel": "VISIT_COMPANY_WEBSITE", "callToActionTarget": "{{SITE_BASE_URL}}?{utm}" } }, "hiddenFields": [ { "name": "utm_id", "value": "{{DYNAMIC_VALUE}}" } ] } }
Rule: every custom question past name/email/company costs completion rate. One qualifying question max at stage 04.
U-04 · Template
Targeting Templates
targetingCriteria per segment archetype. {RESOLVE:} tokens mark URNs you look up via adTargetingEntities typeahead per market — a template never ships resolved URNs because geo and entity ids are market-specific.

Cold-stage archetype (00–02)

{ "include": { "and": [ { "or": { "urn:li:adTargetingFacet:locations": [ "{RESOLVE:geo:{{METRO_GEO}}}" ] } }, /* metro — never the small town alone */ { "or": { "urn:li:adTargetingFacet:{PRIMARY_FACET}": [ "{RESOLVE:…}" ] } }, /* per segment: function OR industry OR skills */ { "or": { "urn:li:adTargetingFacet:staffCountRanges": [ "urn:li:staffCountRange:(2,10)", "urn:li:staffCountRange:(11,50)" ] } } ] }, "exclude": { "or": { "urn:li:adTargetingFacet:employers": [ "{RESOLVE:employer:{{BROKERAGE_NAME}}}" ] } } }
segmentprimary facet strategy
A · {{SEG_A_NAME}}jobFunctions: Healthcare Services + staffCountRanges 2–200. Sub-specialty (dentist vs orthodontist) does NOT exist as industry/function — it lives in creative copy + title-level warm retargeting only.
B · {{SEG_B_NAME}}industries: Restaurants AND skills: Site Selection / Franchise Development.
C · {{SEG_C_NAME}}industries: Health, Wellness & Fitness AND skills: Franchising.
D · {{SEG_D_NAME}}industries: Restaurants AND seniorities: Owner/Partner/Director.
E · {{SEG_E_NAME}}industries: Financial Services / Insurance / Law AND seniorities Owner/Partner.
F · {{SEG_F_NAME}}skills: Tenant Representation / Site Selection AND industries: Real Estate. Layer ABM company list.
G · {{SEG_G_NAME}}industries: Retail / Veterinary AND seniorities Owner.

Warm-stage archetype (01–04) — audience swap, same shell

{ "include": { "and": [ { "or": { "urn:li:adTargetingFacet:locations": [ "{RESOLVE:geo:{{METRO_GEO}}}" ] } }, { "or": { "urn:li:adTargetingFacet:dynamicSegments": [ "urn:li:adSegment:{ENGAGEMENT_SEGMENT_ID}" ] } } ] } } /* stage 04 adds audienceMatchingSegments for CRM lists. Small is fine here: intent compensates. */

Boolean rules the API enforces (violations = 400 or silent under-delivery)

• titles ✗ AND seniorities / jobFunctions (include)   • employers ✗ AND industries / staffCountRanges   • memberBehaviors ✗ AND contact-list segments or website retargeting   • ageRanges / genders / groups: include-only   • Preflight every campaign: GET /rest/audienceCounts — floor 300, launch floor for this system 5,000.
U-05 · Template
Journey & Audience System
The engagement ladder that moves a stranger to a tour. Each rung is a dmpSegment with an engagementRule; the CRM streams ADD/REMOVE as contacts progress or stall.

The ladder

00→01 {{PROPERTY_CODE}}_{SEG}_VID_FIRSTQ_90D trigger FIRST_QUARTILE (≥25% of stage-00 video) 01→02 {{PROPERTY_CODE}}_{SEG}_VID_MIDPOINT_90D trigger MIDPOINT (≥50% of stage-01) 02→03 {{PROPERTY_CODE}}_{SEG}_VID_THIRDQ_90D trigger THIRD_QUARTILE (≥75%) + SITE visitors 03→04 {{PROPERTY_CODE}}_ALL_IMG_CLICK_90D + LGF_OPEN_90D + {space-page} PAGE_VIEW 04→05 CRM list {{PROPERTY_CODE}}_STAGE_LEAD_OPEN (streamed, SHA256_EMAIL) 05→06 CRM list {{PROPERTY_CODE}}_STAGE_TENANT (signed — exit all paid except 06)
Gate: a stage’s campaign activates only when its source segment reports ≥300 matched members (≤48h build + 24h to serve). Until then the stage above keeps spending.

Stage transition — the two-call pattern

POST /rest/dmpSegments/{NEXT_STAGE_SEGMENT}/users X-RestLi-Method: BATCH_CREATE { "elements": [ { "action": "ADD", "userIds": [ { "idType": "SHA256_EMAIL", "idValue": "{sha256(lower(trim(email)))}" } ] } ] } POST /rest/dmpSegments/{PRIOR_STAGE_SEGMENT}/users X-RestLi-Method: BATCH_CREATE { "elements": [ { "action": "REMOVE", "userIds": [ { "idType": "SHA256_EMAIL", "idValue": "{same hash}" } ] } ] }
Disengagement is the same pattern in reverse: no engagement in {{DISENGAGE_DAYS → default 45}} days ⇒ REMOVE from current stage, ADD back one stage. LIST_UPLOAD segments can’t be streamed — journey tags must be USER-type segments.
Where niche messaging lives: warm rungs. A “dentist” creative against {{PROPERTY_CODE}}_A_VID_MIDPOINT is the right-sized use of hyper-specific copy — the audience earned it by watching, so 300–900 members is enough.
U-06 · Template
Tracking & UTM Architecture
One join key end to end: utm_id. LinkedIn is the media truth, GA4 the behavior truth, the CRM the revenue truth — reconciled on utm_id + li_fat_id, never expected to match counts.

UTM grammar

utm_source = {{UTM_SOURCE}} utm_medium = {{UTM_MEDIUM}} utm_campaign = {{PROPERTY_CODE|lower}}_{seg}_{stage} utm_content = {creative-variant} /* the sub-specialty message label lives HERE */ utm_id = {{PROPERTY_CODE|lower}}_{seg}_{stage}_{variant} {{SITE_BASE_URL}}/{space-slug}?utm_source={{UTM_SOURCE}}&utm_medium={{UTM_MEDIUM}}&utm_campaign=…&utm_content=…&utm_id=…

Conversion rules — /rest/conversions

{ "name": "{{PROPERTY_CODE}} Tour Request ({{PRIMARY_CONVERSION}})", "account": "urn:li:sponsoredAccount:{{AD_ACCOUNT_ID}}", "conversionMethod": "CONVERSIONS_API", "type": "{{PRIMARY_CONVERSION}}", /* LEAD → 365-day post-click window available */ "attributionType": "LAST_TOUCH_BY_CAMPAIGN", "postClickAttributionWindowSize": 90, "viewThroughAttributionWindowSize": 7 } /* + PIXEL rule: KEY_PAGE_VIEW on {space-slug} pages via Insight Tag {{PARTNER_ID}} */

li_fat_id loop (offline attribution)

1. Enhanced conversion tracking ON → LinkedIn appends ?li_fat_id= to {{SITE_BASE_URL}} clicks 2. Landing page stores it (cookie/localStorage) → CRM saves it on the lead 3. Weeks later, LOI signs → POST /rest/conversionEvents: { "conversion": "urn:lla:llaPartnerConversion:{ID}", "conversionHappenedAt": {epoch ms, ≤90d}, "conversionValue": { "currencyCode": "USD", "amount": "{annualized lease value or 0}" }, "eventId": "{unique — dedup vs Insight Tag}", "user": { "userIds": [ { "idType": "LINKEDIN_FIRST_PARTY_ADS_TRACKING_UUID", "idValue": "{li_fat_id}" }, { "idType": "SHA256_EMAIL", "idValue": "{hash}" } ] } }
U-07 · Template
Flight Cadence
A {{FLIGHT_WEEKS}}-week rhythm that any property inherits. Weeks are relative to {{FLIGHT_START}}.

Standing rhythm

whenactionmodule
Week 0Insight Tag live · conversions created · segments created (empty) · group + campaigns in DRAFT · audienceCounts preflight all — kill anything <5,000U-02/04/06
Week 1Launch: document ad ({SEG F}) + Thought Leader posts sponsored + stage-00 videosU-03
Week 2Single-image variants live (3–5 per campaign, OPTIMIZED rotation)U-03
Week 3–4First ladder gates: activate stage 01 wherever VID_FIRSTQ ≥300U-05
Every 7dadAnalytics pull, CREATIVE + MEMBER_COMPANY pivots → CRM enrichmentinstance OS
Every 14dFatigue pass: pause creative when frequency >3.5/wk AND CTR −15% vs 7-day baselineinstance OS
Every 21–28dCreative refresh: new variant per active campaign; retire the loser, never the whole set at onceU-03
MonthlyBump LinkedIn-Version ({{LI_VERSION}} → next) · competitor Ad Library sweep → gap gridinstance OS
On LOISuite → LOI on the plate · pause its campaigns · CAPI event with lease value · move contact to 05instance OS
Template completion check: registry 100% filled · every {RESOLVE:} URN swapped · audienceCounts ≥5,000 per cold campaign · privacy URL live · disclaimer on gated collateral · prohibited-claims list reviewed against every creative. Then this file’s values export into the instance OS.
U-08 · Template
Prospect Record Schema
One record per human. Card header (name / email / phone / address), unlimited contact points with a verification state machine, a tag taxonomy, linked people who each get their own record, and five tabs: Context, Profile, Tracking, Bio, Next Best Action.

Contact points — verification state machine

emails[] / phones[] / addresses[] { label, value, st: SCRAPED | UNVERIFIED | VERIFIED, at: date } RULES 1. Anything imported → SCRAPED. 2. Verify = format check + human confirmation → VERIFIED + datestamp. 3. Any edit to a VERIFIED value → auto-reverts to UNVERIFIED. 4. {{VERIFICATION_POLICY}}

Tags & connections

tags: { type: [{{TYPE_TAGS}}], journey: 00–06 (mirrors DMP stage segments), custom: [] } connections[]: { contactId → their own full record, relation: Spouse | Business Partner | Attorney | Broker… } Every decision-toucher gets a record — deals are signed by households and partnerships, not individuals.

Tracking tab (server-side, consent-gated)

IDENTITY KEYS (the join) SHA256_EMAIL · li_fat_id · GA4 client_id · tracked phone · utm_id first/last EVENT STREAM (unified) sources: CDP({{CDP_HOST}}) | GA4({{GA4_MEASUREMENT_ID}}) | LI_TAG | LI_CAPI | EMAIL | CALL({{CALL_TRACKING_NUMBER}}) | SMS | CRM types: AD_CLICK, PAGE_VIEW, VIDEO_25/50/75/97, LGF_OPEN/SUBMIT, DOC_DOWNLOAD, EMAIL_OPEN/CLICK/REPLY, CALL_IN/OUT, TOUR_*, CAPI_LEAD_SENT ENGAGEMENT SCORE weighted sum, 50% decay after 30 days; submits/tours/inbound calls dominate, opens trickle. route at {{SCORE_ROUTE_THRESHOLD}}

Bio + Next Best Action (computed, never typed)

BIO = live narrative assembled from fields: who · LinkedIn signals · firmographics · portfolio ownership · deal · source · data quality. NBA = ranked rules, recomputed on open: P1 verify-before-handoff · speed-to-tour · score routing · LOI sequence P2 package send · DMP/journey sync · warm-intro path P3 enrichment · missing LinkedIn URL · missing context P1 items block broker handoff.
U-09 · Template
Competitor Intel — Gallery, Analysis, Counter-Strategy
LinkedIn’s Ad Library has no official API — monitor {{COMP_SEARCH_KEYWORDS}} manually or via a scraper feeding this schema. Archetype cards hold the pattern until real captures replace them.

Capture schema

{ advertiser, advType, format, commentary, headline, cta, visual: what the media shows, infSeg / infStage: mapped to YOUR architecture, targeting: inferred facets, strengths[], weaknesses[], counter } Normalizing to your own segment×stage grid is the whole trick — gaps then read directly against your campaigns.

Analysis dimensions (computed)

format mix · stage mix · CTA mix · segment coverage WHITESPACE = formats they skip (document/conversation/TLA), stages they ignore (00–02 — cheap attention), segments with zero presence. MESSAGING READ: the field splits into adjective ads and one-number ads. Stack sourced numbers + inventory menu + delivery date in one frame and neither can follow.

Counter-strategy formula

PER SEGMENT: their pattern → counter-message → targeting counter → draft. STANDING RULES 1. Never enter the price war ({{PRICE_COMPETITOR_PATTERN}}). 2. Proof beats promise: {{PROOF_ASSETS}}. 3. Buy the empty early stages before CPMs follow the crowd. 4. Run the formats they skip. 5. Franchisor + tenant-rep spend is PIPELINE, not competition — sequence your site ads behind their brand ads.
U-10 · Template
Action Feed — Autopilot + Human in the Loop
Every action the system wants to take, queued on a clock. Untouched cards fire at T-0 when autopilot is {{AUTOPILOT_DEFAULT}}; humans can run early, edit payloads, snooze, or kill. Approval classes never self-fire.

Card schema

{ kind: API_CALL | AUDIENCE | CONTENT | OPTIMIZATION | TEST | GROWTH | NURTURE, title, desc, runAt: epoch, status: QUEUED → RUNNING → DONE | SKIPPED, approval: bool /* {{APPROVAL_CLASSES}} */, exec: { REQ: method+path+editable body } or { FN: registry call } } Horizon: {{FEED_HORIZON_DAYS}} days ahead, regenerated from live state.

Generation sources → kinds

calendar items → CONTENT (fire at slot time) campaign state → API_CALL (activations, preflights) CRM status vs DMP tags → AUDIENCE (ADD/REMOVE moves, hashed) analytics + fatigue → OPTIMIZATION (budget shifts, pauses) creative library → TEST (variant rotations) competitor gallery gaps → GROWTH (counter-creative drafts) engagement scores → NURTURE (adopt score, route to broker)

Clock discipline

1-second tick: countdowns repaint; due non-approval cards fire one per tick (no bursts); every send logs to the API console. Due + approval (or autopilot OFF) → AWAITING HUMAN, holds forever. Snooze = +1h / +1d. Edit = the edited payload is what fires. The feed is a queue, not a log: DONE cards sink, soonest floats.