Standing instructions, James Rosewell, 15 September 2026. Every test in
this programme runs against the template as changed on A's branch of
javascript-templates, never against the template inside the published
FiftyOne.Pipeline.JavaScriptBuilder 4.5.104 package or the pipeline-dotnet
Templates submodule as it stands on main. A test that passes against the
old template counts as not run. Everything is proved locally before anything
is pushed, local branches and commits are expected, and every pull request
opens as a draft. The parent issue carries the three instructions in full.
Work package of the create last programme, which is tracked internally. One
agent, this repository, one pull request. The structure and the diagram can
be written now from the work packages, and the pages are published with the
cloud release that carries the PMP change, not before, because they
describe behaviour that release introduces.
James Rosewell, 15 September 2026: "All this needs to be in the developer
documentation. We might need to break it down into more sub pages to better
explain the different features. We do need a diagram that shows the load
process."
Today
src/identifiers/pmp.md is 83 lines with six headings, being Endpoint,
Integration, Configuration attributes, id.usage mapping, Flow,
localStorage and Cross-references. It documents the Preference Management
Platform as one page. The 51Did page is src/identifiers/fodid.md beside
it, with overview.md and index.md. The cloud repository's pmp/README.md
is 982 lines and is the developer reference the page condenses, and it is
being changed by the PMP work package in the same programme.
The split
Turn pmp.md into a folder, src/identifiers/pmp/, with one page per
feature, each short enough to read in one sitting, and an index that
carries the diagram.
index.md. What the platform is, the two cards, and the load process
diagram, a mermaid sequence with these actors in this order: the
browser, the page, the PMP loader tag, the PMP bundle (asynchronous), the
cloud, and the 51Did client script. It shows the PMP loader fetching the
bundle; the bundle's init() reading local storage, else reading the
shared store through the third party cookie and showing nothing when an
answer comes back; the answer being announced on the window and held in
memory behind the getter; the client script's construction reading the
getter or the local key, registering for the event and for __tcfapi, making its first request
and running the snippets; the first card being answered; the event, the
script's refresh(), the request that carries the usage and every snippet
result, and the 51Did coming back; the second card following at once with
the third party cookie result already known; and the shared write. Show as
a branch the case where the page carries no client script and the platform
adds it. Show both tag orders in a note, because the bundle is
asynchronous.
integration.md. The two tags, the object name and the optional
data-object-name attribute which defaults to fod, the action URL as an
optional hook and no longer the way the script is loaded, and load order.
What happens with no client script on the page is the part to get
right, because from 15 September 2026 the platform adds the script itself,
using the resource key and the cloud origin it already holds, and logs
that it did. Document that as the normal, expected behaviour and a
convenience, and say that a publisher who puts the client script tag on
the page themselves keeps full control of its parameters. It is why
data-object-name exists.
preferences.md. The three values, what each means under the Model
Terms, the local storage key __51d_pmp_pref, the window
event 51d-pmp-preference, the getter window.__51d_pmp.preference(),
and the TCF surface the platform exposes as window.__tcfapi. It says
that the alternative answer, non-marketing, is an answer under the
Model Terms and not a refusal, that the TCF surface answers
(null, false) after it, which is only the TCF view of a usage granting
no purposes, and that the PMP is a technically complete TCF implementation
that does not follow the TCF Policies, so a site running a TCF consent
management platform does not add the PMP and the PMP is not a substitute
for one where those policies are required.
sharing.md. The network name, the third party cookie result taken from
the client script's object, the shared store
(naming the endpoint /api/v4/pmp/pref and the cookie
51D_PmpPreference_<code>, and saying another platform could implement
the same exchange, because the shared store and the second card are PMP
only), the second card, the result being taken from the client script's
device.thirdpartycookiesenabled, with the platform adding that script
when the page carries none, and that nothing waits between the cards.
isgdpr.md. What IsGdpr is and where it comes from (a derived property
from the request's country, entitled through the resource key, requested
by name), and the PMP path: the loader sets gdprApplies from
fod.derived.isgdpr when the client script object carries it, logs a
warning against the PMP and leaves it true when it does not, and the
dialog is still shown and a 51Did still created either way, because the
question is contractual.
cmp-wiring.md, the page for a site running a third party consent
platform, in this order. That the PMP is a technically complete TCF
implementation that does not follow the TCF Policies, so a site running a
CMP does not add the PMP, and the two never share a page.
Load order, being that the CMP's inline __tcfapi stub must precede the
51Degrees script tag, as the TCF specification already requires, that a
CMP loading later is fine because the stub queues the registration, and
that a stub missing at construction has no recovery on that page view
and the block's console warning is the only signal. IsGdpr, being what
to read (derived.isgdpr, under the derived section of the client
script's response, a boolean, after the first round completes through
the script's complete callback, absent when the resource key does not
request it), how to pass it (the principle plus one worked example
against a stubbed CMP, with the vendor's own documentation for the real
call, since we do not document another vendor's API), which wins (the
CMP's setting always, IsGdpr unused if they choose the CMP's own
detection), and the consequence (no string from the CMP means no request
carrying an answer and no 51Did). That a string granting too little for
either usage creates nothing, as today. And in one sentence what a CMP
site does not get, being the shared store and the second card. This page
cannot be finished until IsGdpr is live, which waits on
pipeline-dotnet#413
and then the cloud service's own change, so it
ships with a placeholder until then.
fodid.md, the existing 51Did page, gains a section on the user prompt
block: that the script gathers the answer itself from the PMP first and a
framework platform second, that a GPP string is not read because the
Model Terms do not map it, that refresh() exists and when to call it,
that the identifier is created on the request that carries every snippet
result, that a change of answer produces a fresh identifier and calls
onChange, that the iterations of a page view stop at the server's
maximum with a console message, what the signal source flag records, and
that the cache record keeps the inputs of the last request in session
storage on the publisher's origin. It also states the server's order:
id.usage is read first, then the framework string, a stated usage is
always used when present and any string beside it is not read, the flag
records which one was used, and the "no 51Did when a United States
section is present" ruling therefore applies to a request whose only
signal is that string.
configuration.md. The attribute table, with data-object-name added as
an optional attribute defaulting to fod, and data-timeout described as
bounding the shared read only.
- The privacy policy wording, on
sharing.md or a page of its own,
whichever reads better. It covers the shared answer, the third party
cookie, the session storage record and the 51Did, is marked clearly as
not legal advice, and points at the existing
Client Services Policy,
which is how src/pipelineapi/features/clientsideevidence.md already
handles the same problem under its "Privacy Policy" heading. James
Rosewell's decision of 15 September 2026 is that this is written here as a
draft and reviewed by Tracy Barlow through an issue raised internally,
not by email. Mark the section as awaiting that review.
Every page ends with a "Find out more" section giving the repositories as
bare URLs and the 51degrees.com links tagged with the five parameter UTM
convention that common-ci/scripts/utm-lint.ps1 enforces (utm_source,
utm_medium, utm_campaign equal to the lowercase repository name,
utm_content, utm_term). Run that script against the repository before
pushing.
Sources of truth
Write from the work packages and the code, not from memory. The PMP source
is pmp/src in the cloud repository, the client script is
JavaScriptResource.mustache on javascript-templates main, the property
definitions are in the shared property metadata, and the Model Terms are
the versioned
text at https://m4ow.uk/mtm/2.txt. Reference the exact version of the
terms in force, never the explainer page, because a document that can be
edited under the reader cannot prove what an identifier agreed to.
Not part of this
The Prebid module's documentation, which lives in its own repository.
Standing instructions, James Rosewell, 15 September 2026. Every test in
this programme runs against the template as changed on A's branch of
javascript-templates, never against the template inside the published
FiftyOne.Pipeline.JavaScriptBuilder4.5.104 package or the pipeline-dotnetTemplatessubmodule as it stands onmain. A test that passes against theold template counts as not run. Everything is proved locally before anything
is pushed, local branches and commits are expected, and every pull request
opens as a draft. The parent issue carries the three instructions in full.
Work package of the create last programme, which is tracked internally. One
agent, this repository, one pull request. The structure and the diagram can
be written now from the work packages, and the pages are published with the
cloud release that carries the PMP change, not before, because they
describe behaviour that release introduces.
James Rosewell, 15 September 2026: "All this needs to be in the developer
documentation. We might need to break it down into more sub pages to better
explain the different features. We do need a diagram that shows the load
process."
Today
src/identifiers/pmp.mdis 83 lines with six headings, being Endpoint,Integration, Configuration attributes,
id.usagemapping, Flow,localStorage and Cross-references. It documents the Preference Management
Platform as one page. The 51Did page is
src/identifiers/fodid.mdbesideit, with
overview.mdandindex.md. The cloud repository'spmp/README.mdis 982 lines and is the developer reference the page condenses, and it is
being changed by the PMP work package in the same programme.
The split
Turn
pmp.mdinto a folder,src/identifiers/pmp/, with one page perfeature, each short enough to read in one sitting, and an index that
carries the diagram.
index.md. What the platform is, the two cards, and the load processdiagram, a mermaid sequence with these actors in this order: the
browser, the page, the PMP loader tag, the PMP bundle (asynchronous), the
cloud, and the 51Did client script. It shows the PMP loader fetching the
bundle; the bundle's
init()reading local storage, else reading theshared store through the third party cookie and showing nothing when an
answer comes back; the answer being announced on the window and held in
memory behind the getter; the client script's construction reading the
getter or the local key, registering for the event and for
__tcfapi, making its first requestand running the snippets; the first card being answered; the event, the
script's
refresh(), the request that carries the usage and every snippetresult, and the 51Did coming back; the second card following at once with
the third party cookie result already known; and the shared write. Show as
a branch the case where the page carries no client script and the platform
adds it. Show both tag orders in a note, because the bundle is
asynchronous.
integration.md. The two tags, the object name and the optionaldata-object-nameattribute which defaults tofod, the action URL as anoptional hook and no longer the way the script is loaded, and load order.
What happens with no client script on the page is the part to get
right, because from 15 September 2026 the platform adds the script itself,
using the resource key and the cloud origin it already holds, and logs
that it did. Document that as the normal, expected behaviour and a
convenience, and say that a publisher who puts the client script tag on
the page themselves keeps full control of its parameters. It is why
data-object-nameexists.preferences.md. The three values, what each means under the ModelTerms, the local storage key
__51d_pmp_pref, the windowevent
51d-pmp-preference, the getterwindow.__51d_pmp.preference(),and the TCF surface the platform exposes as
window.__tcfapi. It saysthat the alternative answer,
non-marketing, is an answer under theModel Terms and not a refusal, that the TCF surface answers
(null, false)after it, which is only the TCF view of a usage grantingno purposes, and that the PMP is a technically complete TCF implementation
that does not follow the TCF Policies, so a site running a TCF consent
management platform does not add the PMP and the PMP is not a substitute
for one where those policies are required.
sharing.md. The network name, the third party cookie result taken fromthe client script's object, the shared store
(naming the endpoint
/api/v4/pmp/prefand the cookie51D_PmpPreference_<code>, and saying another platform could implementthe same exchange, because the shared store and the second card are PMP
only), the second card, the result being taken from the client script's
device.thirdpartycookiesenabled, with the platform adding that scriptwhen the page carries none, and that nothing waits between the cards.
isgdpr.md. What IsGdpr is and where it comes from (a derived propertyfrom the request's country, entitled through the resource key, requested
by name), and the PMP path: the loader sets
gdprAppliesfromfod.derived.isgdprwhen the client script object carries it, logs awarning against the PMP and leaves it true when it does not, and the
dialog is still shown and a 51Did still created either way, because the
question is contractual.
cmp-wiring.md, the page for a site running a third party consentplatform, in this order. That the PMP is a technically complete TCF
implementation that does not follow the TCF Policies, so a site running a
CMP does not add the PMP, and the two never share a page.
Load order, being that the CMP's inline
__tcfapistub must precede the51Degrees script tag, as the TCF specification already requires, that a
CMP loading later is fine because the stub queues the registration, and
that a stub missing at construction has no recovery on that page view
and the block's console warning is the only signal. IsGdpr, being what
to read (
derived.isgdpr, under the derived section of the clientscript's response, a boolean, after the first round completes through
the script's
completecallback, absent when the resource key does notrequest it), how to pass it (the principle plus one worked example
against a stubbed CMP, with the vendor's own documentation for the real
call, since we do not document another vendor's API), which wins (the
CMP's setting always, IsGdpr unused if they choose the CMP's own
detection), and the consequence (no string from the CMP means no request
carrying an answer and no 51Did). That a string granting too little for
either usage creates nothing, as today. And in one sentence what a CMP
site does not get, being the shared store and the second card. This page
cannot be finished until IsGdpr is live, which waits on
pipeline-dotnet#413
and then the cloud service's own change, so it
ships with a placeholder until then.
fodid.md, the existing 51Did page, gains a section on the user promptblock: that the script gathers the answer itself from the PMP first and a
framework platform second, that a GPP string is not read because the
Model Terms do not map it, that
refresh()exists and when to call it,that the identifier is created on the request that carries every snippet
result, that a change of answer produces a fresh identifier and calls
onChange, that the iterations of a page view stop at the server'smaximum with a console message, what the signal source flag records, and
that the cache record keeps the inputs of the last request in session
storage on the publisher's origin. It also states the server's order:
id.usageis read first, then the framework string, a stated usage isalways used when present and any string beside it is not read, the flag
records which one was used, and the "no 51Did when a United States
section is present" ruling therefore applies to a request whose only
signal is that string.
configuration.md. The attribute table, withdata-object-nameadded asan optional attribute defaulting to
fod, anddata-timeoutdescribed asbounding the shared read only.
sharing.mdor a page of its own,whichever reads better. It covers the shared answer, the third party
cookie, the session storage record and the 51Did, is marked clearly as
not legal advice, and points at the existing
Client Services Policy,
which is how
src/pipelineapi/features/clientsideevidence.mdalreadyhandles the same problem under its "Privacy Policy" heading. James
Rosewell's decision of 15 September 2026 is that this is written here as a
draft and reviewed by Tracy Barlow through an issue raised internally,
not by email. Mark the section as awaiting that review.
Every page ends with a "Find out more" section giving the repositories as
bare URLs and the 51degrees.com links tagged with the five parameter UTM
convention that
common-ci/scripts/utm-lint.ps1enforces (utm_source,utm_medium,utm_campaignequal to the lowercase repository name,utm_content,utm_term). Run that script against the repository beforepushing.
Sources of truth
Write from the work packages and the code, not from memory. The PMP source
is
pmp/srcin the cloud repository, the client script isJavaScriptResource.mustacheon javascript-templatesmain, the propertydefinitions are in the shared property metadata, and the Model Terms are
the versioned
text at
https://m4ow.uk/mtm/2.txt. Reference the exact version of theterms in force, never the explainer page, because a document that can be
edited under the reader cannot prove what an identifier agreed to.
Not part of this
The Prebid module's documentation, which lives in its own repository.