Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
47 changes: 31 additions & 16 deletions adapters/pubmatic/pubmatic.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ type pubmaticBidExt struct {
VideoCreativeInfo *pubmaticBidExtVideo `json:"video,omitempty"`
Marketplace string `json:"marketplace,omitempty"`
PrebidDealPriority int `json:"prebiddealpriority,omitempty"`
InBannerVideo bool `json:"ibv,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

Now that getBidType(bidExt *pubmaticBidExt) has become getMediaTypeForBid(bid *openrtb2.Bid), the BidType *int json:"BidType,omitempty" field seems to not be used anywhere in your adapter's code anymore. Should we remove?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, removed BidType from adapter code

}

type pubmaticWrapperExt struct {
Expand Down Expand Up @@ -461,26 +462,37 @@ func (a *PubmaticAdapter) MakeBids(internalRequest *openrtb2.BidRequest, externa
bid.Cat = bid.Cat[0:1]
}

mType, err := getMediaTypeForBid(&bid)
if err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we write a JSON test case to cover the error scenario?
image

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes Added test case

errs = append(errs, err)
continue
}

typedBid := &adapters.TypedBid{
Bid: &bid,
BidType: openrtb_ext.BidTypeBanner,
BidVideo: &openrtb_ext.ExtBidPrebidVideo{},
}

var bidExt *pubmaticBidExt
err := jsonutil.Unmarshal(bid.Ext, &bidExt)
err = jsonutil.Unmarshal(bid.Ext, &bidExt)
if err != nil {
errs = append(errs, err)
} else if bidExt != nil {
typedBid.Seat = openrtb_ext.BidderName(bidExt.Marketplace)
typedBid.BidType = getBidType(bidExt)
typedBid.BidType = mType
Copy link
Contributor

@guscarreon guscarreon Apr 29, 2025

Choose a reason for hiding this comment

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

The changes implemented in this pull request make that setting typedBid.BidType does not depend on bidExt not being nil because we're now taking mType from bid.MType and not from bid.Ext.BidType. Do we still need to assign typedBid.BidType = mType inside the if bidExt != nil statement?

470
471             typedBid := &adapters.TypedBid{
472                 Bid:      &bid,
473                 BidType:  openrtb_ext.BidTypeBanner,
474                 BidVideo: &openrtb_ext.ExtBidPrebidVideo{},
    +               BidType:  mType,
475             }
476
477             var bidExt *pubmaticBidExt
478             err = jsonutil.Unmarshal(bid.Ext, &bidExt)
479             if err != nil {
480                 errs = append(errs, err)
481             } else if bidExt != nil {
482                 typedBid.Seat = openrtb_ext.BidderName(bidExt.Marketplace)
483 -               typedBid.BidType = mType
484                 if bidExt.PrebidDealPriority > 0 {
485                     typedBid.DealPriority = bidExt.PrebidDealPriority
486                 }
adapters/pubmatic/pubmatic.go

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes you are right,
anyway we are setting default value in getMediaTypeForBid as "banner" and we don't need to assign in if block.

if bidExt.PrebidDealPriority > 0 {
typedBid.DealPriority = bidExt.PrebidDealPriority
}

if bidExt.VideoCreativeInfo != nil && bidExt.VideoCreativeInfo.Duration != nil {
typedBid.BidVideo.Duration = *bidExt.VideoCreativeInfo.Duration
}

typedBid.BidMeta = &openrtb_ext.ExtBidPrebidMeta{MediaType: string(mType)}
if bidExt.InBannerVideo {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suppose a native type bid comes and, for some unknown reason, its bidExt.InBannerVideo is set to true. Would it be misleading to set typedBid.BidMeta.MediaType to "video" given that this is not a banner? In other words, would it be desirable to add an additional check here to make sure this is really a banner that contains a video?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This scenario will not occur on Pubmatic-openwrap side. It will be handled by Pubmatic SSP side.
So, we don't need any extra check for this scenario.

typedBid.BidMeta.MediaType = string(openrtb_ext.BidTypeVideo)
Copy link
Contributor

Choose a reason for hiding this comment

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

Is the scenario where bidExt.InBannerVideo is true, but bidExt.VideoCreativeInfo or bidExt.VideoCreativeInfo.Duration is nil, valid? If not, should we validate and append an error to the errs array in such cases?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, It is valid case bidExt.VideoCreativeInfo and bidExt.VideoCreativeInfo.Duration is nil in case of bidExt.InBannerVideo is true.

}
}

if typedBid.BidType == openrtb_ext.BidTypeNative {
Expand Down Expand Up @@ -637,24 +649,27 @@ func getStringArray(array []interface{}) []string {
return aString
}

// getBidType returns the bid type specified in the response bid.ext
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we update the comment? getMediaTypeForBid doesn't return the bid type from bid.ext anymore.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes sure

func getBidType(bidExt *pubmaticBidExt) openrtb_ext.BidType {
// getMediaTypeForBid returns the bid type specified in the response bid.ext
func getMediaTypeForBid(bid *openrtb2.Bid) (openrtb_ext.BidType, error) {
// setting "banner" as the default bid type
bidType := openrtb_ext.BidTypeBanner
if bidExt != nil && bidExt.BidType != nil {
switch *bidExt.BidType {
case 0:
bidType = openrtb_ext.BidTypeBanner
case 1:
bidType = openrtb_ext.BidTypeVideo
case 2:
bidType = openrtb_ext.BidTypeNative
mType := openrtb_ext.BidTypeBanner
if bid != nil {
switch bid.MType {
Copy link
Contributor

Choose a reason for hiding this comment

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

Are we sure from now on the media type will always be located in bid.MType and not in bid.Ext? Do you think we should look in bid.MType first and then bid.Ext second for backwards compatibility?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, we are sure on media type will always be located in bid.MType. I don't think we need to have any backward compatibility logic.

case openrtb2.MarkupBanner:
mType = openrtb_ext.BidTypeBanner
case openrtb2.MarkupVideo:
mType = openrtb_ext.BidTypeVideo
case openrtb2.MarkupAudio:
mType = openrtb_ext.BidTypeAudio
case openrtb2.MarkupNative:
mType = openrtb_ext.BidTypeNative
default:
// default value is banner
bidType = openrtb_ext.BidTypeBanner
return "", &errortypes.BadServerResponse{
Message: fmt.Sprintf("failed to parse bid mtype (%d) for impression id %s", bid.MType, bid.ImpID),
Copy link
Contributor

@scr-oath scr-oath Jun 17, 2025

Choose a reason for hiding this comment

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

nitpick: superfluous space.

Suggested change
Message: fmt.Sprintf("failed to parse bid mtype (%d) for impression id %s", bid.MType, bid.ImpID),
Message: fmt.Sprintf("failed to parse bid mtype (%d) for impression id %s", bid.MType, bid.ImpID),

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed extra space

}
}
}
return bidType
return mType, nil
}

// Builder builds a new instance of the Pubmatic adapter for the given bidder with the given config.
Expand Down
196 changes: 150 additions & 46 deletions adapters/pubmatic/pubmatic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/prebid/prebid-server/v3/adapters"
"github.com/prebid/prebid-server/v3/adapters/adapterstest"
"github.com/prebid/prebid-server/v3/config"
"github.com/prebid/prebid-server/v3/errortypes"
"github.com/prebid/prebid-server/v3/openrtb_ext"
"github.com/stretchr/testify/assert"
)
Expand All @@ -26,52 +27,66 @@ func TestJsonSamples(t *testing.T) {
adapterstest.RunJSONBidderTest(t, "pubmatictest", bidder)
}

func TestGetBidTypeVideo(t *testing.T) {
pubmaticExt := &pubmaticBidExt{}
pubmaticExt.BidType = new(int)
*pubmaticExt.BidType = 1
actualBidTypeValue := getBidType(pubmaticExt)
if actualBidTypeValue != openrtb_ext.BidTypeVideo {
t.Errorf("Expected Bid Type value was: %v, actual value is: %v", openrtb_ext.BidTypeVideo, actualBidTypeValue)
}
}

func TestGetBidTypeForMissingBidTypeExt(t *testing.T) {
pubmaticExt := &pubmaticBidExt{}
actualBidTypeValue := getBidType(pubmaticExt)
// banner is the default bid type when no bidType key is present in the bid.ext
if actualBidTypeValue != "banner" {
t.Errorf("Expected Bid Type value was: banner, actual value is: %v", actualBidTypeValue)
}
}

func TestGetBidTypeBanner(t *testing.T) {
pubmaticExt := &pubmaticBidExt{}
pubmaticExt.BidType = new(int)
*pubmaticExt.BidType = 0
actualBidTypeValue := getBidType(pubmaticExt)
if actualBidTypeValue != openrtb_ext.BidTypeBanner {
t.Errorf("Expected Bid Type value was: %v, actual value is: %v", openrtb_ext.BidTypeBanner, actualBidTypeValue)
}
}

func TestGetBidTypeNative(t *testing.T) {
pubmaticExt := &pubmaticBidExt{}
pubmaticExt.BidType = new(int)
*pubmaticExt.BidType = 2
actualBidTypeValue := getBidType(pubmaticExt)
if actualBidTypeValue != openrtb_ext.BidTypeNative {
t.Errorf("Expected Bid Type value was: %v, actual value is: %v", openrtb_ext.BidTypeNative, actualBidTypeValue)
func TestGetMediaTypeForBid(t *testing.T) {
tests := []struct {
name string
mType openrtb2.MarkupType
expectedMType openrtb_ext.BidType
expectedError error
}{
{
name: "Test Banner Bid Type",
mType: 1,
expectedMType: openrtb_ext.BidTypeBanner,
expectedError: nil,
},
{
name: "Test Video Bid Type",
mType: 2,
expectedMType: openrtb_ext.BidTypeVideo,
expectedError: nil,
},
{
name: "Test Audio Bid Type",
mType: 3,
expectedMType: openrtb_ext.BidTypeAudio,
expectedError: nil,
},
{
name: "Test Native Bid Type",
mType: 4,
expectedMType: openrtb_ext.BidTypeNative,
expectedError: nil,
},
{
name: "Test Unsupported MType (Invalid MType)",
mType: 44,
expectedMType: "", // default value for unsupported types
expectedError: &errortypes.BadServerResponse{Message: "failed to parse bid mtype (44) for impression id "},
},
{
name: "Test Default MType (MType 0 or Not Set)",
mType: 0, // This represents the default case where MType is not explicitly set
expectedMType: "", // Default is empty and return error
expectedError: &errortypes.BadServerResponse{Message: "failed to parse bid mtype (0) for impression id "},
},
}
}

func TestGetBidTypeForUnsupportedCode(t *testing.T) {
pubmaticExt := &pubmaticBidExt{}
pubmaticExt.BidType = new(int)
*pubmaticExt.BidType = 99
actualBidTypeValue := getBidType(pubmaticExt)
if actualBidTypeValue != openrtb_ext.BidTypeBanner {
t.Errorf("Expected Bid Type value was: %v, actual value is: %v", openrtb_ext.BidTypeBanner, actualBidTypeValue)
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Bid := openrtb2.Bid{
MType: tt.mType,
}
actualBidTypeValue, actualError := getMediaTypeForBid(&Bid)
if actualBidTypeValue != tt.expectedMType {
t.Errorf("Expected Bid Type value was: %v, actual value is: %v", tt.expectedMType, actualBidTypeValue)
}
if tt.expectedError != nil && actualError == nil {
t.Errorf("Expected error: %v, but got nil", tt.expectedError)
} else if tt.expectedError != nil && actualError != nil && actualError.Error() != tt.expectedError.Error() {
Copy link
Contributor

@guscarreon guscarreon Mar 11, 2025

Choose a reason for hiding this comment

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

The if-else statement seems to not compare an tt.expectedError equal to nil. If tt.expectedError equals nil, shouldn't we assert that actualError is also nil?

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 check if expectedError is nil.
Modified code accordingly.

t.Errorf("Expected error: %v, but got: %v", tt.expectedError, actualError)
}
})
}
}

Expand Down Expand Up @@ -398,7 +413,7 @@ func TestPubmaticAdapter_MakeBids(t *testing.T) {
args: args{
response: &adapters.ResponseData{
StatusCode: http.StatusOK,
Body: []byte(`{"id": "test-request-id", "seatbid":[{"seat": "958", "bid":[{"id": "7706636740145184841", "impid": "test-imp-id", "price": 0.500000, "adid": "29681110", "adm": "some-test-ad", "adomain":["pubmatic.com"], "crid": "29681110", "h": 250, "w": 300, "dealid": "testdeal", "ext":{"dspid": 6, "deal_channel": 1, "prebiddealpriority": 1}}]}], "bidid": "5778926625248726496", "cur": "USD"}`),
Body: []byte(`{"id": "test-request-id", "seatbid":[{"seat": "958", "bid":[{"id": "7706636740145184841", "impid": "test-imp-id", "price": 0.500000, "adid": "29681110", "adm": "some-test-ad", "adomain":["pubmatic.com"], "crid": "29681110", "h": 250, "w": 300, "dealid": "testdeal", "mtype": 1, "ext":{"dspid": 6, "deal_channel": 1, "prebiddealpriority": 1}}]}], "bidid": "5778926625248726496", "cur": "USD"}`),
},
},
wantErr: nil,
Expand All @@ -416,11 +431,30 @@ func TestPubmaticAdapter_MakeBids(t *testing.T) {
H: 250,
W: 300,
DealID: "testdeal",
MType: 1,
Ext: json.RawMessage(`{"dspid": 6, "deal_channel": 1, "prebiddealpriority": 1}`),
},
DealPriority: 1,
BidType: openrtb_ext.BidTypeBanner,
BidVideo: &openrtb_ext.ExtBidPrebidVideo{},
BidMeta: &openrtb_ext.ExtBidPrebidMeta{
AdapterCode: "",
AdvertiserDomains: nil,
AdvertiserID: 0,
AdvertiserName: "",
AgencyID: 0,
AgencyName: "",
DChain: nil,
DemandSource: "",
MediaType: "banner",
NetworkID: 0,
NetworkName: "",
RendererName: "",
RendererVersion: "",
RendererData: nil,
RendererUrl: "",
SecondaryCategoryIDs: nil,
},
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick: reduce complexity by omitting "zero values"

Suggested change
BidMeta: &openrtb_ext.ExtBidPrebidMeta{
AdapterCode: "",
AdvertiserDomains: nil,
AdvertiserID: 0,
AdvertiserName: "",
AgencyID: 0,
AgencyName: "",
DChain: nil,
DemandSource: "",
MediaType: "banner",
NetworkID: 0,
NetworkName: "",
RendererName: "",
RendererVersion: "",
RendererData: nil,
RendererUrl: "",
SecondaryCategoryIDs: nil,
},
BidMeta: &openrtb_ext.ExtBidPrebidMeta{
MediaType: "banner",
},

},
},
Currency: "USD",
Expand All @@ -431,7 +465,7 @@ func TestPubmaticAdapter_MakeBids(t *testing.T) {
args: args{
response: &adapters.ResponseData{
StatusCode: http.StatusOK,
Body: []byte(`{"id": "test-request-id", "seatbid":[{"seat": "958", "bid":[{"id": "7706636740145184841", "impid": "test-imp-id", "price": 0.500000, "adid": "29681110", "adm": "some-test-ad", "adomain":["pubmatic.com"], "crid": "29681110", "h": 250, "w": 300, "dealid": "testdeal", "ext":{"dspid": 6, "deal_channel": 1, "prebiddealpriority": -1}}]}], "bidid": "5778926625248726496", "cur": "USD"}`),
Body: []byte(`{"id": "test-request-id", "seatbid":[{"seat": "958", "bid":[{"id": "7706636740145184841", "impid": "test-imp-id", "price": 0.500000, "adid": "29681110", "adm": "some-test-ad", "adomain":["pubmatic.com"], "crid": "29681110", "h": 250, "w": 300, "dealid": "testdeal","mtype": 1, "ext":{"dspid": 6, "deal_channel": 1, "prebiddealpriority": -1}}]}], "bidid": "5778926625248726496", "cur": "USD"}`),
},
},
wantErr: nil,
Expand All @@ -449,10 +483,80 @@ func TestPubmaticAdapter_MakeBids(t *testing.T) {
H: 250,
W: 300,
DealID: "testdeal",
MType: 1,
Ext: json.RawMessage(`{"dspid": 6, "deal_channel": 1, "prebiddealpriority": -1}`),
},
BidType: openrtb_ext.BidTypeBanner,
BidVideo: &openrtb_ext.ExtBidPrebidVideo{},
BidMeta: &openrtb_ext.ExtBidPrebidMeta{
AdapterCode: "",
AdvertiserDomains: nil,
AdvertiserID: 0,
AdvertiserName: "",
AgencyID: 0,
AgencyName: "",
DChain: nil,
DemandSource: "",
MediaType: "banner",
NetworkID: 0,
NetworkName: "",
RendererName: "",
RendererVersion: "",
RendererData: nil,
RendererUrl: "",
SecondaryCategoryIDs: nil,
},
},
},
Currency: "USD",
},
},
{
name: "bid_ext_InBannerVideo_is_true",
args: args{
response: &adapters.ResponseData{
StatusCode: http.StatusOK,
Body: []byte(`{"id": "test-request-id", "seatbid":[{"seat": "958", "bid":[{"id": "7706636740145184841", "impid": "test-imp-id", "price": 0.500000, "adid": "29681110", "adm": "some-test-ad", "adomain":["pubmatic.com"], "crid": "29681110", "h": 250, "w": 300, "dealid": "testdeal", "mtype": 1, "ext":{"dspid": 6, "deal_channel": 1, "prebiddealpriority": -1, "ibv": true}}]}], "bidid": "5778926625248726496", "cur": "USD"}`),
},
},
wantErr: nil,
wantResp: &adapters.BidderResponse{
Bids: []*adapters.TypedBid{
{
Bid: &openrtb2.Bid{
ID: "7706636740145184841",
ImpID: "test-imp-id",
Price: 0.500000,
AdID: "29681110",
AdM: "some-test-ad",
ADomain: []string{"pubmatic.com"},
CrID: "29681110",
H: 250,
W: 300,
DealID: "testdeal",
MType: 1,
Ext: json.RawMessage(`{"dspid": 6, "deal_channel": 1, "prebiddealpriority": -1, "ibv": true}`),
},
BidType: openrtb_ext.BidTypeBanner,
BidVideo: &openrtb_ext.ExtBidPrebidVideo{},
BidMeta: &openrtb_ext.ExtBidPrebidMeta{
AdapterCode: "",
AdvertiserDomains: nil,
AdvertiserID: 0,
AdvertiserName: "",
AgencyID: 0,
AgencyName: "",
DChain: nil,
DemandSource: "",
MediaType: "video",
NetworkID: 0,
NetworkName: "",
RendererName: "",
RendererVersion: "",
RendererData: nil,
RendererUrl: "",
SecondaryCategoryIDs: nil,
},
},
},
Currency: "USD",
Expand Down
2 changes: 2 additions & 0 deletions adapters/pubmatic/pubmatictest/exemplary/banner.json
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@
"h": 250,
"w": 300,
"dealid":"test deal",
"mtype": 1,
"ext": {
"dspid": 6,
"deal_channel": 1,
Expand Down Expand Up @@ -142,6 +143,7 @@
"w": 300,
"h": 250,
"dealid":"test deal",
"mtype": 1,
"ext": {
"dspid": 6,
"deal_channel": 1,
Expand Down
2 changes: 2 additions & 0 deletions adapters/pubmatic/pubmatictest/exemplary/fledge.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
"crid": "crid_10",
"h": 90,
"w": 728,
"mtype": 1,
"ext": {}
}
]
Expand Down Expand Up @@ -123,6 +124,7 @@
"crid": "crid_10",
"w": 728,
"h": 90,
"mtype": 1,
"ext": {}
},
"type": "banner"
Expand Down
2 changes: 2 additions & 0 deletions adapters/pubmatic/pubmatictest/exemplary/native.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
"adid": "some-test-id",
"adm": "{\"native\":{\"assets\":[{\"id\":2,\"img\":{\"h\":90,\"url\":\"//ads.pubmatic.com/AdTag/native/728x90.png\",\"w\":728}},{\"data\":{\"value\":\"Sponsored By PubMatic\"},\"id\":4},{\"id\":3,\"img\":{\"h\":90,\"url\":\"//ads.pubmatic.com/AdTag/native/728x90.png\",\"w\":728}},{\"id\":1,\"title\":{\"text\":\"Native Test Title\"}},{\"data\":{\"value\":\"Sponsored By PubMatic\"},\"id\":5}],\"imptrackers\":[\"http://clicktracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35\"],\"jstracker\":\"<script src='\\\/\\\/ads.pubmatic.com\\\/AdTag\\\/native\\\/tempReseponse.js'><script src='\\\/\\\/ads.pubmatic.com\\\/AdTag\\\/native\\\/tempReseponse.js'>\",\"link\":{\"clicktrackers\":[\"http://clicktracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35\"],\"fallback\":\"http://www.pubmatic.com\",\"url\":\"//www.pubmatic.com\"}}}",
"crid": "29681110",
"mtype":4,
"ext": {
"deal_channel": 1,
"bidtype": 2
Expand All @@ -102,6 +103,7 @@
"adid": "some-test-id",
"adm": "{\"assets\":[{\"id\":2,\"img\":{\"h\":90,\"url\":\"//ads.pubmatic.com/AdTag/native/728x90.png\",\"w\":728}},{\"data\":{\"value\":\"Sponsored By PubMatic\"},\"id\":4},{\"id\":3,\"img\":{\"h\":90,\"url\":\"//ads.pubmatic.com/AdTag/native/728x90.png\",\"w\":728}},{\"id\":1,\"title\":{\"text\":\"Native Test Title\"}},{\"data\":{\"value\":\"Sponsored By PubMatic\"},\"id\":5}],\"imptrackers\":[\"http://clicktracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35\"],\"jstracker\":\"<script src='\\\/\\\/ads.pubmatic.com\\\/AdTag\\\/native\\\/tempReseponse.js'><script src='\\\/\\\/ads.pubmatic.com\\\/AdTag\\\/native\\\/tempReseponse.js'>\",\"link\":{\"clicktrackers\":[\"http://clicktracker.com/AdTag/9bde02d0-6017-11e4-9df7-005056967c35\"],\"fallback\":\"http://www.pubmatic.com\",\"url\":\"//www.pubmatic.com\"}}",
"crid": "29681110",
"mtype":4,
"ext": {
"deal_channel": 1,
"bidtype": 2
Expand Down
Loading
Loading