Skip to content

Commit

Permalink
OTT:161 - Filter VAST tags based on duration
Browse files Browse the repository at this point in the history
Signed-off-by: mohammad-murad <[email protected]>
  • Loading branch information
mohammad-murad authored and PubMatic-OpenWrap committed Jun 23, 2021
1 parent 58d0a4e commit ff2b05c
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 0 deletions.
68 changes: 68 additions & 0 deletions endpoints/openrtb2/ctv_auction.go
Original file line number Diff line number Diff line change
Expand Up @@ -421,10 +421,78 @@ func (deps *ctvEndpointDeps) createBidRequest(req *openrtb2.BidRequest) *openrtb
//createImpressions
ctvRequest.Imp = deps.createImpressions()

filterImpsVastTagsByDuration(&ctvRequest)

//TODO: remove adpod extension if not required to send further
return &ctvRequest
}

//filterImpsVastTagsByDuration checks if a Vast tag should be called for a generated impression based on the duration of tag and impression
func filterImpsVastTagsByDuration(bidReq *openrtb2.BidRequest) {

allExtMap := make(map[string]map[string]map[string]interface{})
for impCount, imp := range bidReq.Imp {
index := strings.LastIndex(imp.ID, "_")
if index == -1 {
continue
}

originalImpID := imp.ID[:index]

if _, exists := allExtMap[originalImpID]; !exists {
var impExt map[string]map[string]interface{}
if err := json.Unmarshal(imp.Ext, &impExt); err != nil {
continue
}

allExtMap[originalImpID] = impExt
}

impExtMap := allExtMap[originalImpID]
newImpExtMap := make(map[string]map[string]interface{})
for k, v := range impExtMap {
newImpExtMap[k] = v
}

for partnerName, partnerExt := range newImpExtMap {
if partnerExt["tags"] != nil {
impVastTags, ok := partnerExt["tags"].([]interface{})
if !ok {
continue
}

var compatibleVasts []interface{}
for _, tag := range impVastTags {
vastTag, ok := tag.(map[string]interface{})
if !ok {
continue
}

tagDuration := int(vastTag["dur"].(float64))
if int(imp.Video.MinDuration) <= tagDuration && tagDuration <= int(imp.Video.MaxDuration) {
compatibleVasts = append(compatibleVasts, tag)
}
}

if len(compatibleVasts) < 1 {
delete(newImpExtMap, partnerName)
} else {
newImpExtMap[partnerName] = map[string]interface{}{
"tags": compatibleVasts,
}
}

bExt, err := json.Marshal(newImpExtMap)
if err != nil {
continue
}
imp.Ext = bExt
}
}
bidReq.Imp[impCount] = imp
}
}

//getAllAdPodImpsConfigs will return all impression adpod configurations
func (deps *ctvEndpointDeps) getAllAdPodImpsConfigs() {
for index, imp := range deps.request.Imp {
Expand Down
73 changes: 73 additions & 0 deletions endpoints/openrtb2/ctv_auction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,76 @@ func TestAdjustBidIDInVideoEventTrackers(t *testing.T) {
}
}
}

func TestFilterImpsVastTagsByDuration(t *testing.T) {
tt := []struct {
testName string
inputBid openrtb2.BidRequest
expectedOutputBid openrtb2.BidRequest
}{
{
testName: "test_single_impression_single_vast_partner",
inputBid: openrtb2.BidRequest{
Imp: []openrtb2.Imp{
{ID: "imp1_1", Video: &openrtb2.Video{MinDuration: 10, MaxDuration: 10}, Ext: []byte(`{"openx_vast_bidder":{"tags":[{"dur":35},{"dur":25},{"dur":20}]}}`)},
{ID: "imp1_2", Video: &openrtb2.Video{MinDuration: 10, MaxDuration: 20}, Ext: []byte(`{"openx_vast_bidder":{"tags":[{"dur":35},{"dur":25},{"dur":20}]}}`)},
{ID: "imp1_3", Video: &openrtb2.Video{MinDuration: 25, MaxDuration: 30}, Ext: []byte(`{"openx_vast_bidder":{"tags":[{"dur":35},{"dur":25},{"dur":20}]}}`)},
},
},
expectedOutputBid: openrtb2.BidRequest{
Imp: []openrtb2.Imp{
{ID: "imp1_1", Video: &openrtb2.Video{MinDuration: 10, MaxDuration: 10}, Ext: []byte(`{}`)},
{ID: "imp1_2", Video: &openrtb2.Video{MinDuration: 10, MaxDuration: 20}, Ext: []byte(`{"openx_vast_bidder":{"tags":[{"dur":20}]}}`)},
{ID: "imp1_3", Video: &openrtb2.Video{MinDuration: 25, MaxDuration: 30}, Ext: []byte(`{"openx_vast_bidder":{"tags":[{"dur":25}]}}`)},
},
},
},
{
testName: "test_single_impression_multiple_vast_partners",
inputBid: openrtb2.BidRequest{
Imp: []openrtb2.Imp{
{ID: "imp1_1", Video: &openrtb2.Video{MinDuration: 10, MaxDuration: 10}, Ext: []byte(`{"spotx_vast_bidder":{"tags":[{"dur":15},{"dur":25},{"dur":30}]},"openx_vast_bidder":{"tags":[{"dur":35},{"dur":25},{"dur":20}]}}`)},
{ID: "imp1_2", Video: &openrtb2.Video{MinDuration: 10, MaxDuration: 20}, Ext: []byte(`{"spotx_vast_bidder":{"tags":[{"dur":15},{"dur":25},{"dur":30}]},"openx_vast_bidder":{"tags":[{"dur":35},{"dur":25},{"dur":20}]}}`)},
{ID: "imp1_3", Video: &openrtb2.Video{MinDuration: 25, MaxDuration: 30}, Ext: []byte(`{"spotx_vast_bidder":{"tags":[{"dur":15},{"dur":25},{"dur":30}]},"openx_vast_bidder":{"tags":[{"dur":35},{"dur":25},{"dur":20}]}}`)},
},
},
expectedOutputBid: openrtb2.BidRequest{
Imp: []openrtb2.Imp{
{ID: "imp1_1", Video: &openrtb2.Video{MinDuration: 10, MaxDuration: 10}, Ext: []byte(`{}`)},
{ID: "imp1_2", Video: &openrtb2.Video{MinDuration: 10, MaxDuration: 20}, Ext: []byte(`{"openx_vast_bidder":{"tags":[{"dur":20}]},"spotx_vast_bidder":{"tags":[{"dur":15}]}}`)},
{ID: "imp1_3", Video: &openrtb2.Video{MinDuration: 25, MaxDuration: 30}, Ext: []byte(`{"openx_vast_bidder":{"tags":[{"dur":25}]},"spotx_vast_bidder":{"tags":[{"dur":25},{"dur":30}]}}`)},
},
},
},
{
testName: "test_multi_impression_multi_partner",
inputBid: openrtb2.BidRequest{
Imp: []openrtb2.Imp{
{ID: "imp1_1", Video: &openrtb2.Video{MinDuration: 10, MaxDuration: 10}, Ext: []byte(`{"openx_vast_bidder":{"tags":[{"dur":35},{"dur":25},{"dur":20}]}}`)},
{ID: "imp1_2", Video: &openrtb2.Video{MinDuration: 10, MaxDuration: 20}, Ext: []byte(`{"openx_vast_bidder":{"tags":[{"dur":35},{"dur":25},{"dur":20}]}}`)},
{ID: "imp1_3", Video: &openrtb2.Video{MinDuration: 25, MaxDuration: 30}, Ext: []byte(`{"openx_vast_bidder":{"tags":[{"dur":35},{"dur":25},{"dur":20}]}}`)},
{ID: "imp2_1", Video: &openrtb2.Video{MinDuration: 5, MaxDuration: 30}, Ext: []byte(`{"spotx_vast_bidder":{"tags":[{"dur":30},{"dur":40}]}}`)},
},
},
expectedOutputBid: openrtb2.BidRequest{
Imp: []openrtb2.Imp{
{ID: "imp1_1", Video: &openrtb2.Video{MinDuration: 10, MaxDuration: 10}, Ext: []byte(`{}`)},
{ID: "imp1_2", Video: &openrtb2.Video{MinDuration: 10, MaxDuration: 20}, Ext: []byte(`{"openx_vast_bidder":{"tags":[{"dur":20}]}}`)},
{ID: "imp1_3", Video: &openrtb2.Video{MinDuration: 25, MaxDuration: 30}, Ext: []byte(`{"openx_vast_bidder":{"tags":[{"dur":25}]}}`)},
{ID: "imp2_1", Video: &openrtb2.Video{MinDuration: 5, MaxDuration: 30}, Ext: []byte(`{"spotx_vast_bidder":{"tags":[{"dur":30}]}}`)},
},
},
},
}

for _, tc := range tt {
tc := tc
t.Run(tc.testName, func(t *testing.T) {
t.Parallel()

outputBids := &tc.inputBid
filterImpsVastTagsByDuration(outputBids)
assert.Equal(t, tc.expectedOutputBid, *outputBids, "Expected length of impressions array was %d but actual was %d", tc.expectedOutputBid, outputBids)
})
}
}

0 comments on commit ff2b05c

Please sign in to comment.