Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update TargetingInfo Behavior #1088

Open
wants to merge 13 commits into
base: master
Choose a base branch
from

Conversation

ankit-thanekar007
Copy link
Contributor

@ankit-thanekar007 ankit-thanekar007 commented Jan 16, 2025

  • Add a flag that allows devs to use this feature.
  • If the flag is set, the targeting info will be added to adObject regardless of bid status
  • If the flag is not set, it'll retain the current behavior
  • Add tests

@YuriyVelichkoPI : After our discussion, do we need the flag or should this be the default behavior ?

Fixes Issue : #1087

@ankit-thanekar007 ankit-thanekar007 changed the title Add Targeting option Update TargetingInfo Behavior Jan 16, 2025
@@ -187,6 +187,11 @@ public class AdUnit: NSObject, DispatcherDelegate {
}

private func setUp(_ adObject: AnyObject?, with bidResponse: BidResponse) -> ResultCode {

if Prebid.shared.forceTargetingInfo, let adObject {

Choose a reason for hiding this comment

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

Looks like the provided solution will break the existing behaviour.
In case forceTargetingInfo == false, which is default behaviour, bidResponse will never be attached for winning bid.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, thanks for catching that. I removed the flag altogether and by default it'll always add targeting params.

@@ -187,6 +187,11 @@ public class AdUnit: NSObject, DispatcherDelegate {
}

private func setUp(_ adObject: AnyObject?, with bidResponse: BidResponse) -> ResultCode {

if let adObject {
Copy link
Contributor

Choose a reason for hiding this comment

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

In order to make the solution generic and not break the current behavior, we should implement it according to the following requirements:

  1. The current behavior should remain the same. It means that for the current users SKD should continue to add the targeting keywords only in the case when the bid response has a winning bid.
  2. We should inform users that in the future (3.0 release), this behavior will be changed. As usual, we do it via deprecating the method or property, so the app developers see the compile time warning. But in this case, I don't see such an option. Therefore, we should at least log some error message that the current behavior will be changed soon. Also we should put a respective warning note to the public documentation.
  3. We should add the flag to like Targeting.forceSdkChooseWinner which will allow adding targeting keywords regardless of the presence of the winning bid. The default value should be true. That was partially done in the initial commit, but it should still be adjusted according to the review comment. If forceSdkChooseWinner is true, the keywords should be sent only if the winning bid is present (the current behavior). If forceSdkChooseWinner is false, the keywords should be sent regarding the winning bid.
  4. And the most important. If we start sending info from all bids - SDK shouldn't return .prebidDemandNoBids if there are bids in the response, regardless of the presence of the winning bid.
  5. And, of course, we should add unit tests for the new behavior. Also, please ensure that we have unit tests that verify that the BidResposne.targetingInfo really contains targeting keywords from all bids in the response.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hey @YuriyVelichkoPI , For 4

  • It's possible to not have a winning bid as it doesn't have hb_pb value. It's just targeting data.
  • In that case we'll be passing the targeting data to GAM, it's not a bid or a winning bid. What should we send in return ?
  • I think 4 should be part of the 3.x release as it's scope is much bigger.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've made changes for 1,3 and 5.
Can you let me know the msg for 2 ? Should it use Log.warn ?

Copy link
Contributor

Choose a reason for hiding this comment

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

Hi @ankit-thanekar007 !

About the item 4: we already have a good ResultCode for it - .prebidDemandFetchSuccess The method that publishers use is fetchDemand. The targeting info is placed in bid.ext.prebid.targeting. Hence we can legally send the .prebidDemandFetchSuccess to the publisher because there are bids in the response. The .prebidDemandNoBids should indicate real 0 bids in the response. It's a common Prebid behavior.

About the item 2:

  • First, let's log the error message - Log.error. We should make it as verbose as possible to force publishers to adapt the upcoming changes.
  • Let's log an error if forceSdkToChooseWinner is true, regardless the response content.
  • The message: `Breaking change: set Targeting.forceSdkToChooseWinner = false and test your behavior. In the upcoming major release, the SDK will send all targeting keywords to the AdSever, so you should prepare your setup."
  • The warning message should be in the SDK's doc.

//If Bid Present and the bid is winning
//OR
//If forceSdkChooseWinner == false : Any bid works -- winnning or loosing
if bidResponse.winningBid?.isWinning == true || !Targeting.shared.forceSdkToChooseWinner {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it would be more appropriate to verify that bidResponse.winningBid != nil to make things clearer. There's no need to verify if winningBid is already isWinning, as it inherently is if present.

//forceSdkToChooseWinner + Winner = Contains Targeting Info
func testForcedWinnerAndWinningBid() {
//given
Targeting.shared.forceSdkToChooseWinner = true
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please reset all global values to their default settings after the test completes (e.g. in tearDown) to prevent any unexpected behaviour.

@ankit-thanekar007
Copy link
Contributor Author

@YuriyVelichkoPI @OlenaPostindustria Updated the PR with the fixes for comments + 1 test case fix. Please verify.

@@ -34,6 +34,6 @@ class NativeAdsTest: BaseAdsTest {
}

override func checkAd(testCase: String) {
XCTAssert(app.staticTexts["Prebid (Title)"].waitForExistence(timeout: 10),assertFailedMessage(testCase: testCase, reason: "Prebid title is not displayed"))
XCTAssert(app.staticTexts[testCase].waitForExistence(timeout: 10),assertFailedMessage(testCase: testCase, reason: "Prebid title is not displayed"))
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is it necessary to modify the test conditions? testCase text is always visible on the screen since it’s not part of an ad, so it is not a valid indicator for detecting ad presence.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

During this flow app.staticTexts never have "Prebid (Title)" they have the testCase strings. The tests were failing because it could never find "Prebid (Title)" inside app.staticTexts.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

These started failing since Yesterday.

Copy link
Collaborator

Choose a reason for hiding this comment

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

This occurred due to the hb_cache_id_local key missing issue causing the test case to stop working.

return .prebidDemandNoBids
}

if let cacheId = cacheBidIfNeeded(winningBid) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

We are missing the addition of hb_cache_id_local (cacheId) to the adObject, which is crucial for certain types of ads (e.g., native in-app).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It currently uses winning bid, this is the case when there are no winning bids.

  1. Would this be a valid case ?
  2. Which bids should we use in case of multiple bids ?

Copy link
Collaborator

@OlenaPostindustria OlenaPostindustria Jan 23, 2025

Choose a reason for hiding this comment

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

In this case, the winningBid is the bid intended for display. The SDK should cache such a bid and attach the cacheID to the adObject as hb_cache_id_local. Otherwise, it will break the existing functionality. The SDK should maintain the default behaivior.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks for the updates! I’d also suggest adding some unit tests to ensure this functionality doesn’t break in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've added 2 tests that target

  1. the new behavior + winning bid
  2. the new behavior + losing bid

Do you mean more tests for hb_cache_id_local ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The 2 other tests target the old behavior

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, I mean more tests for hb_cache_id_local

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added 2 cases for native format, please can you verify those. I'm not that versed in the native format from Prebid yet

@@ -122,6 +123,17 @@ class TargetingTests: XCTestCase {
XCTAssertEqual(locationPrecision, Targeting.shared.locationPrecision)
}

func testforceSdkToChooseWinner() {
//given
let forceSdkToChooseWinner = true
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think false would be more suitable here, as Targeting.shared.forceSdkToChooseWinner is true by default.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated

Ankit Rajendra Thanekar added 2 commits January 24, 2025 14:47

//then
XCTAssertNotNil(bidResponse.targetingInfo?[PrebidLocalCacheIdKey])
XCTAssertTrue((adObject.allKeys as? [String])?.contains("hb_bidder") ?? false)
Copy link
Collaborator

@OlenaPostindustria OlenaPostindustria Jan 24, 2025

Choose a reason for hiding this comment

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

I believe it would be helpful to check if the hb_cache_id_local key is attached to the ad object. This applies to both native tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added

Copy link
Collaborator

@OlenaPostindustria OlenaPostindustria left a comment

Choose a reason for hiding this comment

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

LGTM!

@ankit-thanekar007
Copy link
Contributor Author

@YuriyVelichkoPI Can you review and let me know in case of any changes ?

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.

4 participants