Skip to content

PLAT-287894: Add uncapped paid-media calculated-rate fields; deprecate capped originals#2202

Open
ejsuncy wants to merge 1 commit into
adobe:masterfrom
ejsuncy:feature-2201-paid-media-rate-caps
Open

PLAT-287894: Add uncapped paid-media calculated-rate fields; deprecate capped originals#2202
ejsuncy wants to merge 1 commit into
adobe:masterfrom
ejsuncy:feature-2201-paid-media-rate-caps

Conversation

@ejsuncy

@ejsuncy ejsuncy commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #2201
Jira: PLAT-287894

Adds new uncapped paid-media calculated-rate fields and deprecates the capped originals. Non-breaking — purely additive; the capped fields are retained unchanged (minimum: 0, maximum: 1), so existing data and producers keep working.

Motivation

Ingesting Google Ads summary metrics failed because paidMedia.conversionMetrics.conversionRate (mapped to Google Ads metrics.conversions_from_interactions_rate = all_conversions / interactions) returned 2.0, exceeding the maximum: 1.0 cap. These rates have a numerator and denominator drawn from different event populations (numerator is not a subset of the denominator), so they can legitimately exceed 1.0. Multiple conversions can be attributed to a single click, and networks can similarly inflate CTR and engagement counts.

Approach

These fields are now meta:status: stable. Removing or relaxing the maximum in place is a breaking change and is blocked by the xed-validation restricted-property gate (check_properties.js flags any change to an existing maximum/minimum). Per CONTRIBUTING/CLAUDE guidance ("deprecate, don't remove or rename"), this PR instead:

  • adds a new uncapped sibling field (minimum: 0, no maximum, meta:status: stable), and
  • marks each capped original meta:status: deprecated with a description pointer to its replacement.

This is the same pattern used elsewhere in the repo (e.g. pushdetail blacklistedblocklisted).

Deprecated (capped, retained) New (uncapped)
ctr ctrUncapped
conversionRate conversionRateUncapped
engagementRate engagementRateUncapped
budgetUtilization budgetUtilizationUncapped
dailyBudgetUtilization dailyBudgetUtilizationUncapped
negativeActionRate negativeActionRateUncapped
positiveActionRate positiveActionRateUncapped
crossDeviceConversionRate crossDeviceConversionRateUncapped

True subset/total proportions that are mathematically bounded at 1.0 are untouched and keep their cap: viewabilityRate, video view/completion/skip rates, fraudRate, validationRate, leadFormCompletionRate, invalid/bot/human traffic rates, the impressionShare set, attribution weights/confidence/contribution, and statistical indices.

Changes

  • core-paid-media-conversion-metrics.schema.json — deprecate conversionRate, add conversionRateUncapped
  • core-paid-media-metrics.schema.json — deprecate ctr/engagementRate, add ctrUncapped/engagementRateUncapped
  • core-paid-media-cost-metrics.schema.json — deprecate budgetUtilization/dailyBudgetUtilization, add budgetUtilizationUncapped/dailyBudgetUtilizationUncapped
  • core-paid-media-quality-metrics.schema.json — deprecate negativeActionRate/positiveActionRate, add negativeActionRateUncapped/positiveActionRateUncapped
  • core-paid-media-attribution-metrics.schema.json — deprecate crossDeviceConversionRate, add crossDeviceConversionRateUncapped
  • corresponding *.example.1.json files updated to exercise the new fields (with >1.0 values where the metric can legitimately exceed 1.0)

Validation

  • npm test — 2406 passing
  • npm run lint — clean (prettier added no extra changes)
  • npm run incompatibility-check — clean (exit 0)
  • npm run xed-validationNo disallowed changes detected + All good

Breaking changes

None.

@ejsuncy ejsuncy marked this pull request as ready for review June 10, 2026 20:48
@ejsuncy ejsuncy marked this pull request as draft June 12, 2026 22:08
…e capped originals

The maximum:1.0 cap on several calculated-rate fields rejects legitimate
values >1.0. Rates whose numerator and denominator come from different event
populations can exceed 1.0 (e.g. Google Ads all-conversions/clicks, multiple
engagements per impression, spend overrunning budget).

These fields are now stable, so the cap cannot be removed or relaxed in place
(breaking change, and blocked by the xed-validation restricted-property gate).
Instead, add new uncapped sibling fields (minimum:0, no maximum) and mark the
capped originals meta:status:deprecated with a pointer to the replacement:

  ctr                       -> ctrUncapped
  conversionRate            -> conversionRateUncapped
  engagementRate            -> engagementRateUncapped
  budgetUtilization         -> budgetUtilizationUncapped
  dailyBudgetUtilization    -> dailyBudgetUtilizationUncapped
  negativeActionRate        -> negativeActionRateUncapped
  positiveActionRate        -> positiveActionRateUncapped
  crossDeviceConversionRate -> crossDeviceConversionRateUncapped

Non-breaking: purely additive. Capped fields retain minimum:0, maximum:1
untouched. Examples updated to exercise the new fields (with >1.0 values where
the metric can legitimately exceed 1.0).

Validation: npm test 2406 passing; lint clean; incompatibility-check clean;
xed-validation "No disallowed changes detected" + "All good".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ejsuncy ejsuncy force-pushed the feature-2201-paid-media-rate-caps branch from ac52479 to 1bba6ef Compare June 12, 2026 23:01
@ejsuncy ejsuncy changed the title PLAT-287894: Relax maximum:1.0 cap on paid-media calculated-rate fields PLAT-287894: Add uncapped paid-media calculated-rate fields; deprecate capped originals Jun 12, 2026
@ejsuncy ejsuncy marked this pull request as ready for review June 15, 2026 16:58
@ejsuncy

ejsuncy commented Jun 15, 2026

Copy link
Copy Markdown
Contributor Author

This is now ready

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Paid Media: calculated-rate fields (conversionRate, ctr, engagementRate) reject values > 1.0, causing ingestion failures

2 participants