The Ops Atlas xOps School

Business & Growth Overlapping synonym Sources verified

MarTechOps

MarTechOps (marketing technology operations) designs and runs the plumbing of the marketing stack: how tools connect, how customer data and consent signals flow between them, which tags fire, and which tools the company keeps.

Key takeaways

  • MarTechOps is not a separate discipline. It is the technology-and-data side of marketing operations, seen mostly in job titles. This Atlas gives it stack architecture and data plumbing; MarketingOps keeps campaigns and the funnel (an editorial split).
  • Treat consent as a signal that must reach every tag and tool: set defaults before any tag runs, honour Global Privacy Control where opt-out law applies, and test the result in a browser instead of trusting the banner settings.
  • Every tag, integration and tool needs an owner, a purpose, a contract and a review date. California's Honda order shows the risk: adtech vendors on the site, but no contracts the company could produce.
  • Design CRM–MAP sync field by field: one system of record per field, explicit sync rules, an API budget and a daily reconciliation, because sync tools overwrite values silently. Treat opt-outs as one-way: once set, only the person clears them.
  • Server-side tagging moves vendor code off the page and gives control over what leaves it. It does not remove consent duties, it costs money to run, and it suits only some tags.
  • Choose a packaged CDP, a warehouse-native (composable) approach or neither by deciding who will own identity rules and data quality; over-merged identities are a common, expensive failure.
  • Measure the stack itself: consent-test pass rate, tracking-plan conformance, sync errors and lag, identity anomalies and licence use (Gartner reports that only 49% of martech tools were actively used in its 2025 survey).

MarTechOps (marketing technology operations) is the work of designing and running the marketing stack as one system. It decides how the marketing automation platform (MAP), the CRM, the website’s tags, the customer data platform or warehouse and the ad platforms connect; which customer data and consent signals flow between them; who may change what; and which tools the company keeps or retires.

When it works, a person who rejects advertising cookies is not tracked by an ad pixel, a web-form lead reaches the CRM with the right owner within minutes, and nobody’s profile is merged with a stranger’s. When it fails, a regulator, a customer or a renewal invoice is often the first to notice.

Who this page is for. Beginners curious about the “martech” half of marketing operations; martech managers, marketing engineers and data teams; privacy and security partners; leaders deciding whether they need the role.

Item Summary
Goal A rationalised stack in which trustworthy, consented data flows between tools
Typical owners Martech manager, marketing engineer, marketing ops (technology side), with data engineering and IT
In scope Stack architecture; CRM–MAP sync design; tag management; consent-signal plumbing; server-side tagging; CDPs and identity resolution; tracking plans; email authentication set-up; tool selection and retirement; admin access
Handed off Campaigns and the funnel, stack decision rights, consent policy, ad delivery, reporting (see What MarTechOps is not)
Key outputs Stack inventory, tag register, field contract, tracking plan, consent test results, access reviews
Prerequisites HTTP, cookies and DNS basics; how a CRM and a MAP work; reading JSON
Term status Overlapping synonym of the technology side of marketing operations (see below)

Term status: a job title, not a discipline

Link to section “Term status: a job title, not a discipline”

A search on 2026-10-23 found no organisation, standard, certification or product named “MarTechOps”; the phrase appears mostly in job titles. A Danish software company’s “MarTech Operations Specialist” is to “own and continuously improve the technology, data and automation that power our Marketing function”;[1] a US “MarTech Operations Associate” role “sits at the intersection of technical execution and campaign delivery”.[2] Both mix stack work with campaign work.

Summarising the MarketingOps.com survey of “more than 600 marketing ops pros”, Scott Brinker wrote that “marketing ops is clearly an entangled mix of process, technology, and data with 77.8%, 72.7%, and 73.3% of responsibilities matching those three pillars”.[3] Technology is one pillar of marketing operations, not a separate profession, so this page is classed as an overlapping synonym.

Stacks grow by accretion. The 2025 marketing technology landscape counted 15,384 products in 49 categories, up 9% in a year, while 1,211 products from the previous edition disappeared.[4] Each purchase brings a tag, an integration, an admin account and a contract. Gartner says its 2025 Marketing Technology Survey found that “Only 49% of tools are actively used”.[5] Its 2023 survey of 405 marketing leaders measured something else, the share of stack capability in use: 33%, down from 58% in 2020, with ecosystem complexity among the main obstacles.[6] The measures differ, so they are not a time series; both say much of the stack goes unused.

Without an owner for the stack as a system, the same failures recur: consent that stops at the banner; two tools that both believe they own a field; profiles merged on a shared identifier; dead tags slowing pages; licences renewing for unused tools and former contractors keeping admin rights.

  • Not campaign operations: campaigns, scoring and the hand-off SLA are MarketingOps’ work; stack decision rights are RevOps’; reporting models are AnalyticsOps’.
  • Not the privacy function: lawful basis, notices and consent policy belong to PrivacyOps and counsel; MarTechOps implements the signals and proves they work.
  • Not ad trafficking: ad servers and consent strings to bidders are AdOps; MarTechOps owns the tag infrastructure the pixels run in.
  • Not company-wide integration engineering, which belongs to IntegrationOps.

MarTechOps has no founding document; it grew out of the technical side of marketing. Datable milestones:

  • The marketing technologist. In 2013 Brinker reported that 70% of 203 large US firms in a Gartner survey had a “chief marketing technologist”-type role (the role, not the title).[7]
  • Landscape growth. From 150 products in the first official landscape to 15,384 in 2025 (“100X growth since 2011”), plus a “hypertail” of custom-built apps and agents.[4]
  • Consent becomes a runtime signal. The IAB Europe TCF (v2.3, adoption deadline 28 February 2026),[8] Google’s consent mode[9] and California’s opt-out signal rules[10] made consent data every tag must read.
  • Browsers limit tracking. WebKit caps or deletes several kinds of script-written storage;[11] Chrome kept users’ third-party-cookie choice and in October 2025 announced that it would retire most Privacy Sandbox APIs.[12]
  • The centre of the stack moves. In Brinker and Riemersma’s 2025 survey most B2B respondents named the CRM or MAP as the centre; among B2C and hybrid companies, CDP answers fell (26.9% to 17.4%) and cloud warehouses rose (20.9% to 23.9%).[4]
Term Meaning
Tag; tag manager; container Third-party code or pixel sending data to a vendor; the tool that loads and controls tags; one site’s set of tags, triggers and variables
Custom HTML; template; workspace In Google Tag Manager: a tag holding free-form code; a sandboxed tag type with declared permissions;[13] a separate set of draft changes to a container[14]
Consent string (TCF, GPP) A coded record of a person’s choices passed to advertising vendors, in IAB Europe’s or IAB Tech Lab’s format[8][15]
Data layer A structured object the page fills so tags read agreed values instead of scraping the page
Consent management platform (CMP) The banner and preference centre that records choices and exposes them to tags
Consent state and default The current choice per purpose (granted or denied), and the value used before the person chooses
Opt-out preference signal; GPC A browser signal meaning “do not sell or share my data”; Global Privacy Control sends Sec-GPC: 1
Server-side tagging; conversions API Tags run in a server container you control; vendors’ server-to-server endpoints for events (Meta’s is the Conversions API)
Customer data platform (CDP) Software keeping a persistent, unified customer record available to other systems[16]
Identity resolution Rules deciding which identifiers (user ID, email, device IDs) belong to one person
Reverse ETL Syncing modelled warehouse data into operational tools[17]
Tracking plan The agreed events and properties, with types and rules, that collection is checked against
System of record The one tool whose value wins for a given field
SPF, DKIM, DMARC DNS-based email authentication: allowed senders, signatures, and the policy tying them to the From domain
DPA; MQL Data-processing agreement, the contract terms for a vendor handling personal data for you; marketing-qualified lead, one that marketing’s rules judge ready for sales

Mental model: pipes, valves and a register. Pipes (integrations, tags) move data; valves (consent signals, access rights) decide what may flow; the register says who owns each, why it exists and when it goes. Most MarTechOps work is keeping the three in step.

Figure 1. Where MarTechOps sits among its neighbours
decision rightspolicy in, records and testsoutrequirementsspeed budgetsstandardstag infrastructureclean eventsRevOpsMarTechOps: stack andplumbingPrivacyOpsMarketingOpsWebOpsIntegrationOpsAdOpsAnalyticsOps
Diagram source (Mermaid)
flowchart TB
  RO["RevOps"] -->|"decision rights"| MT
  PO["PrivacyOps"] <-->|"policy in, records and tests out"| MT
  MO["MarketingOps"] <-->|"requirements"| MT
  WO["WebOps"] -->|"speed budgets"| MT
  IO["IntegrationOps"] -->|"standards"| MT
  MT["MarTechOps: stack and plumbing"] -->|"tag infrastructure"| AO["AdOps"]
  MT -->|"clean events"| AN["AnalyticsOps"]
  classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
  classDef neutral fill:#f1f4f6,stroke:#5b7a87,color:#122029
  class MT core
  class MO,RO,PO,AO,AN,WO,IO neutral

Text equivalent: RevOps gives MarTechOps decision rights over the stack; MarketingOps exchanges requirements for platforms and data flows; PrivacyOps sends consent policy and the GPC rule and gets consent records and test results back; MarTechOps supplies tag infrastructure to AdOps and clean events to AnalyticsOps; WebOps sets tag performance budgets; IntegrationOps sets integration standards.

Neighbour Shared ground MarTechOps focus Neighbour’s focus
MarketingOps MAP, CRM, consent Architecture, sync, tags Campaigns, scoring, consent capture
RevOps Go-to-market stack Marketing stack design Decision rights, source of truth
PrivacyOps Consent Signals, tests, records Policy, lawful basis, rights
AdOps Pixels Tag infrastructure Ad servers, bidders, consent strings
AnalyticsOps Event data Collection quality Models, dashboards
WebOps Page weight Which tags load Core Web Vitals, releases
DataOps Pipelines Activation, identity Pipeline engineering

This charter is this Atlas’s proposal; no official MarTechOps manifesto exists. Mission: run the marketing stack so that the right data, with a valid consent signal, reaches the right tool, and every tool earns its place.

  1. Consent travels with the data. Defaults apply before anything runs; every tag, server container and destination honours the consent state.
  2. One owner per field, tag and tool, and one system of record per field.
  3. Change through a pipeline: workspace or sandbox, non-live test, a small group of publishers, a version to roll back to.
  4. Test behaviour, not configuration. Prove in a browser and in the data what fires and flows.
  5. Least privilege, two administrators, no shared logins.
  6. Remove as deliberately as you add: every tool and tag has a review date.
  7. Integration before features. Brinker reports “ability to integrate” as the top criterion (81.3%) of surveyed marketing ops professionals evaluating new technology.[3]

Non-goals: campaign strategy, legal policy, owning the company data platform, chasing every new tool.

Five layers: sources (site, apps, forms, uploads); collection (tag manager, SDKs, server container, conversions APIs); consent and identity (CMP states, identity rules); data (CDP or warehouse, tracking plan); activation (MAP, CRM, ad tools). A governance plane spans them: inventory, access, change control, contracts, tests and cost.

Small companies give all of this to one marketing ops generalist; larger ones split it across a martech manager, marketing engineers, a data engineer and an IT or security partner. The RACI below has one Accountable (A) per row; R = responsible, C = consulted, I = informed.

Activity MarTechOps MarketingOps PrivacyOps / legal Data, IT and security
Stack architecture and integration design A, R C C C
Choosing or retiring a marketing tool (A: the marketing leader who holds the budget, within RevOps decision rights) R C C C (security review)
Tag request, build and publish A, R R (requests) C (new vendors, data types) I
Consent policy and purposes R (implements) I A C
Consent-signal tests and records A, R I C I
CRM–MAP field ownership and sync rules A, R C I C (CRM admin)
Identity rules in the CDP or warehouse R I C A (data platform owner)
Email authentication (SPF, DKIM, DMARC) R C I A (DNS owner)
Admin access reviews R I I A

Skills. HTTP and browser developer tools; JavaScript sufficient to read tags; SQL; APIs and webhooks; DNS; the data models of the MAP and CRM; enough privacy law to know when to call counsel.

Tools move through evaluate (integration, security and privacy), contract (data-processing and exit terms), integrate, operate, review before renewal, and a planned sunset. Tags cycle faster, and many incidents can start in the middle: a tag published untested, or kept long after its purpose ended.

Figure 2. Lifecycle of a marketing tag
yesnofailspassesyesnoRequest: purpose, owner,data, vendor contractReview: new vendor or newdata type?Privacy and security reviewBuild in a workspace,template firstTest in QA environment:consent and payloadPublish as a new versionMonitor: errors, page speed,data arrivalQuarterly review: stillneeded?Remove tag, triggers andvariables
Diagram source (Mermaid)
flowchart TB
  A["Request: purpose, owner, data, vendor contract"] --> B{"Review: new vendor or new data type?"}
  B -->|"yes"| C["Privacy and security review"]
  B -->|"no"| D["Build in a workspace, template first"]
  C --> D
  D --> E["Test in QA environment: consent and payload"]
  E -->|"fails"| D
  E -->|"passes"| F["Publish as a new version"]
  F --> G["Monitor: errors, page speed, data arrival"]
  G --> H{"Quarterly review: still needed?"}
  H -->|"yes"| G
  H -->|"no"| I["Remove tag, triggers and variables"]
  classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
  classDef decision fill:#fdf3e3,stroke:#c9800f,color:#122029
  classDef risk fill:#fbeceb,stroke:#b4332b,color:#122029
  class A,D,E,F,G core
  class B,H decision
  class C,I risk

Text equivalent: a request names purpose, owner, data and contract; a new vendor or data type triggers privacy and security review; the tag is built in a workspace from a template, tested in a QA environment (failures return to build), published as a version and monitored; a quarterly review keeps it or removes it with its triggers and variables.

  • Two change classes. Standard: an approved vendor and template, no new data; one reviewer, weekly publish window. High-risk: a new vendor, Custom HTML, a new data type or consent logic; privacy review, QA-environment test, named publisher, rollback version recorded.
  • Cadences. Weekly publish window and sync-error review; monthly Lab 1 and Lab 2 reports; quarterly tag, access and inventory review; a tool review before every renewal.
  • Escalation. Tags firing without consent, mis-merged identities reaching customers and failed opt-outs are incidents; PrivacyOps is informed the same day.
  • Decision rights. RevOps decides the source of truth for each shared object; MarTechOps decides how the marketing stack implements it.

Reference architecture: the consented data path

Link to section “Reference architecture: the consented data path”

A representative design, not the only correct one. What matters is where the controls sit: consent is read at collection, checked again at the server, stored next to the profiles and checked before each sync; one governance plane spans all.

Figure 3. Reference architecture of a marketing stack with consent and identity layers
ActivationData and identityCollectionSourcesWebsite and appsForms and offline uploadsCMP: consent stateTag manager and data layerServer container: consentcheckProfiles and consent recordsIdentity rules and trackingplanMAP and CRM: consentedonlyAd and analytics platformsGovernance plane: inventory,access, change control,contracts, tests, cost
Diagram source (Mermaid)
flowchart TB
  subgraph SRC["Sources"]
    S1["Website and apps"]
    S2["Forms and offline uploads"]
  end
  subgraph COL["Collection"]
    C1["CMP: consent state"]
    C2["Tag manager and data layer"]
    C3["Server container: consent check"]
  end
  subgraph DAT["Data and identity"]
    D1["Profiles and consent records"]
    D2["Identity rules and tracking plan"]
  end
  subgraph ACT["Activation"]
    A1["MAP and CRM: consented only"]
    A2["Ad and analytics platforms"]
  end
  S1 --> C1
  C1 --> C2
  C2 --> C3
  C1 --> D1
  S2 --> D1
  C3 --> D1
  C3 --> A2
  D2 --> D1
  D1 --> A1
  A1 --> D1
  G["Governance plane: inventory, access, change control, contracts, tests, cost"]
  COL -.- G
  DAT -.- G
  ACT -.- G
  classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
  classDef neutral fill:#f1f4f6,stroke:#5b7a87,color:#122029
  classDef decision fill:#fdf3e3,stroke:#c9800f,color:#122029
  class C1,D2 decision
  class C2,C3,D1 core
  class S1,S2,A1,A2 neutral

Text equivalent: the CMP sets consent first; the tag manager reads it and sends events to a server container, which checks consent again and forwards events to ad and analytics platforms and to the warehouse or CDP, where the CMP also sends consent records. Forms and offline uploads go straight to the warehouse or CDP, whose profiles are governed by identity rules and the tracking plan. The warehouse or CDP syncs both ways with the MAP and CRM, sending only profiles with the required consent. A governance plane covers collection, data and activation.

Components and their main risks.

Component Responsibility Main risk
CMP Records choices per purpose and region; exposes them to tags Wrong or late defaults; choices not exported as records
Tag manager Loads tags under consent conditions; keeps versions Anyone with Publish rights runs code on every page
Server container Receives events on your domain; shapes and forwards them A service to run; you decide what leaves
Warehouse or CDP Profiles, events, identity resolution Over-merging; personal data kept too long
MAP and CRM Email, routing, sales work Sync conflicts; opt-outs not propagated

Alternative. A small business may stop at CMP, tag manager and the MAP’s native CRM connector, with no CDP or server container; often that is the right design (see when not to use a heavier stack).

Link to section “End-to-end workflow: one consent choice from banner to tools”

One visitor in the EEA (an opt-in region), followed through a CMP, a tag manager in basic consent mode and a server container. US opt-out regions and GPC are covered in the exception paths below and in Lab 1.

Figure 4. How an EEA visitor’s consent choice reaches tags and vendors (basic consent mode)
VendorServerTag managerCMPBrowserBasic mode: nothing sentAds vendor gets nothingPage load (EEA)Defaults: all deniedAccept analytics onlyAnalytics grantedEvents + consent stateAnalytics only
Diagram source (Mermaid)
sequenceDiagram
  participant B as Browser
  participant C as CMP
  participant T as Tag manager
  participant S as Server
  participant V as Vendor
  B->>C: Page load (EEA)
  C->>T: Defaults: all denied
  Note over T,S: Basic mode: nothing sent
  B->>C: Accept analytics only
  C->>T: Analytics granted
  T->>S: Events + consent state
  S->>V: Analytics only
  Note over S,V: Ads vendor gets nothing

Text equivalent: an EEA visitor loads the page; the CMP sets all-denied defaults in the tag manager. In basic consent mode Google tags send nothing before a choice (in advanced mode they would send cookieless pings). The visitor accepts analytics only; the tag manager then sends events with the consent state, and the server forwards them to the analytics vendor only. The ads vendor receives nothing.

Happy path. Default set before any tag; the choice recorded with the notice version; the update applied on the same page before navigation, as Google’s guide requires;[18] only consented destinations receive data.

Exception paths.

  • The CMP loads late. Consent mode’s wait_for_update makes tags wait a set number of milliseconds for an update;[18] if the CMP keeps missing it, fix the load order rather than raising the wait.
  • A tag has no built-in consent check. Add a consent requirement in the tag manager’s consent settings,[9] or replace the tag with a template.
  • The browser sends GPC where the law requires honouring it. California treats it as an opt-out of sale or sharing, extended to the consumer if known;[10] ads stay off even without a banner.
  • A destination cannot receive consent parameters. Filter in the server container so it only gets data for people who granted the purpose.

Any tag manager needs the same controls: roles separating build from publish, a non-live environment, review, versions to roll back to, and sandboxed templates instead of free-form code. Adobe Experience Platform Tags, for example, moves libraries through development, staging and production, with Develop, Approve and Publish rights that “are not inclusive”.[19] The steps show one implementation, Google Tag Manager (GTM).

  1. Register every tag with purpose, owner, vendor, data sent, consent purpose, contract reference and review date (Artefact 1).
  2. Template first. Google’s web.dev guidance ranks image pixels as the most performant tag type, then custom templates, then Custom HTML, and calls sandboxed templates “often safer” than full Custom HTML access.[20]
  3. Restrict what can run. GTM reads gtm.allowlist and gtm.blocklist from the data layer, for example to block Custom HTML (class customScripts). Two caveats: any blocklist also blocks sandboxed templates unless sandboxedScripts is allowlisted (Artefact 2 does this), and Google now recommends templates with template policies over these lists.[13]
  4. Separate rights. GTM container permissions are Read, Edit (no versions or publishing), Approve (versions, no publishing) and Publish.[21] Give Publish to two or three people; require 2-step verification for Custom JavaScript variables, Custom HTML tags and user settings.[22]
  5. Test outside Live. Publishing a version to a QA environment does not change Live.[23] Formal approval requests exist only in Tag Manager 360; in the free edition, use the Approve permission and a written review.[24]
  6. Keep the rollback. Every publish records a version you can revert to.[24]
  7. Remove, do not block. Pause or remove unused tags; tags suppressed by trigger exceptions still ship in the container.[20]

The consent policy comes from PrivacyOps; this playbook implements it.

  1. Map purposes to consent types and tags. Google’s types are ad_storage, ad_user_data, ad_personalization and analytics_storage, plus functionality, personalisation and security storage.[9] Map non-Google tags too.
  2. Set defaults before any measurement command: a region-less default covers every visitor not matched by a regional one, so make it the strictest, and grant by default only in regions (ISO 3166-2) where counsel approved an opt-out model.[18] The region list is a PrivacyOps decision.
  3. Choose basic or advanced consent mode deliberately. Only advanced mode sends cookieless pings while consent is denied;[9] that is a legal call as well as a measurement one (see the judgement call).
  4. Honour opt-out preference signals. California requires online businesses to accept a signal (its example: “an HTTP header field or JavaScript object”) plus another method, and says a cookie banner “is not by itself an acceptable method” for opting out of sale or sharing.[10] Colorado recognised GPC as its first universal opt-out mechanism, required from 1 July 2024 for businesses within its law’s thresholds;[25] PrivacyOps keeps the jurisdiction list. GPC arrives as Sec-GPC: 1 and navigator.globalPrivacyControl (W3C Working Draft, 24 September 2026).[26]
  5. Make choices symmetric. The CPPA found Honda’s tool let people “Accept All” in one step while opting out took at least two clicks, and ordered a “Reject All” button.[27]
  6. Export consent records in the format PrivacyOps defines; Google’s EU user consent policy also requires retaining consent records for users in the EEA, UK and Switzerland.[28]
  7. Test on every CMP or container release and monthly with a scripted browser (Lab 1).
  1. Write a field contract (Artefact 3): system of record, direction, blank-value rule and writers for each field.
  2. Know the connector. Marketo’s Salesforce sync pauses five minutes between cycles and is bidirectional only for leads, contacts and Salesforce campaigns.[29] HubSpot’s rules are “Prefer Salesforce unless blank”, “Always use Salesforce”, “Two-way” (most recent value wins; deletions propagate) and “Don’t sync”; a field’s first sync with no history takes the Salesforce value as baseline, which can overwrite a newer HubSpot value.[30] Two defaults differ: Lifecycle stage “can only be moved forward” by HubSpot tools, the integration included;[31] and clearing Email Opt Out in Salesforce does not resubscribe a HubSpot contact, while contacts that are not syncing (for example, outside the inclusion segment) get no opt-out sync at all.[32]
  3. Give every field one writer. “Prefer Salesforce unless blank” lets HubSpot write only while Salesforce is empty; after that, Salesforce always wins,[30] so use it for values HubSpot fills once. For a field the MAP keeps updating, use two-way and make the Salesforce field read-only for everyone except the connected user, whose permissions decide what the sync can write.[33][34] If marketing and sales both need a “stage”, give each a field.
  4. Budget API calls. One HubSpot contact sync can take up to four API calls per record, and HubSpot asks you to allocate a share of the Salesforce limit to it.[34][35] Schedule bulk updates.
  5. Make opt-outs one-way and propagate them first. Only the person clears an opt-out, in the preference centre; never a sync, import or bulk job. Push it to every sending tool and check contacts outside the sync scope; a miss is an incident.
  6. Reconcile daily (Lab 3).
  1. Rank identifiers. Segment gives immutable IDs such as user_id the highest priority, unique IDs such as email more than shared device IDs, and by default allows one user_id and five of other identifiers per profile.[36]
  2. Block junk values. Segment warns that a hard-coded test user_id reaching production “can cause hundreds of profiles to merge incorrectly”, and suggests blocking zeroes and dashes, -1, null and anonymous.[36] The discipline applies to any CDP or warehouse identity model.
  3. Alert on profiles over identifier limits and on merge spikes.
  4. Decide where the profile lives: the CDP Institute recognises packaged, warehouse-native (composable) and hybrid CDPs;[16] see the decision framework.

Playbook: server-side tagging and conversions APIs

Link to section “Playbook: server-side tagging and conversions APIs”
  1. What it does. A server container runs “on a server that you control” and forwards events to vendors; Google says to use a first-party domain and production mode before going live.[37]
  2. What it does not do. Remove consent duties. In Google’s design consent is set in the web container and Google product tags in the server are consent-aware;[38] the guide says nothing similar about other vendors’ server tags, so this Atlas advises an explicit consent condition on each.
  3. Browser rules still apply. WebKit caps cookies set via third-party CNAME or IP-address cloaking at seven days.[11]
  4. Deduplicate. Meta’s recommended method matches the Pixel’s event ID and event name with the Conversions API’s event_id and event_name, within 48 hours; an alternative matches event_name with fbp and/or external_id and generally works only for events sent first from the browser.[39]
  5. Budget it. Google estimates about $45 a month per Cloud Run server, recommends at least two, and warns about logging charges above roughly a million requests a month (as of May 2026).[40]

MarketingOps checks campaign headers; the domain set-up is done here with the DNS owner.

  1. List every system that sends as your domain (MAP, CRM, support, billing, product email).
  2. SPF: include, a, mx, ptr, exists and redirect count towards a limit of 10 DNS lookups, beyond which evaluation returns “permerror”;[41] give each sending tool its own subdomain as the list grows.
  3. Know which domain each check sees. SPF checks the envelope (MAIL FROM, or return-path) domain, not the visible From; DMARC “relies solely on SPF validation of the MAIL FROM identity” and needs it, or a DKIM signing domain, aligned with the From domain.[42] A tool bouncing through its own domain aligns SPF only with a custom return-path on your subdomain; otherwise alignment comes from DKIM.
  4. DKIM: a key per tool, signing with your domain or subdomain, rotated on a schedule.
  5. DMARC (now RFC 9989, May 2026):[42] start at p=none with aggregate reports, fix alignment, then tighten. Gmail requires SPF or DKIM from every sender and all three above 5,000 messages a day;[43] Outlook.com requires all three above 5,000 a day.[44] Full provider rules: MarketingOps.

Inventory every tool (Artefact 4); measure active users against paid seats; map tools doing the same job; decide keep, consolidate, replace or retire, with reasons; and retire properly: export data, confirm vendor deletion, remove tags, keys, DNS records and SSO apps, then cancel before the notice date.

Item Type What it gives MarTechOps
CCPA regulations §7025–7026 (California) Law Duty to honour opt-out preference signals; banner alone not enough[10]
EU ePrivacy Directive Art. 5(3); EDPB Guidelines 2/2023 Law; regulators’ interpretation Consent for device storage and access, pixels and tracking links included[45]
W3C Global Privacy Control Draft specification The header and JavaScript property to detect[26]
IAB Europe TCF v2.3; IAB Tech Lab Global Privacy Protocol (GPP) Industry frameworks Consent strings for advertising vendors (ad-request use in AdOps)[8][15]
Google EU user consent policy; consent mode Vendor contract and API Consent and record duties; how Google tags read consent[28][9]
RFC 7208 (SPF), RFC 9989 (DMARC), RFC 8058 Internet standards Email authentication and one-click unsubscribe[41][42][46]

Examples checked on 2026-10-23; not endorsements.

Category Job Examples Selection points and risks
Tag management Load and control tags Google Tag Manager (free and 360); Adobe Experience Platform Tags;[47] Matomo Tag Manager[48] The controls in the tag governance playbook
Server-side collection Receive and forward events on your domain GTM server container[37] Run cost, uptime, vendor support
Consent management Banner, preferences, records, signals TCF-registered CMPs (ad-product requirements in AdOps) Region rules, GPC, symmetric choices, record export
CDP, packaged Profiles, identity, activation Segment Unify[36] among 240+ vendors listed by the CDP Institute[16] Identity controls, residency, cost model
Warehouse-native activation Model in the warehouse, sync to tools Hightouch;[17] RudderStack (server under the source-available Elastic License 2.0)[49] Data engineering; warehouse cost
Event validation Tracking plans Segment Protocols;[50] Snowplow schemas[51] Block or flag violations
MAP and CRM Engagement and sales records See MarketingOps, SalesOps Connector behaviour, API limits

Automate the checks in the cadences above (Labs 1–3 in CI or daily), plus alerts on sync errors and unregistered tags. Use AI with limits: language models can draft tag documentation or explain a container diff, but should not hold publish or admin rights, where one wrong change hits every page or record. Company-built apps and agents, the “hypertail”,[4] need registering like any other tool.

Reference implementation: operating artefacts

Link to section “Reference implementation: operating artefacts”

One representative set-up: a B2B website with a tag manager and CMP, a MAP synced to a CRM, a warehouse and two sending tools; names and values are placeholders.

Example status: YAML syntax-checked by the Atlas validator; a record format, not a product configuration.

tag_id: tag-0142
name: Ads conversion - demo request
owner: martech@example.com            # a team mailbox, not a person
requested_by: demand-gen
vendor: ExampleAds Inc.
contract_ref: DPA-2026-031            # data-processing terms on file
purpose: advertising measurement
consent_purpose: ads                  # maps to ad_storage and ad_user_data
regions_blocked_without_consent: [EEA, UK, CH]
honours_gpc: true                     # stays off when Sec-GPC: 1 is sent
data_sent: [event_name, value, currency, hashed_order_id]
personal_data_in_payload: false
implementation: vendor template       # not Custom HTML
container_version_added: 87
last_consent_test: 2026-10-01
review_by: 2027-01-15
removal_plan: delete tag, trigger trg-demo-thanks, variable var-order-id
Link to section “Artefact 2: consent defaults and tag restrictions in the page head”

Example status: JavaScript syntax-checked with node --check; not executed in a browser. US only illustrates the regional mechanics (playbook step 2). What it blocks: Custom HTML tags, Custom JavaScript variables and the few built-in vendor tags in class customScripts; template tags keep running.

// Runs before the tag manager snippet.
window.dataLayer = window.dataLayer || [];
function gtag() { window.dataLayer.push(arguments); }

// 1. Default for every visitor not matched below: nothing granted before a choice.
gtag('consent', 'default', {
  ad_storage: 'denied',
  ad_user_data: 'denied',
  ad_personalization: 'denied',
  analytics_storage: 'denied',
  wait_for_update: 500,
});

// 2. Only regions where counsel approved an opt-out model (illustrative):
//    granted by default, but advertising off when the browser sends GPC.
const gpc = navigator.globalPrivacyControl === true;
gtag('consent', 'default', {
  ad_storage: gpc ? 'denied' : 'granted',
  ad_user_data: gpc ? 'denied' : 'granted',
  ad_personalization: gpc ? 'denied' : 'granted',
  analytics_storage: 'granted',
  region: ['US'],
});

// 3. No Custom HTML; keep sandboxed custom templates (vendor and CMP templates) working.
//    Template policies then decide what each template may do.
window.dataLayer.push({
  'gtm.allowlist': ['sandboxedScripts'],
  'gtm.blocklist': ['customScripts'],
});

Allowlisting sandboxedScripts restricts no other tag class.[13] A GTM consent template uses setDefaultConsentState and updateConsentState instead.[18]

Example status: YAML syntax-checked; the sync rule names are HubSpot’s, other connectors use different terms.

contract: crm-map-fields
version: 2026-10-23
approved_by: [revops-lead, marketingops-lead, crm-admin]
fields:
  - field: marketing_stage         # custom: engaged, MQL (see Scenario 2)
    system_of_record: MAP
    rule: Two-way                   # no "always use HubSpot" rule exists
    writers: [MAP scoring only]     # Salesforce FLS read-only, except the connected user
    not_written_by: Salesforce flows, Apex or imports
    backfill: manual or bulk resync after a sample test  # no retroactive sync
  - field: sales_stage             # custom: accepted, qualified, disqualified
    system_of_record: CRM
    rule: Always use Salesforce     # HubSpot never writes; copy used for lists
    writers: [CRM users, CRM assignment rules]
  - field: phone
    system_of_record: CRM after creation  # the form fills it once, sales corrects it
    rule: Prefer Salesforce unless blank  # HubSpot writes only while Salesforce is blank
  - field: lifecycle_stage         # HubSpot default property
    rule: integration setting       # "Adjusting Lifecycle Stage"; forward only
    moving_back: clear by workflow first, e.g. disqualified leads
  - field: email_opt_out
    system_of_record: the person    # preference centre; any system may record it
    rule: default mapping           # both ways; a Salesforce clear won't resubscribe
    once_true: cleared only by the person, never by sync, import or bulk job
    scope_gap: contacts outside the sync segment get no opt-out sync; check daily
    max_lag_minutes: 15
    incident_if_breached: true
  - field: account_owner
    system_of_record: CRM
    rule: Two-way                   # HubSpot maps Owner only two-way
    writers: [CRM assignment rules] # no owner edits in the MAP
  - field: lead_source_detail
    system_of_record: MAP
    rule: Don't sync               # kept in MAP; reported from the warehouse
api_budget:
  share_of_crm_daily_limit: 0.30
  bulk_updates_window: "Sat 02:00-06:00 UTC"

Example status: JSON syntax-checked; figures are invented for illustration.

{
  "tool": "Example Webinar Platform",
  "category": "events",
  "business_owner": "field-marketing",
  "technical_owner": "martech",
  "contract": { "renewal": "2027-03-31", "notice_days": 60, "annual_cost": 18000 },
  "seats": { "paid": 25, "active_last_90_days": 7 },
  "integrations": ["MAP (native)", "CRM via MAP"],
  "tags_on_site": ["tag-0098"],
  "personal_data": ["name", "email", "attendance"],
  "dpa_on_file": true,
  "sso": true,
  "decision": "consolidate into MAP events module at renewal",
  "review_date": "2026-12-01"
}

Example status: illustrative DNS records with placeholder domains and a truncated key; not published anywhere.

example.com.             TXT "v=spf1 include:_spf.mailhost.example -all"
mail.example.com.        TXT "v=spf1 include:send.mapvendor.example -all"
s2026._domainkey.mail.example.com.  TXT "v=DKIM1; k=rsa; p=MIIBIjANBg..."
_dmarc.example.com.      TXT "v=DMARC1; p=none; rua=mailto:dmarc@example.com"

A subdomain per sending tool keeps each SPF record under the 10-lookup limit, but aligns for DMARC only if the tool uses it as its return-path; a DKIM signature from mail.example.com aligns with a From at example.com under relaxed alignment, the default. DMARC stays at none until reports show every sender aligned.

All three labs were executed on 2026-10-23 on Linux with the versions named, against local fixtures only.

Link to section “Lab 1 (beginner–intermediate): test which tags fire under each consent signal”

Objective. Prove in a real browser which tag purposes fire for an EU visitor before and after a choice, and for a US visitor with and without GPC.

Prerequisites. Node.js 20, Python 3, about 300 MB for a Playwright browser. Cost: none. Risk: none (local only).

Steps.

  1. Create a folder with a site/ subfolder and install Playwright: npm init -y && npm i playwright@1.47.2 && npx playwright install chromium.
  2. Save the fixture as site/index.html: an imitation CMP with opt-in for ?region=eu and opt-out for ?region=us, where GPC switches the ads tag off. The “vendor” is a second local server.

Example status: executed as the fixture for this lab (not a real CMP).

<!doctype html>
<html lang="en">
<head><meta charset="utf-8"><title>Consent fixture</title></head>
<body>
<div id="banner">
  <button id="accept">Accept all</button>
  <button id="reject">Reject all</button>
</div>
<script>
  // Illustrative consent logic, not a real CMP. Region comes from the URL.
  const VENDOR = 'http://127.0.0.1:8002';
  const region = new URLSearchParams(location.search).get('region') || 'eu';
  const gpc = navigator.globalPrivacyControl === true;
  const fire = (path) => { new Image().src = VENDOR + path + '?t=' + Date.now(); };
  const apply = (s) => {
    if (s.analytics) fire('/analytics/collect');
    if (s.ads) fire('/ads/pixel');
  };
  if (region === 'us') {
    // Opt-out model: tags run by default; GPC opts out of sale/sharing.
    document.getElementById('banner').hidden = true;
    apply({ analytics: true, ads: !gpc });
  } else {
    // Opt-in model: nothing fires until the person chooses.
    const onClick = (id, s) => { document.getElementById(id).onclick = () => apply(s); };
    onClick('accept', { analytics: true, ads: true });
    onClick('reject', { analytics: false, ads: false });
  }
</script>
</body>
</html>
  1. Save the scenarios as consent-cases.json (in real use, trackers comes from the tag register and the cases from the consent policy).

Example status: executed.

{
  "site": "http://localhost:8001/index.html",
  "settleMs": 1500,
  "trackers": [
    { "match": "127.0.0.1:8002/analytics/", "purpose": "analytics" },
    { "match": "127.0.0.1:8002/ads/", "purpose": "ads" }
  ],
  "cases": [
    { "name": "eu-no-choice", "query": "?region=eu", "gpc": false, "click": null,
      "expect": { "analytics": false, "ads": false } },
    { "name": "eu-accept", "query": "?region=eu", "gpc": false, "click": "#accept",
      "expect": { "analytics": true, "ads": true } },
    { "name": "eu-reject", "query": "?region=eu", "gpc": false, "click": "#reject",
      "expect": { "analytics": false, "ads": false } },
    { "name": "us-default", "query": "?region=us", "gpc": false, "click": null,
      "expect": { "analytics": true, "ads": true } },
    { "name": "us-gpc", "query": "?region=us", "gpc": true, "click": null,
      "expect": { "analytics": true, "ads": false } }
  ]
}
  1. Save the test as consent-test.mjs. For GPC cases it sends Sec-GPC: 1 and sets navigator.globalPrivacyControl; it records requests matching a tracker and compares the purposes fired with the expectation.

Example status: executed with Playwright 1.47.2 (Chromium 129) and Node.js 20.19.

// Consent-signal regression test: which tag purposes fire in each scenario?
// Usage: node consent-test.mjs consent-cases.json
import fs from 'node:fs';
import { chromium } from 'playwright';

const cfg = JSON.parse(fs.readFileSync(process.argv[2] || 'consent-cases.json', 'utf8'));
const purposeOf = (url) => cfg.trackers.find((t) => url.includes(t.match))?.purpose;
const browser = await chromium.launch();
let failed = 0;
for (const c of cfg.cases) {
  const context = await browser.newContext({
    extraHTTPHeaders: c.gpc ? { 'Sec-GPC': '1' } : {},
  });
  if (c.gpc) {
    // Browsers that send Sec-GPC also expose navigator.globalPrivacyControl.
    await context.addInitScript(() => {
      Object.defineProperty(Navigator.prototype, 'globalPrivacyControl', {
        get: () => true,
      });
    });
  }
  const seen = new Set();
  context.on('request', (r) => {
    const p = purposeOf(r.url());
    if (p) seen.add(p);
  });
  const page = await context.newPage();
  await page.goto(cfg.site + c.query, { waitUntil: 'load' });
  if (c.click) await page.click(c.click);
  await page.waitForTimeout(cfg.settleMs ?? 1500);
  const problems = Object.entries(c.expect)
    .filter(([purpose, want]) => seen.has(purpose) !== want)
    .map(([purpose, want]) => `${purpose} ${want ? 'missing' : 'fired'}`);
  if (problems.length) failed += 1;
  const fired = [...seen].sort().join(',');
  console.log(`${problems.length ? 'FAIL' : 'PASS'} ${c.name.padEnd(13)} fired=[${fired}]`
    + (problems.length ? `  ${problems.join('; ')}` : ''));
  await context.close();
}
await browser.close();
console.log(`${cfg.cases.length - failed}/${cfg.cases.length} scenarios passed`);
process.exit(failed ? 1 : 0);
  1. Start the two local servers and run the test.

Example status: executed.

python3 -m http.server 8001 --bind 127.0.0.1 --directory site &
python3 -m http.server 8002 --bind 127.0.0.1 --directory site &
node consent-test.mjs consent-cases.json

Expected output (from the run on 2026-10-23):

PASS eu-no-choice  fired=[]
PASS eu-accept     fired=[ads,analytics]
PASS eu-reject     fired=[]
PASS us-default    fired=[ads,analytics]
PASS us-gpc        fired=[analytics]
5/5 scenarios passed

Validation. Prove the test can fail: change ads: !gpc to ads: true in the fixture and rerun. On 2026-10-23 this printed FAIL us-gpc ... ads fired and 4/5 scenarios passed, exiting with code 1, as a CI job needs. Restore the line.

Troubleshooting. Nothing fires: the port-8002 server is down or match misses the URLs (print r.url()). Clicks time out: wrong selector, or no banner in that region. Flaky on real sites: wait for a specific request, not a fixed time.

On a real site, point site at staging and list vendor hosts from the register; a headless browser sees only its own region’s banner, so use the CMP’s test override or run from each region.

Teardown. Stop both servers (kill %1 %2 in the same shell) and delete the folder.

Lab 2 (intermediate): validate events against a tracking plan

Link to section “Lab 2 (intermediate): validate events against a tracking plan”

Objective. Check events against a JSON Schema tracking plan and catch personal data in the wrong fields.

Prerequisites. A supported Python (3.10 or later) with jsonschema 4.x in a virtual environment. Cost and risk: none.

Steps.

  1. Save the plan as tracking-plan.json.

Example status: executed.

{
  "version": "2026-10-23",
  "events": {
    "form_submitted": {
      "type": "object",
      "required": ["form_id", "consent_version", "page_type"],
      "properties": {
        "form_id": { "type": "string", "pattern": "^[a-z0-9-]+$" },
        "consent_version": { "type": "string", "pattern": "^cv-[0-9]{4}-[0-9]{2}$" },
        "page_type": { "enum": ["product", "pricing", "blog", "event"] },
        "campaign_id": { "type": "string" }
      },
      "additionalProperties": false
    },
    "demo_requested": {
      "type": "object",
      "required": ["form_id", "product"],
      "properties": {
        "form_id": { "type": "string" },
        "product": { "enum": ["core", "analytics"] }
      },
      "additionalProperties": false
    }
  },
  "forbidden_value_patterns": {
    "email address": "[^@\\s]+@[^@\\s]+\\.[A-Za-z]{2,}",
    "phone number": "\\+?[0-9][0-9 ()-]{7,}[0-9]"
  }
}
  1. Save a sample of collected events as events.json (in practice, an export from your event pipeline or warehouse).

Example status: executed; fake data.

[
  {"event": "form_submitted",
   "properties": {"form_id": "webinar-2026-11", "consent_version": "cv-2026-09",
                  "page_type": "event", "campaign_id": "c-1042"}},
  {"event": "form_submitted",
   "properties": {"form_id": "Pricing Form", "consent_version": "cv-2026-09",
                  "page_type": "pricing"}},
  {"event": "form_submitted",
   "properties": {"form_id": "newsletter", "page_type": "blog"}},
  {"event": "demo_requested",
   "properties": {"form_id": "demo", "product": "core"}},
  {"event": "demo_requested",
   "properties": {"form_id": "demo", "product": "core", "email": "jane@example.com"}},
  {"event": "Form Submitted",
   "properties": {"form_id": "contact"}},
  {"event": "form_submitted",
   "properties": {"form_id": "contact", "consent_version": "cv-2026-09",
                  "page_type": "product", "campaign_id": "call +44 20 7946 0000"}}
]
  1. Save the checker as check_events.py and run python3 check_events.py tracking-plan.json events.json.

Example status: executed with jsonschema 4.23.0 and 3.2.0, identical output, on Python 3.8.10 (end of life, the only interpreter on the test machine; not run on 3.10 or later).

"""Validate tracked events against a tracking plan (one JSON Schema per event)."""
import json
import re
import sys

from jsonschema import Draft7Validator

plan = json.load(open(sys.argv[1]))
events = json.load(open(sys.argv[2]))
validators = {name: Draft7Validator(s) for name, s in plan["events"].items()}
pii = {label: re.compile(p) for label, p in plan["forbidden_value_patterns"].items()}

clean = 0
for n, ev in enumerate(events, start=1):
    name, props = ev.get("event"), ev.get("properties", {})
    problems = []
    if name not in validators:
        problems.append(f"unknown event name {name!r}")
    else:
        for err in sorted(validators[name].iter_errors(props), key=str):
            where = "/".join(map(str, err.path)) or "(event)"
            problems.append(f"{where}: {err.message}")
    for key, value in props.items():
        for label, rx in pii.items():
            if isinstance(value, str) and rx.search(value):
                problems.append(f"{key}: possible {label} (personal data)")
    if problems:
        print(f"event {n} {name}: " + "; ".join(problems))
    else:
        clean += 1

print(f"{clean}/{len(events)} events conform ({100 * clean / len(events):.1f}%)")
sys.exit(0 if clean == len(events) else 1)

Expected output (the fifth line is wrapped here for width; the script prints it on one line):

event 2 form_submitted: form_id: 'Pricing Form' does not match '^[a-z0-9-]+$'
event 3 form_submitted: (event): 'consent_version' is a required property
event 5 demo_requested: (event): Additional properties are not allowed
  ('email' was unexpected); email: possible email address (personal data)
event 6 Form Submitted: unknown event name 'Form Submitted'
event 7 form_submitted: campaign_id: possible phone number (personal data)
2/7 events conform (28.6%)

Validation. Fix the five events (lower-case form_id, add consent_version, drop email, rename the event, clean campaign_id); the run should reach 7/7 and exit 0.

Troubleshooting. ModuleNotFoundError → install jsonschema in a virtual environment. Order numbers flagged as phone numbers → tighten the pattern.

Teardown. Delete the files. In production, run the check in CI and on a daily sample; route personal-data hits to PrivacyOps.

Lab 3 (intermediate–advanced): reconcile a CRM export with a MAP export

Link to section “Lab 3 (intermediate–advanced): reconcile a CRM export with a MAP export”

Objective. Measure coverage, field drift, consent conflicts in both directions and lag between two systems that should agree, and fail the job when an opt-out has not reached both.

Prerequisites. Python 3 (standard library only) and Bash. Cost and risk: none; the data is fake.

Steps.

  1. Create the two exports with bash make_exports.sh.

Example status: executed.

#!/usr/bin/env bash
# Two small exports with deliberate drift (illustrative data, fake people).
set -euo pipefail
cat > crm.csv <<'CSV'
crm_id,email,lifecycle_stage,email_opt_out,updated_at
C001,ana@example.com,lead,0,2026-10-23T09:00:00Z
C002,ben@example.com,mql,0,2026-10-23T09:05:00Z
C003,chi@example.com,sql,0,2026-10-23T09:10:00Z
C004,dev@example.com,customer,1,2026-10-23T09:15:00Z
C005,eli@example.com,lead,0,2026-10-23T09:20:00Z
C006,fay@example.com,mql,0,2026-10-23T09:25:00Z
C007,gia@example.com,sql,1,2026-10-23T09:50:00Z
CSV
cat > map.csv <<'CSV'
crm_id,email,lifecycle_stage,unsubscribed,updated_at
C001,ana@example.com,lead,0,2026-10-23T09:01:00Z
C002,ben@example.com,lead,0,2026-10-23T08:40:00Z
C003,chi@example.com,sql,1,2026-10-23T09:30:00Z
C004,dev@example.com,customer,1,2026-10-23T09:16:00Z
C006,FAY@example.com,mql,0,2026-10-23T09:26:00Z
C007,gia@example.com,sql,0,2026-10-23T09:10:00Z
,gus@example.com,lead,0,2026-10-23T09:40:00Z
CSV
echo "wrote crm.csv and map.csv"
  1. Save reconcile.py and run python3 reconcile.py crm.csv map.csv. The column names are fixed in the script, so a file with other headers is rejected instead of being turned into SQL.

Example status: executed with Python 3.8.10 (standard library csv and sqlite3); exit code 1 because of the P1 conflicts.

"""Reconcile a CRM export with a MAP export: coverage, field drift, consent conflicts."""
import csv
import sqlite3
import sys

# Fixed column names: SQL is never built from headers found in a file.
COLUMNS = {
    "crm": ["crm_id", "email", "lifecycle_stage", "email_opt_out", "updated_at"],
    "map": ["crm_id", "email", "lifecycle_stage", "unsubscribed", "updated_at"],
}
db = sqlite3.connect(":memory:")
for table, path in (("crm", sys.argv[1]), ("map", sys.argv[2])):
    with open(path, newline="") as f:
        reader = csv.DictReader(f)
        if reader.fieldnames != COLUMNS[table]:
            sys.exit(f"{path}: expected {COLUMNS[table]}, got {reader.fieldnames}")
        rows = [tuple(r[c] for c in COLUMNS[table]) for r in reader]
    db.execute(f"CREATE TABLE {table} ({', '.join(COLUMNS[table])})")
    db.executemany(f"INSERT INTO {table} VALUES (?, ?, ?, ?, ?)", rows)

q = lambda sql: db.execute(sql).fetchall()
crm_n = q("SELECT COUNT(*) FROM crm")[0][0]
matched = q("SELECT COUNT(*) FROM crm JOIN map USING (crm_id)")[0][0]
print(f"CRM records: {crm_n}; matched in MAP: {matched} ({100 * matched / crm_n:.1f}%)")
for (cid,) in q("SELECT crm_id FROM crm WHERE crm_id NOT IN "
                "(SELECT crm_id FROM map WHERE crm_id <> '')"):
    print(f"  missing in MAP: {cid}")
for (email,) in q("SELECT email FROM map WHERE crm_id = ''"):
    print(f"  MAP-only (no CRM id): {email}")

checks = {
    "email (case-insensitive)": "lower(c.email) <> lower(m.email)",
    "email (exact)": "c.email <> m.email",
    "lifecycle_stage": "c.lifecycle_stage <> m.lifecycle_stage",
}
for label, cond in checks.items():
    ids = [r[0] for r in q(f"SELECT c.crm_id FROM crm c JOIN map m USING (crm_id) "
                           f"WHERE {cond}")]
    print(f"mismatch {label}: {len(ids)}/{matched} {ids}")

# An opt-out in either system must hold in both: check both directions.
conflicts = q("SELECT crm_id, m.unsubscribed FROM crm c JOIN map m USING (crm_id) "
              "WHERE m.unsubscribed <> c.email_opt_out")
for cid, unsub in conflicts:
    side = ("MAP unsubscribed, CRM mailable" if unsub == "1"
            else "CRM opted out, MAP mailable")
    print(f"P1 consent conflict: {cid} ({side})")
lag = q("SELECT crm_id, (julianday(c.updated_at) - julianday(m.updated_at)) * 1440 "
        "FROM crm c JOIN map m USING (crm_id) WHERE c.updated_at > m.updated_at")
for cid, minutes in lag:
    if minutes > 15:
        print(f"stale in MAP by {minutes:.0f} min: {cid}")
sys.exit(1 if conflicts else 0)  # a P1 conflict fails the job, so alerts fire

Expected output (from the run on 2026-10-23):

CRM records: 7; matched in MAP: 6 (85.7%)
  missing in MAP: C005
  MAP-only (no CRM id): gus@example.com
mismatch email (case-insensitive): 0/6 []
mismatch email (exact): 1/6 ['C006']
mismatch lifecycle_stage: 1/6 ['C002']
P1 consent conflict: C003 (MAP unsubscribed, CRM mailable)
P1 consent conflict: C007 (CRM opted out, MAP mailable)
stale in MAP by 25 min: C002
stale in MAP by 40 min: C007

Interpretation. C002’s stage mismatch is lag (the MAP copy is 25 minutes old): fix the sync, not the data. C006 differs only in case, which matters to tools that match emails exactly. C003 and C007 are incidents under Artefact 3; C007, opted out in the CRM but mailable in the MAP, is the direction that sends marketing email. If C005 is outside the sync segment, its opt-out would not sync either.[32]

Validation. Set C003’s email_opt_out to 1 in crm.csv and C007’s unsubscribed to 1 in map.csv, then rerun: no P1 lines, exit code 0. Rename a header and rerun: the script stops with “expected … got …”.

Troubleshooting. Different headers → map them to the expected names first; mixed time zones → convert to UTC; large exports → run the same SQL in the warehouse.

Teardown. Delete the files. Real exports hold personal data: keep them in an approved location and delete after use.

Link to section “Scenario 1 (documented): a regulator reads the cookie tool and the contracts”

In a stipulated order of 7 March 2025, the California Privacy Protection Agency found that American Honda’s cookie tool let consumers “Accept All” with one click while opting out took at least two, and that Honda, which sold, shared or disclosed website data to advertising technology companies, “could not produce contracts with these advertising technology companies”.[27] The order imposed a $632,500 fine and required, among other changes, a “Reject All” button, applying Global Privacy Control to known consumers, and better contract management.

For MarTechOps each finding maps to a control here: symmetric choices in the CMP, GPC honoured in tag logic and linked to known profiles, and a contract reference for every vendor in the tag register.

Scenario 2 (illustrative): a new two-way mapping overwrites a sales field

Link to section “Scenario 2 (illustrative): a new two-way mapping overwrites a sales field”

Scenario 3 (illustrative): tag bloat slows the site

Link to section “Scenario 3 (illustrative): tag bloat slows the site”

Measure behaviour, not tool or tag counts; funnel outcomes belong to MarketingOps and RevOps.

KPI Definition and formula Data source Pitfall Cadence
Consent-test pass rate Scenarios passing ÷ scenarios run Lab 1 in CI Too few regions or purposes Each release; monthly
Pre-consent firing Non-essential vendor requests before a choice in opt-in regions; target 0 Lab 1, crawls Hard-coded tags outside the container Monthly
Register coverage Tags with complete entries ÷ tags in the container Container export Entries without contracts Quarterly
Tracking-plan conformance Conforming events ÷ sampled events Lab 2, pipeline Sampling one site only Daily
Sync error rate and lag Errored ÷ synced records; 95th-percentile lag (minutes) Connector health, Lab 3 Averages hide the worst records Daily
Opt-out propagation 95th-percentile minutes from an unsubscribe to suppression in every sender Seeded test contacts; Lab 3 Checking one direction only; missing contacts outside the sync segment Weekly
Identity anomaly rate Profiles over identifier limits or in merge spikes ÷ profiles CDP or warehouse Limits set too high Weekly
Licence utilisation 90-day active users ÷ paid seats; cost ÷ active users Admin reports, SSO logs Activity is not value Before renewal

Worked calculation (illustrative month). Register coverage: 96 ÷ 120 tags = 80%. Consent tests: 58 ÷ 60 scenarios = 96.7%. Sync errors: 312 ÷ 48,000 = 0.65%. Opt-out propagation p95: 22 minutes against a 15-minute target, a breach. The webinar tool in Artefact 4: 7 ÷ 25 seats = 28%, or 18,000 ÷ 7 ≈ 2,571 per active user a year, the number for its renewal.

Vanity traps. Counts of integrations, tags or events collected say nothing about quality; modelled conversions are estimates, not observed counts.

Operational controls only; not legal advice. Rules differ by jurisdiction, and PrivacyOps owns the policy.

  • A tag manager deploys code. Publish rights mean running JavaScript on every page, checkout included. Limit Publish, require 2-step verification for risky changes,[22] and keep two administrators and no shared logins (Google will not add users to a locked-out account).[21]
  • Device access can need consent without cookies. The EDPB’s Guidelines 2/2023 (v2.0, 7 October 2024) treat tracking pixels and links as within Article 5(3) of the ePrivacy Directive, “even if this storage is not permanent”.[45]
  • Opt-out signals are law in some places, California and Colorado among them.[25] In California, sale or sharing must stop “as soon as feasibly possible, but no later than 15 business days” after a valid request.[10]
  • Contracts and integrations are part of the stack: a regulator may ask for each adtech vendor’s contract;[27] integrations need dedicated users with narrow permissions, rotated keys and removal at retirement.
  • Minimise payloads: no personal data in URLs, event names or free text (Lab 2 catches some).
  • Licences are usually the largest line MarTechOps can change (the Atlas’s judgement, not a survey finding). For scale, Gartner’s 2023 CMO Spend and Strategy Survey found organisations spending 25.4% of their 2023 marketing budget on technology.[6] Utilisation reviews before renewals are the lever.
  • New layers cost money to run: about $45 a month per Cloud Run tagging server in Google’s estimate, at least two recommended (May 2026);[40] warehouse compute for reverse ETL.
  • API capacity is a shared budget across every CRM integration.[34]
  • People time and sustainability: a tool nobody owns costs more than its licence; fewer tags mean less script on every visitor’s device (measure your own page weight with WebOps).

The cadences under operating model are the assurance loop. Share consent-test results with PrivacyOps, alert on every P1 conflict from Lab 3, and treat tags missing from the register as incidents until explained.

Symptom Likely cause Diagnosis Fix and prevention
Conversions fall sharply after a banner change CMP no longer sends the update; or defaults changed GTM preview: consent state before and after a click; Lab 1 Roll back; add the case to Lab 1 (see the runbook)
Vendors receive data before consent Tag hard-coded in page HTML; default set after a tag loads Browser network log with no interaction Move the tag into the manager; default first in the head
Conversions counted twice Pixel and Conversions API both send without matching event IDs Compare event IDs in both payloads Same ID and event name on both paths[39]
New leads missing in CRM API allocation exhausted; a validation rule rejects records Connector errors and API usage Raise allocation or move bulk jobs; map required fields
Messages reach the wrong person Profiles merged on a shared or hard-coded identifier Profiles with many identifiers; merge spikes Block junk values, set identifier limits, split profiles[36]
Marketing email lands in junk SPF permerror (over 10 lookups) or DMARC misalignment after adding a sender Message headers; DMARC aggregate reports Subdomain per sender; align DKIM[41]
Site error after a container publish Custom HTML error or conflicting script Console errors; diff of versions Revert to the previous version and publish[24]
Link to section “Worked runbook: conversions halved after a consent banner release”
Figure 5. Runbook for a consent-related tracking drop
noyesyesnoAlert: conversions down aftera releaseScope: which regions, tags,platformsReproduce with Lab 1 andGTM previewConsent state updated afteraccept?Roll back CMP config orcontainer versionTags firing before consent?Incident: inform PrivacyOpstodayReal change in consent rates:report, no fixValidate with Lab 1, watch 24hoursPost-incident: add test case,require QA environment
Diagram source (Mermaid)
flowchart TB
  A["Alert: conversions down after a release"] --> B["Scope: which regions, tags, platforms"]
  B --> C["Reproduce with Lab 1 and GTM preview"]
  C --> D{"Consent state updated after accept?"}
  D -->|"no"| E["Roll back CMP config or container version"]
  D -->|"yes"| F{"Tags firing before consent?"}
  F -->|"yes"| G["Incident: inform PrivacyOps today"]
  F -->|"no"| H["Real change in consent rates: report, no fix"]
  E --> I["Validate with Lab 1, watch 24 hours"]
  G --> I
  I --> J["Post-incident: add test case, require QA environment"]
  classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
  classDef decision fill:#fdf3e3,stroke:#c9800f,color:#122029
  classDef risk fill:#fbeceb,stroke:#b4332b,color:#122029
  class A,B,C,I,J core
  class D,F decision
  class E,G,H risk

Text equivalent: scope the drop and reproduce it with the consent test and the tag manager’s preview. If the consent state is not updated after accepting, roll back; if tags fired before consent, it is a privacy incident (inform PrivacyOps the same day); otherwise consent rates really changed: report, do not fix. Validate, watch 24 hours, add a test case and make the QA environment mandatory.

  1. Scope and reproduce (45 minutes). The drop is EEA-only and hits every tag that waits for consent. Lab 1 against live, EEA, “Accept all”: no analytics or ads requests; the tag manager’s preview shows the state still denied.
  2. Cause. The new CMP configuration renamed a purpose, so its template no longer maps it to ad_storage and analytics_storage.
  3. Act (MarTechOps lead; inform PrivacyOps and paid media). Revert to the previous, tested configuration. Do not “fix forward” by granting defaults, which would fire tags without consent.
  4. Validate and communicate. Lab 1 passes in every region. Conversions in the gap were not recorded and any modelled figures are estimates: annotate the reports. CMP changes become high-risk changes.
  • “Server-side tagging gets around consent and blockers.” It moves where tags run, not what you may collect (see the FAQ).
  • “A CDP will fix our data.” It unifies whatever it receives; without identity rules, a tracking plan and owners it unifies the mess faster.
  • “Two-way sync everything.” The last writer wins; give each field one writer, split “stage” into one field per team, and never let a sync clear an opt-out.
  • “Block old tags, we might need them.” Blocked tags still ship and weigh on the page;[20] remove them, the version history keeps the configuration.
  • “Give everyone Publish to move faster.” Speed comes from templates and a weekly window, not more publishers.
  • “One more tool will fix it.” Gartner’s respondents named ecosystem complexity among the most common barriers to using what they had.[6]

A dedicated MarTechOps role pays off when several of these hold: different consent rules across jurisdictions; more than one system writing customer fields; a CDP, server container or warehouse activation in use; ad spend that depends on conversion signals; sensitive or regulated customer data; renewals that have become hard to track.

Do not create a separate function when one MAP and one CRM connect natively, you sell in one jurisdiction and a few tags run on the site. Make the work a defined part of the marketing ops generalist’s role, use the quarterly checklist, and revisit as the stack grows; a team without enough work tends to add tools. Hidden responsibilities: a server container is a service to run, a CDP needs identity owners, warehouse activation needs data engineers.

The most consequential choice is where the customer profile lives. The tree is this Atlas’s starting point, not a rule.

Figure 6. Deciding where customer profiles should live
noyesnoyesnoyesDo you need profiles that joinseveral sources?Stay with MAP and CRM: noCDPIs there a warehouse with anowning data team?Packaged CDP, own-storeNeed real-time decisions inmilliseconds?Warehouse-native withreverse ETLHybrid: warehouse modelsplus real-time layerThen assign identity andconsent owners
Diagram source (Mermaid)
flowchart TB
  Q1{"Do you need profiles that join several sources?"}
  Q1 -->|"no"| N["Stay with MAP and CRM: no CDP"]
  Q1 -->|"yes"| Q2{"Is there a warehouse with an owning data team?"}
  Q2 -->|"no"| P["Packaged CDP, own-store"]
  Q2 -->|"yes"| Q3{"Need real-time decisions in milliseconds?"}
  Q3 -->|"no"| W["Warehouse-native with reverse ETL"]
  Q3 -->|"yes"| H["Hybrid: warehouse models plus real-time layer"]
  P --> R["Then assign identity and consent owners"]
  W --> R
  H --> R
  classDef decision fill:#fdf3e3,stroke:#c9800f,color:#122029
  classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
  classDef neutral fill:#f1f4f6,stroke:#5b7a87,color:#122029
  class Q1,Q2,Q3 decision
  class P,W,H core
  class N,R neutral

Text equivalent: without a need for cross-source profiles, stay with the MAP and CRM. With it but no warehouse and owning data team, use a packaged CDP; with them, warehouse-native activation, or a hybrid if decisions are needed in milliseconds. Every CDP path ends by assigning identity and consent owners.

Server-side tagging: go or no-go. Go when you must control what each vendor receives or cut page scripts, and can run a service. No-go when key vendors lack support (it “only works with some tags”),[20] when nobody can run the server, or when the real goal is collecting data people declined to share.

This is this Atlas’s model, not an industry standard.

Level Observable behaviour Exit criteria to the next level
1. Accidental Tags added by whoever needs them; no inventory; shared logins Register exists; two named admins per system
2. Inventoried Owners, purposes and contracts recorded Field contract agreed; change classes and QA environment in use
3. Governed Changes through workspaces and review; consent defaults by region Automated consent and tracking-plan checks
4. Tested Lab 1–3 style checks run automatically; monthly metric review Opt-out and freshness targets met for a quarter
5. Run as a product Roadmap, service levels, cost per capability; yearly rationalisation Sustain; revisit when law or architecture changes
Window Actions Output and metric
Days 1–30 Build the register from the container and tool list; end shared logins; run Lab 1 by hand Register coverage; first consent results
Days 31–60 Field contract (with RevOps); change classes; QA environment; remove dead tags; email authentication Contract signed; DMARC reports flowing
Days 61–90 Lab 1 in CI; daily reconciliation; tracking plan for top events; one utilisation review Tests on every release; one renewal decided on evidence

It depends on RevOps, PrivacyOps, the DNS owner, a data engineer and leaders willing to retire tools.

New tag preflight

  • Register entry complete: purpose, owner, vendor, data sent, consent purpose, contract reference, review date
  • Vendor template used, or Custom HTML justified in writing
  • Consent requirement set on the tag; behaviour checked with and without consent and with GPC
  • No personal data in URLs, event names or free-text properties
  • Tested in the QA environment; page errors and script time checked
  • Rollback version noted; published by someone other than the builder

CMP or container release

  • Lab 1 passes for every region and purpose; denied defaults still load before the tag manager
  • Reject still as easy as accept; consent records still exported

Quarterly review

  • Container diffed against the register; unknown tags explained or removed
  • Access lists for tag manager, MAP, CRM, CDP and warehouse reviewed; leavers removed
  • Sync error, lag and opt-out propagation metrics within targets, both directions
  • Opt-outs checked for contacts outside the CRM–MAP sync segment
  • Tools with renewals in the next two quarters have a utilisation review scheduled

Tool sunset

  • Data exported; vendor deletion confirmed; tags, keys, integration users, SSO app and DNS records removed
  • Licence cancelled before the notice date; inventory updated

Tool evaluation scorecard (weights are a suggestion; agree them before seeing vendors)

TOOL EVALUATION  | Tool: ____________ | Requested by: ________ | Date: ________
Criterion (weight)                           Score 1-5   Evidence
Integration with CRM/MAP/warehouse (30%)     ___         connector docs, API limits
Consent and privacy handling (20%)           ___         consent API, GPC, DPA, region
Data model fit and identity (15%)            ___         fields, objects, identifiers
Admin, access and audit (10%)                ___         SSO, roles, audit log
Overlap with existing tools (10%)            ___         inventory check
Total cost incl. people time (15%)           ___         licence, run cost, admin hours
Exit: data export and deletion terms         yes/no      contract clause
Decision: adopt / pilot / reject   Owner after adoption: ____________

Stack change record

CHANGE  | ID: ______ | Class: standard / high-risk | Requested: ________
What changes (tags, mappings, integrations): ________________________________
Systems and regions affected: ______________________________________________
Data or consent impact (new vendor? new data type?): _______________________
Tests run (Lab 1 / Lab 2 / Lab 3, QA environment): ________________________
Rollback (version number or steps): ________________________________________
Reviewer: ________  Publisher: ________  Published at (UTC): ______________
Approach Strengths Limits Choose when
Client-side tag manager Simple; universal vendor support Vendor code on visitors’ devices Few vendors, small team
Server-side container Payload control; less page code A service to run; partial vendor support Many vendors; data-control needs
Packaged CDP Fast start; built-in identity Duplicates data; cost scales with profiles No warehouse team
Warehouse-native activation One copy of data; reuses models Needs data engineers; real time is harder; consent state must be loaded Mature warehouse and team

Is MarTechOps the same as marketing operations? Mostly: it is their technology and data pillar; the Atlas splits the pages to go deeper.

Do we need a CDP? Only if you need profiles combining several sources and can name owners for identity and data quality (see the decision framework).

Does server-side tagging let us track people who declined cookies? No. Consent travels into the server container,[38] and the EDPB reads device access broadly, pixels included.[45] In advanced mode Google tags send cookieless pings with or without a server container;[9] whether that is allowed is a legal decision (see the judgement call).

Should the tag manager belong to marketing or engineering? To whoever can apply change control. A common split: marketing engineers build, a small group publishes, and web engineering reviews high-risk changes and owns performance budgets with WebOps.

Who owns email authentication? The DNS owner is accountable; MarTechOps knows which tools send as the domain and requests changes; MarketingOps checks campaign headers.

  • Signals for known people. California applies opt-out signals to the consumer if known,[10] which makes cross-device consent an identity problem.
  • Measurement after third-party cookies. With the Privacy Sandbox retirement, Google said it would work on an interoperable attribution standard at the W3C;[12] treat that as future work.
  • More consent strings. IAB Tech Lab’s Global Privacy Protocol carries US state sections alongside the TCF;[15] test them.
  • CDP functions moving into warehouses[4] shift the work towards data contracts and tests.
Stage What to learn and do
Prerequisites HTTP requests and headers, cookies, DNS; JSON; basic SQL
1-day primer This page and MarketingOps; list every third-party request in your site’s network log
1 week Labs 1–3; Google’s consent mode guide; a draft tag register
30 days Register and field contract for a real stack; automate Lab 1; one utilisation review
Specialise Server-side tagging; identity and warehouse activation; PrivacyOps; AdOps
Portfolio A consent-test suite, a tracking plan in CI, a documented tool sunset
Topic Remember
What it is The technology and data side of marketing operations (an overlapping synonym; the split is editorial)
Core artefacts Tag register, field contract, tracking plan, tool inventory, consent test suite
Controls Denied defaults before tags; GPC honoured where required; few publishers; QA environment; rollback
Metrics Consent-test pass rate, pre-consent firing (target 0), sync lag, opt-out propagation, licence use
Watch-outs Over-merged identities, fields with two writers, opt-outs a sync can clear, tags blocked instead of removed
Next action Export the container and tool list and build the register this month
Link to section “A judgement call: basic or advanced consent mode in the EEA?”

Situation. A retailer selling across the EEA uses Google Ads and Analytics. Paid media wants advanced consent mode, which Google says gives “an advertiser-specific model as opposed to a general model”.[9] The privacy team hesitates.

Option A: advanced. Google tags load before the choice with defaults denied and send cookieless pings while consent is denied.[9] GA4 modelling also needs volume: at least 1,000 events a day with analytics storage denied for 7 days, and 1,000 daily users with it granted on 7 of the previous 28 days, without guaranteed eligibility.[53]

Option B: basic. Google tags wait for an interaction; with no consent nothing is sent, not even the status, and Ads modelling uses a general model.[9] GA4 behavioural modelling is lost: it needs tags loaded before the consent dialog (the advanced implementation).[53]

Assumptions. Counsel reads the EDPB guidelines, under which Article 5(3) applies to pixels and tracking links “even if this storage is not permanent”.[45] No regulator decision specifically on Google’s cookieless pings was found for this page. Traffic would meet the modelling thresholds.

Why the attractive option can be wrong. Advanced mode improves reported numbers, but whether a pre-consent ping is lawful is a question about device access, not measurement. If counsel concludes it needs consent, a modelling gain does not offset the risk; if not, advanced mode may be reasonable, with the reasoning recorded.

Process. MarTechOps captures what each mode sends before and after a choice (Lab 1 with network capture); PrivacyOps and counsel decide per region, recording reasoning and a review date, because the uncertainty is legal; MarTechOps implements and tests monthly.

You should now be able to explain how MarTechOps differs from its neighbours; design a consent-signal path and a CRM–MAP field contract; test consent behaviour and event quality; choose where profiles live; and run a stack review that ends in decisions.

1. A tag fires in the EEA before the banner is answered, but defaults show denied. Name two likely causes.

The tag is hard-coded outside the tag manager, so consent settings never apply; or the default command runs after tags start. A non-Google tag with no consent requirement is a third possibility.

2. Why is “Two-way” a risky sync rule for a stage field, and what is different about HubSpot’s lifecycle stage?

The most recent value wins and deletions propagate, so any system or bulk job writing a custom stage field overwrites the other; “Prefer Salesforce unless blank” fails too, as Salesforce wins after the first value. Give each field one writer: a MAP-written marketing stage, read-only in Salesforce, and a sales stage on “Always use Salesforce”. HubSpot’s default Lifecycle stage only moves forward, the Salesforce integration included, so its risk is stale stages after disqualification, handled by a workflow that clears the value.

3. A vendor says going server-side will “recover” conversions lost to consent refusals. Your answer?

Server-side changes where code runs, not what people agreed to; consent must still be honoured in the server container. Any “recovery” comes from modelling, which is an estimate.

4. One CDP profile holds 40 email addresses. What happened and what do you change?

A shared or placeholder identifier (a hard-coded test user_id, “anonymous”, a shared device ID) linked unrelated records. Split the profile, block the value, set identifier limits and priorities, and alert on profiles over the limit.

5. California requires honouring GPC. Which part is MarTechOps’ job?

Detecting Sec-GPC and navigator.globalPrivacyControl, mapping the signal to the purposes counsel classes as selling or sharing, linking it to known profiles where policy says so, and testing it. The classification is PrivacyOps’ and counsel’s.

6. A tool has 25 paid seats, 7 active users and renews in 60 days. What do you bring?

Utilisation (28%), cost per active user, what the tool produced, overlap, exit costs, the notice date, and a recommendation (right-size, consolidate or retire) with an owner and, if retiring, a sunset plan.

MarTechOps is not a new discipline. It is the part of marketing operations that treats the stack as plumbing: pipes that move data, consent signals that act as valves, and a register of who owns each piece. A consent choice that never reaches a tag, a sync that clears an opt-out or a profile merged on a placeholder can do more harm than a failed campaign, and none shows on a marketing dashboard until it is expensive. Keep the register, change the stack through a pipeline, test behaviour rather than settings, and remove tools as deliberately as you add them.

Further reading.

  • State of Martech 2025 (Brinker and Riemersma): the full survey, linked from the landscape post.
  • research/martechops-ledger.md: every source, what it supports, and what could not be verified.

Changelog.

  • 2026-10-23, first version (r0): researched and written; the three labs executed on local fixtures; awaiting independent fact check.
  • 2026-10-23, r1 revision after independent review: safe consent defaults and template allowlist; one-way opt-outs; HubSpot lifecycle rule; Gartner 2025 figure; Colorado GPC; Labs 2–3 re-run; diagrams, glossary, footnotes fixed.
  • 2026-10-23, r2 revision after scoring: the shared stage field split into a MAP-written and a CRM-written field (Artefact 3, Scenario 2, sync playbook, mastery question 2); GA4 modelling needs advanced mode; repetition trimmed.
  • 2026-10-23, post-score polish: Gmail and Outlook.com sender thresholds stated precisely; Gartner “most common” barriers; lifecycle incident claim softened; HubSpot resync wording.

  1. MarTech Operations Specialist (PriceShape ApS) — The Hub job listing (one posting). Checked 2026-10-23. ↩︎

  2. We’re Hiring: MarTech Operations Associate at World 50 Group — Clay community, 2026-02-07. Checked 2026-10-23. ↩︎

  3. The state of marketing operations professionals is OK, but it’s going to get much, much better — Scott Brinker, chiefmartec, 2024-11-10. Checked 2026-10-23. ↩︎ ↩︎

  4. 2025 Marketing Technology Landscape Supergraphic: 100X growth since 2011, but now with AI — Scott Brinker (with Frans Riemersma), chiefmartec, 2025-05-06. Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  5. Marketing Technology (topic page) — Gartner, undated, on its 2025 survey (read on the mirror host gcom.pdo.aws.gartner.com). Checked 2026-10-23. ↩︎

  6. Gartner Survey Finds 63% of Marketing Leaders Plan to Invest in Generative AI in the Next 24 Months — Gartner, 2023-08-23 (read on Gartner’s mirror host gcom.pdo.aws.gartner.com). Checked 2026-10-23. ↩︎ ↩︎ ↩︎

  7. Gartner confirms 70% have chief marketing technologist — Scott Brinker, chiefmartec, 2013-03-13. Checked 2026-10-23. ↩︎

  8. Transparency and Consent Framework — IAB Europe. Checked 2026-10-23. ↩︎ ↩︎ ↩︎

  9. Consent mode overview — Google for Developers, updated 2026-07-30. Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  10. California Consumer Privacy Act Regulations, effective 1 January 2026 — California Privacy Protection Agency, §§7025–7026. Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  11. Tracking Prevention in WebKit — WebKit. Checked 2026-10-23. ↩︎ ↩︎

  12. Update on Plans for Privacy Sandbox Technologies — Google, 2025-10-17. Checked 2026-10-23. ↩︎ ↩︎

  13. Restrict tag deployment — Google for Developers, updated 2026-07-30. Checked 2026-10-23. ↩︎ ↩︎ ↩︎

  14. Workspaces — Tag Manager Help, Google. Checked 2026-10-23. ↩︎

  15. Global Privacy Protocol (GPP) — IAB Tech Lab. Checked 2026-10-23. ↩︎ ↩︎ ↩︎

  16. What Is a CDP? Customer Data Platform Meaning and Definition — CDP Institute, 2026 definition. Checked 2026-10-23. ↩︎ ↩︎ ↩︎

  17. Data activation concepts — Hightouch Docs. Checked 2026-10-23. ↩︎ ↩︎

  18. Set up consent mode on websites — Google for Developers, updated 2026-10-13. Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎

  19. Publishing flow — Adobe Experience League, updated 2026-10-21. Checked 2026-10-23. ↩︎

  20. Best practices for tags and tag managers — Katie Hempenius and Barry Pollard, web.dev, published 2021-07-29, updated 2022-08-24. Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  21. Managing users and permissions — Tag Manager Help, Google. Checked 2026-10-23. ↩︎ ↩︎

  22. Tag Manager and 2-step verification — Tag Manager Help, Google. Checked 2026-10-23. ↩︎ ↩︎

  23. Environments — Tag Manager Help, Google. Checked 2026-10-23. ↩︎

  24. Publishing, versions, and approvals — Tag Manager Help, Google. Checked 2026-10-23. ↩︎ ↩︎ ↩︎

  25. Universal Opt-Out and the Colorado Privacy Act — Colorado Attorney General. Checked 2026-10-23. ↩︎ ↩︎

  26. Global Privacy Control (GPC) — W3C Privacy Working Group, Working Draft, 2026-09-24. Checked 2026-10-23. ↩︎ ↩︎

  27. Stipulated Final Order, In the Matter of American Honda Motor Co., Inc. (ENF23-V-HO-2) — California Privacy Protection Agency, 2025-03-07. Checked 2026-10-23. ↩︎ ↩︎ ↩︎

  28. EU user consent policy — Google. Checked 2026-10-23. ↩︎ ↩︎

  29. Understanding the Salesforce Sync — Adobe Experience League, updated 2026-10-07. Checked 2026-10-23. ↩︎

  30. Map HubSpot properties to Salesforce fields — HubSpot Knowledge Base, updated 2026-09-16. Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎

  31. Use contact and company lifecycle stages — HubSpot Knowledge Base, updated 2026-10-20. Checked 2026-10-23. ↩︎ ↩︎

  32. Sync Salesforce leads and contacts to HubSpot — HubSpot Knowledge Base, updated 2026-08-31. Checked 2026-10-23. ↩︎ ↩︎

  33. Control Access to Fields — Salesforce Trailhead, Data Security module. Checked 2026-10-23. ↩︎ ↩︎

  34. Connect HubSpot and Salesforce — HubSpot Knowledge Base (formerly titled “Install the HubSpot–Salesforce integration”), updated 2026-10-16. Checked 2026-10-23. ↩︎ ↩︎ ↩︎

  35. Manage your Salesforce integration settings — HubSpot Knowledge Base, updated 2026-08-12. Checked 2026-10-23. ↩︎

  36. Identity Resolution Settings — Twilio Segment Docs. Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎

  37. An introduction to server-side tagging — Google for Developers, updated 2026-07-30. Checked 2026-10-23. ↩︎ ↩︎

  38. Implement consent mode with server-side Tag Manager — Google for Developers, updated 2026-07-30. Checked 2026-10-23. ↩︎ ↩︎

  39. Handling Duplicate Pixel and Conversions API Events — Meta for Developers (read via WebFetch). Checked 2026-10-23. ↩︎ ↩︎

  40. Cloud Run setup guide — Google for Developers, updated 2026-05-12. Checked 2026-10-23. ↩︎ ↩︎

  41. RFC 7208: Sender Policy Framework (SPF) — IETF, April 2014. Checked 2026-10-23. ↩︎ ↩︎ ↩︎

  42. RFC 9989: Domain-Based Message Authentication, Reporting, and Conformance (DMARC) — IETF, May 2026. Checked 2026-10-23. ↩︎ ↩︎ ↩︎

  43. Email sender guidelines — Google Workspace Admin Help. Checked 2026-10-23. ↩︎

  44. Policies, Practices, and Guidelines — Outlook.com Postmaster. Checked 2026-10-23. ↩︎

  45. Guidelines 2/2023 on Technical Scope of Art. 5(3) of ePrivacy Directive, version 2.0 — European Data Protection Board, adopted 2024-10-07. Checked 2026-10-23. ↩︎ ↩︎ ↩︎ ↩︎

  46. RFC 8058: Signaling One-Click Functionality for List Email Headers — IETF, January 2017. Checked 2026-10-23. ↩︎

  47. Tags overview — Adobe Experience League, updated 2026-10-21. Checked 2026-10-23. ↩︎

  48. Getting started with Tag Manager — Matomo. Checked 2026-10-23. ↩︎

  49. rudderlabs/rudder-server — RudderStack, GitHub. Checked 2026-10-23. ↩︎

  50. Protocols Tracking Plan — Twilio Segment Docs. Checked 2026-10-23. ↩︎

  51. Schemas and data structures — Snowplow Docs. Checked 2026-10-23. ↩︎

  52. Optimize Largest Contentful Paint — web.dev, updated 2025-03-31. Checked 2026-10-23. ↩︎

  53. Behavioral modeling for consent mode — Google Analytics Help. Checked 2026-10-23. ↩︎ ↩︎

Related Ops

MarketingOps

MarketingOps (marketing operations) runs marketing as a dependable system: campaigns built and checked to a standard, leads captured with consent, scored and followed up by sales under an agreed service level, and pipeline measurement people can trust.

RevOps

RevOps (revenue operations) aligns marketing, sales and customer success around one set of funnel definitions, one trusted customer record, governed hand-offs and one forecast, so the revenue process can be measured and improved end to end.

AdOps

AdOps (advertising operations) turns sold or auctioned ad space into delivered, measured and billable impressions: it sets up and checks campaigns in the ad server, runs the auction plumbing, keeps fraud and unauthorised sellers out, and reconciles the numbers.

PrivacyOps

PrivacyOps is a vendor-coined name for running a privacy programme as an operation: knowing which personal data you hold and why, and meeting each person's rights, the impact assessments and breach duties on time, with evidence.

AnalyticsOps

AnalyticsOps has no standard definition. On this page it means operating the layer where people consume data: versioned metric definitions, a semantic layer that serves them, and BI content that is certified, monitored and retired, so each important metric has one trusted definition.

WebOps

WebOps is a loose label for running websites: the path from DNS through CDN, TLS and web servers to the browser, operated by developers and marketers who share one site. No body defines it; vendors also use it as a product category.

IntegrationOps

IntegrationOps is the work of running system-to-system integrations as owned production flows: messages that may arrive twice, late or broken are deduplicated, parked, replayed and reconciled so that no business record is silently lost.

DataOps

DataOps is the practice of delivering and running data pipelines with software discipline: changes are versioned and tested in CI, each load is checked before consumers see it, and data is monitored after, so correct data arrives on time. The label is real but not standardised.

Practise and get certified

From xOps School

Practise MarTechOps and get certified

The MarTechOps track on xOps School (part of the Coffee Pass) has study notes, a 25-question practice quiz with explanations, and a verifiable certificate when you score 70% or more. Sign in with Google to start.

For teams

Instructor-led training

Live batches for your team, with completion certificates and reports for L&D/HR.

Source: master.md (the editorial source of this page) · built 2026-10-23 · diagrams rendered with @mermaid-js/mermaid-cli 11.17.0 (mermaid 11.17.2)