Skip to content

Commit

Permalink
Better fix for bad exchanges
Browse files Browse the repository at this point in the history
  • Loading branch information
dim committed Apr 16, 2017
1 parent 491cb5c commit 9c96622
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 56 deletions.
54 changes: 27 additions & 27 deletions bid.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,33 +16,33 @@ var (
// Cid can be used to block ads that were previously identified as inappropriate.
// Substitution macros may allow a bidder to use a static notice URL for all of its bids.
type Bid struct {
ID string `json:"id"`
ImpID string `json:"impid"` // Required string ID of the impression object to which this bid applies.
Price float64 `json:"price"` // Bid price in CPM. Suggests using integer math for accounting to avoid rounding errors.
AdID string `json:"adid,omitempty"` // References the ad to be served if the bid wins.
NURL string `json:"nurl,omitempty"` // Win notice URL.
BURL string `json:"burl,omitempty"` // Billing notice URL.
LURL string `json:"lurl,omitempty"` // Loss notice URL.
AdMarkup string `json:"adm,omitempty"` // Actual ad markup. XHTML if a response to a banner object, or VAST XML if a response to a video object.
AdvDomain []string `json:"adomain,omitempty"` // Advertiser’s primary or top-level domain for advertiser checking; or multiple if imp rotating.
Bundle string `json:"bundle,omitempty"` // A platform-specific application identifier intended to be unique to the app and independent of the exchange.
IURL string `json:"iurl,omitempty"` // Sample image URL.
CampaignID string `json:"cid,omitempty"` // Campaign ID that appears with the Ad markup.
CreativeID string `json:"crid,omitempty"` // Creative ID for reporting content issues or defects. This could also be used as a reference to a creative ID that is posted with an exchange.
Tactic string `json:"tactic,omitempty"` // Tactic ID to enable buyers to label bids for reporting to the exchange the tactic through which their bid was submitted.
Cat []string `json:"cat,omitempty"` // IAB content categories of the creative. Refer to List 5.1
Attr []int `json:"attr,omitempty"` // Array of creative attributes.
API int `json:"api,omitempty"` // API required by the markup if applicable
Protocol int `json:"protocol,omitempty"` // Video response protocol of the markup if applicable
QAGMediaRating int `json:"qagmediarating,omitempty"` // Creative media rating per IQG guidelines.
Language string `json:"language,omitempty"` // Language of the creative using ISO-639-1-alpha-2.
DealID string `json:"dealid,omitempty"` // DealID extension of private marketplace deals
H int `json:"h,omitempty"` // Height of the ad in pixels.
W int `json:"w,omitempty"` // Width of the ad in pixels.
WRatio int `json:"wratio,omitempty"` // Relative width of the creative when expressing size as a ratio.
HRatio int `json:"hratio,omitempty"` // Relative height of the creative when expressing size as a ratio.
Exp int `json:"exp,omitempty"` // Advisory as to the number of seconds the bidder is willing to wait between the auction and the actual impression.
Ext Extension `json:"ext,omitempty"`
ID string `json:"id"`
ImpID string `json:"impid"` // Required string ID of the impression object to which this bid applies.
Price float64 `json:"price"` // Bid price in CPM. Suggests using integer math for accounting to avoid rounding errors.
AdID string `json:"adid,omitempty"` // References the ad to be served if the bid wins.
NURL string `json:"nurl,omitempty"` // Win notice URL.
BURL string `json:"burl,omitempty"` // Billing notice URL.
LURL string `json:"lurl,omitempty"` // Loss notice URL.
AdMarkup string `json:"adm,omitempty"` // Actual ad markup. XHTML if a response to a banner object, or VAST XML if a response to a video object.
AdvDomain []string `json:"adomain,omitempty"` // Advertiser’s primary or top-level domain for advertiser checking; or multiple if imp rotating.
Bundle string `json:"bundle,omitempty"` // A platform-specific application identifier intended to be unique to the app and independent of the exchange.
IURL string `json:"iurl,omitempty"` // Sample image URL.
CampaignID StringOrNumber `json:"cid,omitempty"` // Campaign ID that appears with the Ad markup.
CreativeID string `json:"crid,omitempty"` // Creative ID for reporting content issues or defects. This could also be used as a reference to a creative ID that is posted with an exchange.
Tactic string `json:"tactic,omitempty"` // Tactic ID to enable buyers to label bids for reporting to the exchange the tactic through which their bid was submitted.
Cat []string `json:"cat,omitempty"` // IAB content categories of the creative. Refer to List 5.1
Attr []int `json:"attr,omitempty"` // Array of creative attributes.
API int `json:"api,omitempty"` // API required by the markup if applicable
Protocol int `json:"protocol,omitempty"` // Video response protocol of the markup if applicable
QAGMediaRating int `json:"qagmediarating,omitempty"` // Creative media rating per IQG guidelines.
Language string `json:"language,omitempty"` // Language of the creative using ISO-639-1-alpha-2.
DealID string `json:"dealid,omitempty"` // DealID extension of private marketplace deals
H int `json:"h,omitempty"` // Height of the ad in pixels.
W int `json:"w,omitempty"` // Width of the ad in pixels.
WRatio int `json:"wratio,omitempty"` // Relative width of the creative when expressing size as a ratio.
HRatio int `json:"hratio,omitempty"` // Relative height of the creative when expressing size as a ratio.
Exp int `json:"exp,omitempty"` // Advisory as to the number of seconds the bidder is willing to wait between the auction and the actual impression.
Ext Extension `json:"ext,omitempty"`
}

// Validate required attributes
Expand Down
4 changes: 1 addition & 3 deletions bidrequest_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package openrtb

import (
"encoding/json"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
Expand Down Expand Up @@ -30,7 +28,7 @@ var _ = Describe("BidRequest", func() {
Imp: []Impression{
{
ID: "1",
Secure: json.Number("1"),
Secure: 1,
Banner: &Banner{W: 300, H: 250, Pos: AdPosAboveFold, BAttr: []int{CreativeAttributeUserInitiated}},
},
},
Expand Down
37 changes: 17 additions & 20 deletions impression.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package openrtb

import (
"encoding/json"
"errors"
)
import "errors"

// Validation errors
var (
Expand All @@ -19,22 +16,22 @@ var (
// The presence of Banner, Video, and/or Native objects
// subordinate to the Imp object indicates the type of impression being offered.
type Impression struct {
ID string `json:"id"` // A unique identifier for this impression
Banner *Banner `json:"banner,omitempty"`
Video *Video `json:"video,omitempty"`
Audio *Audio `json:"audio,omitempty"`
Native *Native `json:"native,omitempty"`
Pmp *Pmp `json:"pmp,omitempty"` // A reference to the PMP object containing any Deals eligible for the impression object.
DisplayManager string `json:"displaymanager,omitempty"` // Name of ad mediation partner, SDK technology, etc
DisplayManagerVer string `json:"displaymanagerver,omitempty"` // Version of the above
Instl int `json:"instl,omitempty"` // Interstitial, Default: 0 ("1": Interstitial, "0": Something else)
TagID string `json:"tagid,omitempty"` // IDentifier for specific ad placement or ad tag
BidFloor float64 `json:"bidfloor,omitempty"` // Bid floor for this impression in CPM
BidFloorCurrency string `json:"bidfloorcur,omitempty"` // Currency of bid floor
Secure json.Number `json:"secure,omitempty"` // Flag to indicate whether the impression requires secure HTTPS URL creative assets and markup.
Exp int `json:"exp,omitempty"` // Advisory as to the number of seconds that may elapse between the auction and the actual impression.
IFrameBuster []string `json:"iframebuster,omitempty"` // Array of names for supportediframe busters.
Ext Extension `json:"ext,omitempty"`
ID string `json:"id"` // A unique identifier for this impression
Banner *Banner `json:"banner,omitempty"`
Video *Video `json:"video,omitempty"`
Audio *Audio `json:"audio,omitempty"`
Native *Native `json:"native,omitempty"`
Pmp *Pmp `json:"pmp,omitempty"` // A reference to the PMP object containing any Deals eligible for the impression object.
DisplayManager string `json:"displaymanager,omitempty"` // Name of ad mediation partner, SDK technology, etc
DisplayManagerVer string `json:"displaymanagerver,omitempty"` // Version of the above
Instl int `json:"instl,omitempty"` // Interstitial, Default: 0 ("1": Interstitial, "0": Something else)
TagID string `json:"tagid,omitempty"` // IDentifier for specific ad placement or ad tag
BidFloor float64 `json:"bidfloor,omitempty"` // Bid floor for this impression in CPM
BidFloorCurrency string `json:"bidfloorcur,omitempty"` // Currency of bid floor
Secure NumberOrString `json:"secure,omitempty"` // Flag to indicate whether the impression requires secure HTTPS URL creative assets and markup.
Exp int `json:"exp,omitempty"` // Advisory as to the number of seconds that may elapse between the auction and the actual impression.
IFrameBuster []string `json:"iframebuster,omitempty"` // Array of names for supportediframe busters.
Ext Extension `json:"ext,omitempty"`
}

func (imp *Impression) assetCount() int {
Expand Down
12 changes: 6 additions & 6 deletions native/response/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import "github.com/bsm/openrtb"

// The native object is the top level JSON object which identifies a native response
type Response struct {
Ver string `json:"ver,omitempty"` // Version of the Native Markup
Assets []Asset `json:"assets"` // An array of Asset Objects
Link Link `json:"link"` // Destination Link. This is default link object for the ad
ImpTrackers []string `json:"imptrackers,omitempty"` // Array of impression tracking URLs, expected to return a 1x1 image or 204 response
JSTracker string `json:"jstracker,omitempty"` // Optional JavaScript impression tracker. This is a valid HTML, Javascript is already wrapped in <script> tags. It should be executed at impression time where it can be supported
Ext openrtb.Extension `json:"ext,omitempty"`
Ver openrtb.StringOrNumber `json:"ver,omitempty"` // Version of the Native Markup
Assets []Asset `json:"assets"` // An array of Asset Objects
Link Link `json:"link"` // Destination Link. This is default link object for the ad
ImpTrackers []string `json:"imptrackers,omitempty"` // Array of impression tracking URLs, expected to return a 1x1 image or 204 response
JSTracker string `json:"jstracker,omitempty"` // Optional JavaScript impression tracker. This is a valid HTML, Javascript is already wrapped in <script> tags. It should be executed at impression time where it can be supported
Ext openrtb.Extension `json:"ext,omitempty"`
}
53 changes: 53 additions & 0 deletions numbers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package openrtb

import (
"encoding/json"
"strconv"
)

// NumberOrString attempts to fix OpenRTB incompatibilities
// of exchanges. On decoding, it can handle numbers and strings.
// On encoding, it will generate a number, as intended by the
// standard.
type NumberOrString int

// UnmarshalJSON implements json.Unmarshaler
func (n *NumberOrString) UnmarshalJSON(data []byte) (err error) {
var v int

if len(data) > 2 && data[0] == '"' && data[len(data)-1] == '"' {
err = json.Unmarshal(data[1:len(data)-1], &v)
} else {
err = json.Unmarshal(data, &v)
}
if err != nil {
return err
}

*n = NumberOrString(v)
return nil
}

// StringOrNumber attempts to fix OpenRTB incompatibilities
// of exchanges. On decoding, it can handle numbers and strings.
// On encoding, it will generate a string, as intended by the
// standard.
type StringOrNumber string

// UnmarshalJSON implements json.Unmarshaler
func (n *StringOrNumber) UnmarshalJSON(data []byte) error {
if len(data) > 2 && data[0] == '"' && data[len(data)-1] == '"' {
var v string
if err := json.Unmarshal(data, &v); err != nil {
return err
}
*n = StringOrNumber(v)
} else {
var v int
if err := json.Unmarshal(data, &v); err != nil {
return err
}
*n = StringOrNumber(strconv.Itoa(v))
}
return nil
}
54 changes: 54 additions & 0 deletions numbers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package openrtb

import (
"encoding/json"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)

var _ = Describe("NumberOrString", func() {

It("should decode numbers", func() {
var n NumberOrString
Expect(json.Unmarshal([]byte(`33`), &n)).To(Succeed())
Expect(n).To(Equal(NumberOrString(33)))
})

It("should decode strings", func() {
var n NumberOrString
Expect(json.Unmarshal([]byte(`"33"`), &n)).To(Succeed())
Expect(n).To(Equal(NumberOrString(33)))
})

It("should encode to numbers", func() {
var n NumberOrString = 33
bin, err := json.Marshal(n)
Expect(err).NotTo(HaveOccurred())
Expect(string(bin)).To(Equal(`33`))
})

})

var _ = Describe("StringOrNumber", func() {

It("should decode numbers", func() {
var n StringOrNumber
Expect(json.Unmarshal([]byte(`33`), &n)).To(Succeed())
Expect(n).To(Equal(StringOrNumber("33")))
})

It("should decode strings", func() {
var n StringOrNumber
Expect(json.Unmarshal([]byte(`"33"`), &n)).To(Succeed())
Expect(n).To(Equal(StringOrNumber("33")))
})

It("should encode to strings", func() {
var n StringOrNumber = "33"
bin, err := json.Marshal(n)
Expect(err).NotTo(HaveOccurred())
Expect(string(bin)).To(Equal(`"33"`))
})

})

0 comments on commit 9c96622

Please sign in to comment.