Skip to content

PMP developer documentation split by feature, with the load process diagram, IsGdpr and the 51Did interplay #237

Description

@jwrosewell

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    type: cleanupTidying that changes no behaviour

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions