Skip to content

Prebid Mobile: makes creative size transformation based on pxRatio.#4510

Open
mdanylov-sigma wants to merge 1 commit into
prebid:masterfrom
mdanylov-sigma:feature/mobile-creative-size-transformation
Open

Prebid Mobile: makes creative size transformation based on pxRatio.#4510
mdanylov-sigma wants to merge 1 commit into
prebid:masterfrom
mdanylov-sigma:feature/mobile-creative-size-transformation

Conversation

@mdanylov-sigma

Copy link
Copy Markdown

Description

Fixes #4501

Prebid Server was not converting device.w/device.h from physical pixels to device-independent pixels (DIPs) when generating the list of candidate sizes for interstitial ads. According to the OpenRTB spec, device.w/device.h represent physical screen pixels, while banner.format sizes are expected in DIPs. On high-density screens this caused standard mobile interstitial sizes (e.g. 320x480) to be absent from the generated format list.

This change adds opt-in pxratio conversion controlled by a new field ext.prebid.sdk.usepxratio. When set to true, device.w/device.h are divided by device.pxratio before being used to calculate the interstitial size bounds. Conversion is only applied when falling back to device dimensions — explicit banner.format sizes are left untouched.

Changes

  • Added usePxRatio (Boolean, JSON: usepxratio) field to ExtRequestPrebidSdk; added explicit of() factory overloads to preserve backward compatibility with existing callers
  • Added usePxRatio(BidRequest) helper to read the flag from ext.prebid.sdk
  • Added deviceSizeToDips(Integer, BigDecimal) helper: divides by pxratio using doubleValue(), rounds to nearest integer, clamps to minimum 1; returns size unchanged when size or pxratio is null or non-positive
  • Applied conversion in processInterstitialImp() only in the device-size fallback branch

Testing

  • processShouldReturnBidRequestUpdatedWithInterstitialFormatsUsingDeviceSizeInDipsWhenFormatIsEmpty — device 1080×1920 @ pxratio 3 → expects 320×480 in results
  • processShouldReturnBidRequestUpdatedWithInterstitialFormatsUsingDeviceSizeInDipsWhenFormatIsOneToOne — same, with 1×1 sentinel format
  • processShouldNotConvertExplicitFormatSizeUsingDevicePxratio — explicit banner format is not converted
  • processShouldKeepCurrentDeviceSizeBehaviorWhenUsePxRatioIsAbsent — no flag, no conversion (backward compatibility)
  • processShouldKeepCurrentDeviceSizeBehaviorWhenUsePxRatioIsTrueAndDevicePxRatioIsAbsent — flag set but pxratio missing, sizes unchanged

@Net-burst Net-burst requested a review from osulzhenko June 10, 2026 17:10

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make your change consistent with the project's style, old code needs to be refactored. So, to simplify your work and the review process, please copy the attached file :)

InterstitialProcessor.java

Comment on lines +25 to +27
public static ExtRequestPrebidSdk of(List<ExtRequestPrebidSdkRenderer> renderers) {
return new ExtRequestPrebidSdk(renderers, null);
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this static constructor and update all usages providing usePxRatio = null

Comment on lines +84 to +86
.device(Device.builder().w(1080).h(1920).pxratio(BigDecimal.valueOf(3))
.ext(ExtDevice.of(null, ExtDevicePrebid.of(ExtDeviceInt.of(60, 60))))
.build())

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

                .device(Device.builder()
                        .w(1080)
                        .h(1920)
                        .pxratio(BigDecimal.valueOf(3))
                        .ext(ExtDevice.of(null, ExtDevicePrebid.of(ExtDeviceInt.of(60, 60))))
                        .build()

Comment on lines +97 to +98
.contains(Format.builder().w(320).h(480).build())
.doesNotContain(Format.builder().w(768).h(1024).build());

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merge into containsExactly(Format.builder().w(320).h(480).build())

Comment on lines +130 to +134
.imp(singletonList(Imp.builder().banner(Banner.builder().format(singletonList(
Format.builder().w(1).h(1).build())).build()).instl(1).build()))
.device(Device.builder().w(1080).h(1920).pxratio(BigDecimal.valueOf(3))
.ext(ExtDevice.of(null, ExtDevicePrebid.of(ExtDeviceInt.of(60, 60))))
.build())

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

assertThat(result.getImp())
.extracting(Imp::getBanner)
.flatExtracting(Banner::getFormat)
.containsOnly(Format.builder().w(320).h(480).build(),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

containsOnly -> containsExactly

Comment on lines +181 to +183
.device(Device.builder().w(1080).h(1920)
.ext(ExtDevice.of(null, ExtDevicePrebid.of(ExtDeviceInt.of(1, 1))))
.build())

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

Comment on lines +202 to +204
.device(Device.builder().w(1080).h(1920).pxratio(BigDecimal.valueOf(3))
.ext(ExtDevice.of(null, ExtDevicePrebid.of(ExtDeviceInt.of(1, 1))))
.build())

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

assertThat(result.getImp())
.extracting(Imp::getBanner)
.flatExtracting(Banner::getFormat)
.contains(Format.builder().w(768).h(1024).build());

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

assertThat(result.getImp())
.extracting(Imp::getBanner)
.flatExtracting(Banner::getFormat)
.contains(Format.builder().w(768).h(1024).build());

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Prebid Server doesn't transform device size to DPIs on calculating the creative sizes for Interstitial ads

2 participants