pixellint

Pixellint 0.41.0 checks IAS identities across declared ad sessions.

An individual URL cannot prove agreement across one ad.

A start tracker can contain a populated external session ID, a recognized endpoint and valid path identifiers. A complete tracker can satisfy those same checks while carrying a different external ID. Inspecting each URL independently establishes facts about its own fields. Establishing whether they describe one ad session requires the caller to supply their relationship, then compare the fields covered by a documented destination contract.

This release starts with IAS Unified Video Pixel URLs on the vevent endpoint family. The IAS Video Solutions Guide describes an external session ID that remains the same across the UVP URLs for one ad session and identifies that ad session uniquely. That gives the validator a concrete relationship to test. The new checks connect known observations instead of requiring every surrounding pixel to be submitted or inventing an event sequence.

The website example makes the failure visible with three synthetic URLs. Two URLs declared as ad-1 use the identities a and b. A third URL declared as ad-2 reuses a. The first pair establishes an inconsistency inside ad-1. The third row establishes reuse across the two declared sessions. Their numeric path fields and nonempty individual IDs can remain valid throughout.

The caller declares membership in the original input rows.

The additive session request contains an ordinary document and a sessions array. Each group has a session_id label and artifact_indexes that point into the original document.artifacts array. Those indexes refer to input rows before ordinary document deduplication. The caller supplies this grouping because the validator cannot establish session membership from shared hosts, neighboring rows, timestamps, IP addresses or a similar-looking identifier.

Original row membership matters when two identical URL strings occur in different ad sessions. The ordinary document report can continue to aggregate those strings as one artifact. Relationship evaluation still retains both original memberships, so it can establish identity reuse across the declared sessions. A repeated URL inside one group remains another observation of that session. The feature makes no assertion that a retry means an event fired twice.

Blank or duplicate group labels, duplicate row membership, overlapping groups and indexes outside the input document are input errors. Empty groups are allowed and receive visible coverage that has not been evaluated. Rows left outside every group still receive ordinary validation and appear as ungrouped rows in the session coverage. The engine does not silently move them into a convenient group.

The IAS profile follows its published identity contract.

The first relationship rule compares resolved xsId values inside each declared ad session. When at least two known observations contain different values, it reports vendor.ias-video-pixel.session.xsid.inconsistent. The second rule compares known values across distinct declared sessions. Reusing one known identity in more than one group reports vendor.ias-video-pixel.session.xsid.reused. Both findings explain which original rows establish the problem.

IAS recommends UUIDv4 for the external session identifier. The relationship profile does not turn that recommendation into a required format. A stable opaque value can still satisfy the comparison contract. The existing URL pack continues to inspect its supported path fields, optional formats and unstable identity macros. Relationship checking adds the agreement and reuse tests that require explicit surrounding context.

The scope remains IAS UVP vevent URLs matched by their actual destination owner. The separate IAS MMT v2 endpoint does not enter these comparisons merely because it shares a directory entry or a vendor name. Selecting a pack explicitly also does not make an unrelated host participate. Event completeness, event order, firing frequency and destination acceptance remain outside these two documented identity checks.

Opaque identities receive one strict decoding pass.

Relationship comparison uses the exact contracted parameter name xsId, including its case. It splits the original query on literal ampersands and excludes a fragment. Matching query names and values receive one decoding pass. Literal plus becomes a space, while an encoded %2B becomes a plus. The resulting identity stays opaque. The engine does not trim it, lowercase it, interpret it as a number or derive a timestamp from it.

Malformed percent escapes and invalid decoded UTF-8 prevent that observation from establishing an identity. A macro that remains unresolved after the supported decoding pass also cannot establish agreement or reuse. The documented installation placeholder receives its own skip reason. These conditions leave the ordinary per-artifact findings intact while making the relationship uncertainty visible in coverage. An invalid unrelated query field does not suppress a valid xsId.

Repeated identical xsId parameters contribute one known identity and retain every original value span. Conflicting repeated literal values cannot be collapsed to whichever value appears first. An unresolved or invalid repeated value cannot disappear behind a neighboring valid literal. Exact decoded strings determine equality, so different Unicode normalization forms remain distinct unless their once-decoded values are identical.

Incomplete coverage stays visible beside proven findings.

A within-session comparison needs two resolved observations. The reuse comparison needs known observations in two distinct declared groups. Below those thresholds the check is not evaluated. Above them, skipped participants produce partially evaluated coverage. The report records participant counts, compared counts, typed skip reasons and the original skipped row provenance. A skipped row is not manufactured into an information finding that obscures this distinction.

A proven mismatch remains useful when another row is unresolved. If two known URLs disagree and a third retains an installation placeholder, the inconsistency still fires and the comparison is marked partially evaluated. The opposite case matters as well: zero error findings with only one known URL cannot establish that the declared session is consistent. The website displays relationship coverage beside its finding counts to keep those two results understandable.

The aggregate report also accounts for empty groups, excluded owners and ungrouped rows. Its evaluated status describes the configured identity checks on the declared observations. It does not promise that every video event was captured. Local input and resource limits fail explicitly before evaluation rather than returning a clean incomplete report. Collection, comparison work and conservative generated-output bounds apply to custom profiles too.

Targets retain the original evidence for each relationship.

A relationship finding includes caller session labels and original artifact indexes, alongside the aggregate artifact ID used by the ordinary document report. Targets contain original query value spans and occurrence metadata for the contributing row. This preserves the place where the known identity appeared, even when the document report deduplicates identical URLs or combines occurrences supplied by different original rows.

Query spans are measured in UTF-8 bytes, as in the shared engine. Browser strings use UTF-16 positions, so the website converts exact code-point boundaries before marking a value. Multibyte characters before a query parameter must not shift the highlight onto its neighbor. The marked text remains the original encoded value in the submitted row. Its once-decoded comparison value is shown separately as text.

Session labels, opaque values and occurrence metadata render through text nodes. They are not inserted as HTML or interpreted as DOM selectors. The UI links each relationship code to its owning pack inventory and the published source scope. This keeps the result inspectable without turning an arbitrary caller label into executable markup or losing the row-specific evidence behind an aggregate report. Browser rendering uses finite previews with exact omitted counts. A local JSON download retains the complete request and report, while finding totals and relationship coverage always reflect the full engine result.

Sessions mode is additive and keeps submitted groups local.

The website adds an explicit Sessions format and a synthetic example. A manually selected Sessions mode remains selected while the caller types or pastes its JSON request. Individual artifacts retain their own expansion state inside the document. The optional reference clock uses integer Unix seconds so clock-sensitive ordinary checks can be replayed consistently with native and JavaScript bindings.

Sessions validation runs in the browser through the shared WASM engine. The website removes the submitted payload from its query string, omits a share link and does not send a usage sample for this mode. The new core, CLI, npm, WASM and MCP entry points return the separate session report. Existing single-artifact, HTTP capture and HAR validation remain available through their established interfaces.

The initial relationship extraction accepts supported direct URL-like rows. Serialized HTTP envelopes and JSON artifacts still receive ordinary document validation, but their relationship checks show an unsupported-artifact skip. The engine does not search arbitrary nested fields for a candidate identity or invent query spans inside a serialized capture. Integrations can explicitly extract and group observed tracker URLs when they have the source context.

Release measurements separate relationship controls from ordinary corpus results.

All 73 independently authored session controls passed with static expected findings, coverage and original-row targets. Nineteen controls establish 23 new relationship errors. Across native, Node WASM, browser WASM and the ESM/CJS wrappers, 507 complete report comparisons agreed at explicit reference clocks. A separate review passed 46 independent native relationship controls and 13 external Rust compatibility, registry and resource controls. The full workspace passed 577 Rust tests, formatting and Clippy, alongside the npm suite.

The ordinary D1 regression corpus contains 8,836 previously captured artifacts. All before and after reports were unchanged: 324 errors, 769 warnings and 250 artifacts with errors. Individual captured artifacts do not supply explicit original ad-session groups. That corpus verifies retained ordinary validation behavior. It cannot establish a relationship detection gain by guessing which rows belong together. The new relationship controls supply declared groups and independent expectations for their specific contracts. A further 708 complete native and WASM report comparisons covered all stored JSON and URL inputs and representatives of the VAST finding signatures.

The release report records both bodies of evidence and the remaining scope limits. The IAS pack page lists the two new relationship codes beside its existing individual URL contracts, with the profile source and caller-declared grouping requirement. Subsequent session profiles need their own published destination contracts and fixtures. Sharing a tracking host or appearing frequently in a capture window is not enough evidence to impose a new relationship rule.

Sources

Contract pages

The dated argument is above. These pages are the field lists.

Inspect declared ad sessions Docs