⋯ 652 unchanged lines
<span class="badge">Staging <b>4017466</b></span>
<span class="badge">Dev <b>4002103</b></span>
<span class="badge warn">Prod is behind — see §Naming</span>
<span class="badge warn">v1.2 adds marketing attribution (§3b) — see below</span>
<span class="badge warn">v1.2 adds marketing attribution (§3b) — see changelog at bottom</span>
</div>
</div>
</header>
<nav class="jumpnav" aria-label="Section navigation">
<div class="jumpnav-inner">
<a href="#whatchanged">What changed</a>
<a href="#tryit">Try it</a>
<a href="#touchsemantics">Touch semantics</a>
<a href="#chain">The chain</a>
<a href="#timing">Timing rules</a>
<a href="#code">Code</a>
<a href="#serverjoin">Server join</a>
<a href="#naming">Naming</a>
<a href="#dpdp">DPDP</a>
<a href="#verify">Verify</a>
<a href="#pins">Open pins</a>
<a href="#whatchanged">Changelog</a>
</div>
</nav>
<main>
<section id="whatchanged">
<p class="section-label">Chief PM review (v1.1) + marketing attribution (v1.2)</p>
<h2>What changed</h2>
<p class="lede">Two revisions today. v1.1 corrected claims that turned out to be wrong against the committed enums file. v1.2 is additive: a whole new attribution contract for non-affiliate marketing links that didn't exist before.</p>
<h3 style="margin-top:4px;">v1.2 — marketing attribution added (new, not a correction)</h3>
<div class="pin-list">
<div class="pin">
<p><strong>A third load-bearing output.</strong> Alongside <code>acquisition_source</code> and <code>marketing_affiliate_id</code>, every session must now carry a full set of <code>mx_*</code> campaign-context super props — <code>mx_channel</code>, <code>mx_phase</code>, <code>mx_episode</code>, <code>mx_recipe</code>, <code>mx_asset</code>, <code>mx_placement</code>, <code>mx_aff</code>. This is what feeds the Channels tab, the Saturday readout, and per-creative analysis. Previously about half the <code>param_map</code> was unmapped to anything.</p>
</div>
<div class="pin">
<p><strong>Touch semantics — the new hard part.</strong> Profile fields (<code>acquisition_source</code>, <code>marketing_affiliate_id</code>) stay first-touch immutable, but the <code>mx_*</code> super props are <strong>latest-touch</strong> — overwritten on every new tagged open, left alone on organic opens. Getting this backwards (e.g. <code>$set_once</code>-ing the super props, or clearing them on organic opens) silently breaks channel/creative attribution. See the interactive walkthrough below.</p>
</div>
<div class="pin">
<p><strong>A second verify test</strong> (§8) specifically for marketing links, including a "tap a second link, different channel" step to confirm the overwrite behavior actually happens.</p>
</div>
</div>
<h3 style="margin-top:20px;">v1.1 — corrections against the committed enums file</h3>
<div class="pin-list">
<div class="pin">
<p><strong>Fixed a fabricated claim.</strong> v1.0 said the <code>acquisition_source</code> rollup "lives in <code>mixxi_attribution_enums.json</code>." It doesn't — no such group exists in the committed file. Now an explicit open pin with a safe interim (write the raw <code>channel</code> value).</p>
</div>
<div class="pin">
<p><strong>Fixed <code>funding</code> values.</strong> <code>organic</code>/<code>paid</code> → <strong><code>organic</code>/<code>sponsorship_funded</code></strong> — the only two values that exist in the enum.</p>
</div>
<div class="pin">
<p><strong>Fixed event-prop names to the committed <code>param_map</code>.</strong> <code>persona</code>/<code>funding_type</code>/<code>distribution_layer</code>/<code>owner_team</code>/<code>cta</code> → <strong><code>mx_persona</code>/<code>mx_funding</code>/<code>mx_layer</code>/<code>mx_team</code>/<code>mx_cta</code></strong>. MMRP's dashboards query the <code>mx_*</code> names — the v1.0 names would land in Mixpanel but be invisible to every MMRP surface.</p>
</div>
<div class="pin">
<p><strong>Added the missing <code>sub_param_ad_platform</code> → <code>mx_ad_platform</code> row</strong> (paid links only — present when <code>funding=sponsorship_funded</code>, omitted for organic).</p>
</div>
<div class="pin">
<p><strong>Updated the <code>vote_cast</code> pin</strong> with Unravel ownership and the preferred server-side-emit resolution; added a new pin on the <code>signup_complete</code> payout re-point.</p>
</div>
</div>
</section>
<section id="tryit">
<p class="section-label">Interactive — §3</p>
<h2>Click any link parameter to see where it lands</h2>
⋯ 281 unchanged lines
<div class="pin">
<span class="pin-tag">New in v1.1 — MMRP action item</span>
<p><strong>Pin #4 — <code>signup_complete</code> as the payout event.</strong> This guide standardises on <code>signup_complete</code> (the only signup event that exists in any environment). MAP payout logic historically referenced <code>account_created</code>; re-pointing it to <code>signup_complete</code> is an MMRP action item, tracked separately. App-side: emit <code>signup_complete</code>, never <code>account_created</code>.</p>
</div>
</div>
</section>
<section id="whatchanged">
<p class="section-label">Chief PM review (v1.1) + marketing attribution (v1.2)</p>
<h2>Changelog — what changed</h2>
<p class="lede">Two revisions today. v1.1 corrected claims that turned out to be wrong against the committed enums file. v1.2 is additive: a whole new attribution contract for non-affiliate marketing links that didn't exist before.</p>
<h3 style="margin-top:4px;">v1.1 — corrections against the committed enums file</h3>
<div class="pin-list">
<div class="pin">
<p><strong>Fixed a fabricated claim.</strong> v1.0 said the <code>acquisition_source</code> rollup "lives in <code>mixxi_attribution_enums.json</code>." It doesn't — no such group exists in the committed file. Now an explicit open pin with a safe interim (write the raw <code>channel</code> value).</p>
</div>
<div class="pin">
<p><strong>Fixed <code>funding</code> values.</strong> <code>organic</code>/<code>paid</code> → <strong><code>organic</code>/<code>sponsorship_funded</code></strong> — the only two values that exist in the enum.</p>
</div>
<div class="pin">
<p><strong>Fixed event-prop names to the committed <code>param_map</code>.</strong> <code>persona</code>/<code>funding_type</code>/<code>distribution_layer</code>/<code>owner_team</code>/<code>cta</code> → <strong><code>mx_persona</code>/<code>mx_funding</code>/<code>mx_layer</code>/<code>mx_team</code>/<code>mx_cta</code></strong>. MMRP's dashboards query the <code>mx_*</code> names — the v1.0 names would land in Mixpanel but be invisible to every MMRP surface.</p>
</div>
<div class="pin">
<p><strong>Added the missing <code>sub_param_ad_platform</code> → <code>mx_ad_platform</code> row</strong> (paid links only — present when <code>funding=sponsorship_funded</code>, omitted for organic).</p>
</div>
<div class="pin">
<p><strong>Updated the <code>vote_cast</code> pin</strong> with Unravel ownership and the preferred server-side-emit resolution; added a new pin on the <code>signup_complete</code> payout re-point.</p>
</div>
</div>
<h3 style="margin-top:20px;">v1.2 — marketing attribution added (new, not a correction)</h3>
<div class="pin-list">
<div class="pin">
<p><strong>A third load-bearing output.</strong> Alongside <code>acquisition_source</code> and <code>marketing_affiliate_id</code>, every session must now carry a full set of <code>mx_*</code> campaign-context super props — <code>mx_channel</code>, <code>mx_phase</code>, <code>mx_episode</code>, <code>mx_recipe</code>, <code>mx_asset</code>, <code>mx_placement</code>, <code>mx_aff</code>. This is what feeds the Channels tab, the Saturday readout, and per-creative analysis. Previously about half the <code>param_map</code> was unmapped to anything.</p>
</div>
<div class="pin">
<p><strong>Touch semantics — the new hard part.</strong> Profile fields (<code>acquisition_source</code>, <code>marketing_affiliate_id</code>) stay first-touch immutable, but the <code>mx_*</code> super props are <strong>latest-touch</strong> — overwritten on every new tagged open, left alone on organic opens. Getting this backwards (e.g. <code>$set_once</code>-ing the super props, or clearing them on organic opens) silently breaks channel/creative attribution. See the interactive walkthrough above.</p>
</div>
<div class="pin">
<p><strong>A second verify test</strong> (§8) specifically for marketing links, including a "tap a second link, different channel" step to confirm the overwrite behavior actually happens.</p>
</div>
</div>
</section>
⋯ 334 unchanged lines