Skip to content

Commit 5547ba6

Browse files
authored
support oRTB 2.6 qty field in impressions object (bsm#111)
1 parent 5563255 commit 5547ba6

File tree

6 files changed

+110
-2
lines changed

6 files changed

+110
-2
lines changed

impression.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ type Impression struct {
3232
BidFloor float64 `json:"bidfloor,omitempty"` // Bid floor for this impression in CPM
3333
BidFloorCurrency string `json:"bidfloorcur,omitempty"` // Currency of bid floor
3434
Secure NumberOrString `json:"secure,omitempty"` // Flag to indicate whether the impression requires secure HTTPS URL creative assets and markup.
35-
Exp int `json:"exp,omitempty"` // Advisory as to the number of seconds that may elapse between the auction and the actual impression.
36-
IFrameBusters []string `json:"iframebuster,omitempty"` // Array of names for supportediframe busters.
35+
Quantity *Quantity `json:"qty,omitempty"` // Includes the impression multiplier, and describes its source.
36+
Exp int `json:"exp,omitempty"` // Advisory as to the number of seconds that may elapse between the auction and the actual impression.
37+
IFrameBusters []string `json:"iframebuster,omitempty"` // Array of names for supportediframe busters.
3738
Ext json.RawMessage `json:"ext,omitempty"`
3839
}
3940

@@ -66,6 +67,11 @@ func (imp *Impression) Validate() error {
6667
return err
6768
}
6869
}
70+
if imp.Quantity != nil {
71+
if err := imp.Quantity.Validate(); err != nil {
72+
return err
73+
}
74+
}
6975

7076
return nil
7177
}

impression_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ func TestImpression(t *testing.T) {
3131
},
3232
},
3333
},
34+
Quantity: &Quantity{
35+
Multiplier: 1.0,
36+
},
3437
}
3538
if got := subject; !reflect.DeepEqual(exp, got) {
3639
t.Errorf("expected %+v, got %+v", exp, got)

quantity.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package openrtb
2+
3+
import (
4+
"encoding/json"
5+
"errors"
6+
)
7+
8+
var (
9+
ErrMissingMultiplier = errors.New("openrtb: qty.multiplier is required")
10+
ErrMissingMeasurementVendor = errors.New("openrtb: qty.vendor is required when qty.sourcetype is 1 (Measurement Vendor)")
11+
)
12+
13+
type MeasurementSourceType int
14+
15+
const (
16+
MeasurementSourceTypeUnknown MeasurementSourceType = 0
17+
MeasurementSourceTypeMeasurementVendor MeasurementSourceType = 1
18+
MeasurementSourceTypePublisher MeasurementSourceType = 2
19+
MeasurementSourceTypeExchange MeasurementSourceType = 3
20+
)
21+
22+
type Quantity struct {
23+
Multiplier float64 `json:"multiplier"`
24+
SourceType MeasurementSourceType `json:"sourcetype,omitempty"`
25+
Vendor string `json:"vendor,omitempty"`
26+
Ext *json.RawMessage `json:"ext,omitempty"`
27+
}
28+
29+
func (qty *Quantity) Validate() error {
30+
if qty.Multiplier == 0 {
31+
return ErrMissingMultiplier
32+
}
33+
if qty.SourceType == MeasurementSourceTypeMeasurementVendor && qty.Vendor == "" {
34+
return ErrMissingMeasurementVendor
35+
}
36+
return nil
37+
}

quantity_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package openrtb_test
2+
3+
import (
4+
"reflect"
5+
"testing"
6+
7+
. "github.com/bsm/openrtb/v3"
8+
)
9+
10+
func TestQuantity(t *testing.T) {
11+
var subject *Quantity
12+
if err := fixture("quantity", &subject); err != nil {
13+
t.Fatalf("expected no error, got %+v", err)
14+
}
15+
16+
exp := &Quantity{
17+
Multiplier: 3.14,
18+
SourceType: MeasurementSourceTypePublisher,
19+
}
20+
21+
if !reflect.DeepEqual(exp, subject) {
22+
t.Fatalf("expected %+v, got %+v", exp, subject)
23+
}
24+
}
25+
26+
func TestQuantity_Validate(t *testing.T) {
27+
subject := Quantity{}
28+
if got := subject.Validate(); got != ErrMissingMultiplier {
29+
t.Fatalf("expected %+v, got %+v", ErrMissingMultiplier, got)
30+
}
31+
32+
// If MeasurementSourceType is MeasurementSourceTypeMeasurementVendor, the
33+
// Vendor field should not be empty.
34+
subject = Quantity{
35+
Multiplier: 1.0,
36+
SourceType: MeasurementSourceTypeMeasurementVendor,
37+
}
38+
if got := subject.Validate(); got != ErrMissingMeasurementVendor {
39+
t.Fatalf("expected %+v, got %+v", ErrMissingMeasurementVendor, got)
40+
}
41+
42+
subject.Vendor = "TestVendor" // Should fix the invalid Quantity
43+
if got := subject.Validate(); got != nil {
44+
t.Fatalf("expected no error, got %+v", got)
45+
}
46+
47+
// All other value from MeasurementSourceType can be used without Vendor
48+
subject = Quantity{
49+
Multiplier: 2.0,
50+
SourceType: MeasurementSourceTypeUnknown,
51+
}
52+
if got := subject.Validate(); got != nil {
53+
t.Fatalf("expected nil, got %+v", got)
54+
}
55+
}

testdata/impression.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,8 @@
1515
"at": 2
1616
}
1717
]
18+
},
19+
"qty": {
20+
"multiplier": 1.0
1821
}
1922
}

testdata/quantity.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"multiplier": 3.14,
3+
"sourcetype": 2
4+
}

0 commit comments

Comments
 (0)