Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 109 additions & 0 deletions lib/addons/prebid/analytics.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,115 @@ describe("OptablePrebidAnalytics", () => {
expect(result.optableMatchers).toEqual([]);
expect(result.optableSources).toEqual([]);
});

it("optableTargetingDone: '1' when a single Optable matcher is present", async () => {
const result = await analytics.toWitness(
{
auctionId: "auction-targeting-one-matcher",
bidderRequests: [
{
bidderCode: "bidder1",
bidderRequestId: "req-1",
ortb2: {
site: { domain: "example.com" },
user: { eids: [{ inserter: "optable.co", matcher: "uid2", source: "uid2.com" }] },
},
bids: [],
},
],
bidsReceived: [],
noBids: [],
timeoutBids: [],
},
[]
);

expect(result.optableTargetingDone).toBe("1");
});

it("optableTargetingDone: '1' when two Optable matchers are present (uid2 + id5)", async () => {
// Regression: previously sent `oMatchersSet.size` (the number 2) which Spark
// coerced to "2" — matching neither IN ('1','true') nor IN ('0','false') →
// processor classified every such auction as status='unknown' instead of 'enriched'.
const result = await analytics.toWitness(
{
auctionId: "auction-targeting-two-matchers",
bidderRequests: [
{
bidderCode: "bidder1",
bidderRequestId: "req-1",
ortb2: {
site: { domain: "example.com" },
user: {
eids: [
{ inserter: "optable.co", matcher: "uid2", source: "uid2.com" },
{ inserter: "optable.co", matcher: "id5", source: "id5-sync.com" },
],
},
},
bids: [],
},
],
bidsReceived: [],
noBids: [],
timeoutBids: [],
},
[]
);

expect(result.optableTargetingDone).toBe("1");
expect(result.optableMatchers).toEqual(["uid2", "id5"]);
});

it("optableTargetingDone: '0' when no Optable EIDs are present", async () => {
const result = await analytics.toWitness(
{
auctionId: "auction-targeting-no-eids",
bidderRequests: [
{
bidderCode: "bidder1",
bidderRequestId: "req-1",
ortb2: {
site: { domain: "example.com" },
user: { eids: [] },
},
bids: [],
},
],
bidsReceived: [],
noBids: [],
timeoutBids: [],
},
[]
);

expect(result.optableTargetingDone).toBe("0");
});

it("optableTargetingDone: '1' when Optable sources are present but no named matcher", async () => {
const result = await analytics.toWitness(
{
auctionId: "auction-targeting-source-only",
bidderRequests: [
{
bidderCode: "bidder1",
bidderRequestId: "req-1",
ortb2: {
site: { domain: "example.com" },
user: { eids: [{ inserter: "optable.co", source: "liveramp.com" }] },
},
bids: [],
},
],
bidsReceived: [],
noBids: [],
timeoutBids: [],
},
[]
);

expect(result.optableTargetingDone).toBe("1");
});
});

describe("trackAuctionEnd", () => {
Expand Down
5 changes: 4 additions & 1 deletion lib/addons/prebid/analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,10 @@ class OptablePrebidAnalytics {
adUnitCode,
totalRequests: bidderRequests.length,
optableSampling: this.config.samplingRate || 1,
optableTargetingDone: oMatchersSet.size || oSourcesSet.size,
// Processor schema declares optableTargetingDone as STRING and checks IN ('1','true').
// Send '1'/'0' so Spark reads a predictable string regardless of matcher count.
// A raw count (e.g. 2) coerces to "2" which matches neither branch → status='unknown'.
optableTargetingDone: oMatchersSet.size > 0 || oSourcesSet.size > 0 ? "1" : "0",
optableMatchers: Array.from(oMatchersSet),
optableSources: Array.from(oSourcesSet),
bidWon: bidWonEvents.map((e) => ({
Expand Down
Loading