From aa04a26112e5bb15becb610721591aae611ff97c Mon Sep 17 00:00:00 2001
From: Nabib El-Rahman <nabib@unity3d.com>
Date: Fri, 30 Jun 2017 13:49:22 -0700
Subject: [PATCH 01/54] Forked bsm/openrtb project to not enforce min/max
 duration

---
 README.md                      | 6 +++---
 native/request/asset.go        | 2 +-
 native/request/data.go         | 2 +-
 native/request/image.go        | 2 +-
 native/request/request.go      | 2 +-
 native/request/request_test.go | 2 +-
 native/request/title.go        | 2 +-
 native/request/video.go        | 2 +-
 native/response/asset.go       | 2 +-
 native/response/data.go        | 2 +-
 native/response/image.go       | 2 +-
 native/response/link.go        | 2 +-
 native/response/response.go    | 2 +-
 native/response/title.go       | 2 +-
 video.go                       | 4 ----
 video_test.go                  | 9 ---------
 16 files changed, 16 insertions(+), 29 deletions(-)

diff --git a/README.md b/README.md
index 04d30a2..92d134e 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # Go OpenRTB v2.x
 
-[![Build Status](https://travis-ci.org/bsm/openrtb.svg?branch=master)](https://travis-ci.org/bsm/openrtb)
+[![Build Status](https://travis-ci.org/UnityTech/openrtb.svg?branch=master)](https://travis-ci.org/UnityTech/openrtb)
 
 OpenRTB implementation for Go
 
@@ -9,7 +9,7 @@ OpenRTB implementation for Go
 To install, use `go get`:
 
 ```shell
-go get github.com/bsm/openrtb
+go get github.com/UnityTech/openrtb
 ```
 
 ## Usage
@@ -21,7 +21,7 @@ package main
 
 import (
   "log"
-  "github.com/bsm/openrtb"
+  "github.com/UnityTech/openrtb"
 )
 
 func main() {
diff --git a/native/request/asset.go b/native/request/asset.go
index da514d1..24bf60b 100644
--- a/native/request/asset.go
+++ b/native/request/asset.go
@@ -1,6 +1,6 @@
 package request
 
-import "github.com/bsm/openrtb"
+import "github.com/UnityTech/openrtb"
 
 // The main container object for each asset requested or supported by Exchange
 // on behalf of the rendering client.  Only one of the {title,img,video,data}
diff --git a/native/request/data.go b/native/request/data.go
index a3723b7..5e8fa2a 100644
--- a/native/request/data.go
+++ b/native/request/data.go
@@ -1,6 +1,6 @@
 package request
 
-import "github.com/bsm/openrtb"
+import "github.com/UnityTech/openrtb"
 
 type DataTypeID int
 
diff --git a/native/request/image.go b/native/request/image.go
index 5864344..a3a2c4e 100644
--- a/native/request/image.go
+++ b/native/request/image.go
@@ -1,6 +1,6 @@
 package request
 
-import "github.com/bsm/openrtb"
+import "github.com/UnityTech/openrtb"
 
 type ImageTypeID int
 
diff --git a/native/request/request.go b/native/request/request.go
index a05d896..d9a4468 100644
--- a/native/request/request.go
+++ b/native/request/request.go
@@ -1,6 +1,6 @@
 package request
 
-import "github.com/bsm/openrtb"
+import "github.com/UnityTech/openrtb"
 
 type LayoutID int
 
diff --git a/native/request/request_test.go b/native/request/request_test.go
index 0f84260..fbdd2ad 100644
--- a/native/request/request_test.go
+++ b/native/request/request_test.go
@@ -5,7 +5,7 @@ import (
 	"io/ioutil"
 	"testing"
 
-	"github.com/bsm/openrtb"
+	"github.com/UnityTech/openrtb"
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
 )
diff --git a/native/request/title.go b/native/request/title.go
index b3bf1b9..e60669f 100644
--- a/native/request/title.go
+++ b/native/request/title.go
@@ -1,6 +1,6 @@
 package request
 
-import "github.com/bsm/openrtb"
+import "github.com/UnityTech/openrtb"
 
 type Title struct {
 	Length int               `json:"len"` // Maximum length of the text in the title element
diff --git a/native/request/video.go b/native/request/video.go
index cc9a5cb..48618eb 100644
--- a/native/request/video.go
+++ b/native/request/video.go
@@ -1,6 +1,6 @@
 package request
 
-import "github.com/bsm/openrtb"
+import "github.com/UnityTech/openrtb"
 
 // TODO unclear if its the same as imp.video https://github.com/openrtb/OpenRTB/issues/26
 type Video struct {
diff --git a/native/response/asset.go b/native/response/asset.go
index c657ddc..612bdb6 100644
--- a/native/response/asset.go
+++ b/native/response/asset.go
@@ -1,6 +1,6 @@
 package response
 
-import "github.com/bsm/openrtb"
+import "github.com/UnityTech/openrtb"
 
 // Corresponds to the Asset Object in the request. The main container object for
 // each asset requested or supported by Exchange on behalf of the rendering
diff --git a/native/response/data.go b/native/response/data.go
index e8af8aa..8afe5aa 100644
--- a/native/response/data.go
+++ b/native/response/data.go
@@ -1,6 +1,6 @@
 package response
 
-import "github.com/bsm/openrtb"
+import "github.com/UnityTech/openrtb"
 
 type Data struct {
 	Label string            `json:"label,omitempty"` // The optional formatted string name of the data type to be displayed
diff --git a/native/response/image.go b/native/response/image.go
index 3e937bc..e1b5585 100644
--- a/native/response/image.go
+++ b/native/response/image.go
@@ -1,6 +1,6 @@
 package response
 
-import "github.com/bsm/openrtb"
+import "github.com/UnityTech/openrtb"
 
 type Image struct {
 	URL    string            `json:"url,omitempty"` // URL of the image asset
diff --git a/native/response/link.go b/native/response/link.go
index 3be381d..37ba3a4 100644
--- a/native/response/link.go
+++ b/native/response/link.go
@@ -1,6 +1,6 @@
 package response
 
-import "github.com/bsm/openrtb"
+import "github.com/UnityTech/openrtb"
 
 type Link struct {
 	URL           string            `json:"url"`                // Landing URL of the clickable link
diff --git a/native/response/response.go b/native/response/response.go
index 120acb0..baaddce 100644
--- a/native/response/response.go
+++ b/native/response/response.go
@@ -1,6 +1,6 @@
 package response
 
-import "github.com/bsm/openrtb"
+import "github.com/UnityTech/openrtb"
 
 // The native object is the top level JSON object which identifies a native response
 type Response struct {
diff --git a/native/response/title.go b/native/response/title.go
index 8fa9af3..e3121f7 100644
--- a/native/response/title.go
+++ b/native/response/title.go
@@ -1,6 +1,6 @@
 package response
 
-import "github.com/bsm/openrtb"
+import "github.com/UnityTech/openrtb"
 
 type Title struct {
 	Text string            `json:"text"` // The text associated with the text element
diff --git a/video.go b/video.go
index 02d551f..296537d 100644
--- a/video.go
+++ b/video.go
@@ -53,10 +53,6 @@ func (v *Video) Validate() error {
 		return ErrInvalidVideoNoMimes
 	} else if v.Linearity == 0 {
 		return ErrInvalidVideoNoLinearity
-	} else if v.MinDuration == 0 {
-		return ErrInvalidVideoNoMinDuration
-	} else if v.MaxDuration == 0 {
-		return ErrInvalidVideoNoMaxDuration
 	} else if v.Protocol == 0 && len(v.Protocols) == 0 {
 		return ErrInvalidVideoNoProtocols
 	}
diff --git a/video_test.go b/video_test.go
index c2e3c9a..56ef3df 100644
--- a/video_test.go
+++ b/video_test.go
@@ -51,15 +51,6 @@ var _ = Describe("Video", func() {
 		Expect((&Video{
 			Mimes: []string{"video/mp4"},
 		}).Validate()).To(Equal(ErrInvalidVideoNoLinearity))
-		Expect((&Video{
-			Linearity: VideoLinearityNonLinear,
-			Mimes:     []string{"video/mp4"},
-		}).Validate()).To(Equal(ErrInvalidVideoNoMinDuration))
-		Expect((&Video{
-			MinDuration: 1,
-			Linearity:   VideoLinearityNonLinear,
-			Mimes:       []string{"video/mp4"},
-		}).Validate()).To(Equal(ErrInvalidVideoNoMaxDuration))
 		Expect((&Video{
 			MinDuration: 1,
 			MaxDuration: 1,

From 8bc583e0bef5ac793c2746c3fca71a53f0c0c657 Mon Sep 17 00:00:00 2001
From: Ryan Hails <ryanhails@unity3d.com>
Date: Tue, 1 May 2018 14:25:06 -0700
Subject: [PATCH 02/54] updated gdpr fields

---
 openrtb.go | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/openrtb.go b/openrtb.go
index 2d3fda5..a7e1136 100644
--- a/openrtb.go
+++ b/openrtb.go
@@ -279,8 +279,8 @@ type Segment struct {
 // coppa flag signals whether or not the request falls under the United States Federal Trade Commission's
 // regulations for the United States Children's Online Privacy Protection Act ("COPPA").
 type Regulations struct {
-	Coppa int       `json:"coppa,omitempty"` // Flag indicating if this request is subject to the COPPA regulations established by the USA FTC, where 0 = no, 1 = yes.
-	Ext   Extension `json:"ext,omitempty"`
+	Coppa int          `json:"coppa,omitempty"` // Flag indicating if this request is subject to the COPPA regulations established by the USA FTC, where 0 = no, 1 = yes.
+	Ext   RegExtension `json:"ext,omitempty"`
 }
 
 // This object represents an allowed size (i.e., height and width combination) for a banner impression.
@@ -290,3 +290,8 @@ type Format struct {
 	H   int       `json:"h,omitempty"` //Height in device independent pixels (DIPS).
 	Ext Extension `json:"ext,omitempty"`
 }
+
+// RegExtension Extension object for Regulations
+type RegExtension struct {
+	GDPR int `json:"gdpr,omitempty"`
+}

From 62306bbe955780f320deb7ba518aa7a1d1c464ad Mon Sep 17 00:00:00 2001
From: Ryan Hails <32077361+hailsryan@users.noreply.github.com>
Date: Tue, 1 May 2018 14:49:53 -0700
Subject: [PATCH 03/54] updated gdpr fields (#2)

---
 openrtb.go | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/openrtb.go b/openrtb.go
index 2d3fda5..a7e1136 100644
--- a/openrtb.go
+++ b/openrtb.go
@@ -279,8 +279,8 @@ type Segment struct {
 // coppa flag signals whether or not the request falls under the United States Federal Trade Commission's
 // regulations for the United States Children's Online Privacy Protection Act ("COPPA").
 type Regulations struct {
-	Coppa int       `json:"coppa,omitempty"` // Flag indicating if this request is subject to the COPPA regulations established by the USA FTC, where 0 = no, 1 = yes.
-	Ext   Extension `json:"ext,omitempty"`
+	Coppa int          `json:"coppa,omitempty"` // Flag indicating if this request is subject to the COPPA regulations established by the USA FTC, where 0 = no, 1 = yes.
+	Ext   RegExtension `json:"ext,omitempty"`
 }
 
 // This object represents an allowed size (i.e., height and width combination) for a banner impression.
@@ -290,3 +290,8 @@ type Format struct {
 	H   int       `json:"h,omitempty"` //Height in device independent pixels (DIPS).
 	Ext Extension `json:"ext,omitempty"`
 }
+
+// RegExtension Extension object for Regulations
+type RegExtension struct {
+	GDPR int `json:"gdpr,omitempty"`
+}

From 667a10ea7b91650b2255da011bef56935ce8b710 Mon Sep 17 00:00:00 2001
From: Hechen Gao <hechen@unity3d.com>
Date: Mon, 14 May 2018 22:36:47 -0700
Subject: [PATCH 04/54] [APIN-632] add Metric to Impression object

---
 impression.go            |  1 +
 impression_test.go       | 12 ++++++++++++
 metric.go                | 12 ++++++++++++
 metric_test.go           | 24 ++++++++++++++++++++++++
 testdata/impression.json | 12 ++++++++++++
 testdata/metric.json     |  5 +++++
 6 files changed, 66 insertions(+)
 create mode 100644 metric.go
 create mode 100644 metric_test.go
 create mode 100644 testdata/metric.json

diff --git a/impression.go b/impression.go
index 3fa096a..b8f5a23 100644
--- a/impression.go
+++ b/impression.go
@@ -17,6 +17,7 @@ var (
 // 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
+	Metric            []*Metric      `json:"metric,omitempty"`
 	Banner            *Banner        `json:"banner,omitempty"`
 	Video             *Video         `json:"video,omitempty"`
 	Audio             *Audio         `json:"audio,omitempty"`
diff --git a/impression_test.go b/impression_test.go
index 93777ff..c7a3b89 100644
--- a/impression_test.go
+++ b/impression_test.go
@@ -16,6 +16,18 @@ var _ = Describe("Impression", func() {
 	It("should parse correctly", func() {
 		Expect(subject).To(Equal(&Impression{
 			ID: "1",
+			Metric: []*Metric{
+				{
+					Type:   "viewable_percentage_1",
+					Value:  0.99,
+					Vendor: "MOAT",
+				},
+				{
+					Type:   "viewable_percentage_2",
+					Value:  0.98,
+					Vendor: "MOAT",
+				},
+			},
 			Banner: &Banner{
 				W: 300,
 				H: 250,
diff --git a/metric.go b/metric.go
new file mode 100644
index 0000000..ae2cb63
--- /dev/null
+++ b/metric.go
@@ -0,0 +1,12 @@
+package openrtb
+
+// Metric object is associated with an impression as an array of metrics. These metrics can offer insight into
+// the impression to assist with decisioning such as average recent viewability, click-through rate, etc. Each
+// metric is identified by its type, reports the value of the metric, and optionally identifies the source or
+// vendor measuring the value.
+type Metric struct {
+	Type   string    `json:"type"`
+	Value  float64   `json:"value"`
+	Vendor string    `json:"vendor"`
+	Ext    Extension `json:"ext,omitempty"`
+}
diff --git a/metric_test.go b/metric_test.go
new file mode 100644
index 0000000..ddee7d8
--- /dev/null
+++ b/metric_test.go
@@ -0,0 +1,24 @@
+package openrtb
+
+import (
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+)
+
+var _ = Describe("Metric", func() {
+	var metric *Metric
+
+	BeforeEach(func() {
+		err := fixture("metric", &metric)
+		Expect(err).NotTo(HaveOccurred())
+	})
+
+	It("should parse correctly", func() {
+		Expect(metric).To(Equal(&Metric{
+			Type:   "viewable_percentage",
+			Value:  0.99,
+			Vendor: "MOAT",
+		}))
+	})
+
+})
diff --git a/testdata/impression.json b/testdata/impression.json
index a66434d..5a1ba0b 100644
--- a/testdata/impression.json
+++ b/testdata/impression.json
@@ -1,5 +1,17 @@
 {
   "id": "1",
+  "metric": [
+    {
+      "type": "viewable_percentage_1",
+      "value": 0.99,
+      "vendor": "MOAT"
+    },
+    {
+      "type": "viewable_percentage_2",
+      "value": 0.98,
+      "vendor": "MOAT"
+    }
+  ],
   "banner": {
     "h": 250,
     "w": 300,
diff --git a/testdata/metric.json b/testdata/metric.json
new file mode 100644
index 0000000..3e09dcd
--- /dev/null
+++ b/testdata/metric.json
@@ -0,0 +1,5 @@
+{
+  "type": "viewable_percentage",
+  "value": 0.99,
+  "vendor": "MOAT"
+}
\ No newline at end of file

From 4b107f1c38851fee91cb668842c8a961e73960e9 Mon Sep 17 00:00:00 2001
From: Ryan Hails <ryanhails@unity3d.com>
Date: Thu, 28 Jun 2018 10:45:14 -0700
Subject: [PATCH 05/54] update bid/imp to hold contentType

---
 bid.go        | 1 +
 impression.go | 1 +
 2 files changed, 2 insertions(+)

diff --git a/bid.go b/bid.go
index 802616b..8b9ab1d 100644
--- a/bid.go
+++ b/bid.go
@@ -42,6 +42,7 @@ type Bid struct {
 	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.
+	ContentType    string         `json:"-"`                        // content of the bid
 	Ext            Extension      `json:"ext,omitempty"`
 }
 
diff --git a/impression.go b/impression.go
index b8f5a23..4b1aa13 100644
--- a/impression.go
+++ b/impression.go
@@ -32,6 +32,7 @@ type Impression struct {
 	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.
+	ContentType       string         `json:"-"`                           // Used to attribute bid to a content - not sent in request
 	Ext               Extension      `json:"ext,omitempty"`
 }
 

From 3b87e53f4d5b932c9d983a2b72d72408ef86b974 Mon Sep 17 00:00:00 2001
From: Ryan Hails <ryanhails@unity3d.com>
Date: Mon, 23 Jul 2018 16:35:55 -0700
Subject: [PATCH 06/54] add media type

---
 bid.go        | 1 +
 impression.go | 1 +
 2 files changed, 2 insertions(+)

diff --git a/bid.go b/bid.go
index 8b9ab1d..5e7521d 100644
--- a/bid.go
+++ b/bid.go
@@ -43,6 +43,7 @@ type Bid struct {
 	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.
 	ContentType    string         `json:"-"`                        // content of the bid
+	MediaType      string         `json:"-"`                        // media of the impression e.g. video/display
 	Ext            Extension      `json:"ext,omitempty"`
 }
 
diff --git a/impression.go b/impression.go
index 4b1aa13..35ea4d2 100644
--- a/impression.go
+++ b/impression.go
@@ -33,6 +33,7 @@ type Impression struct {
 	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.
 	ContentType       string         `json:"-"`                           // Used to attribute bid to a content - not sent in request
+	MediaType         string         `json:"-"`                           // media of the impression e.g. video/display
 	Ext               Extension      `json:"ext,omitempty"`
 }
 

From 9cbc1f92750da908e1800b6f1f572f29e2217119 Mon Sep 17 00:00:00 2001
From: Yishu Yan <yishu@unity3d.com>
Date: Tue, 26 Feb 2019 11:36:54 -0800
Subject: [PATCH 07/54] [APIN-1583] Add consent field in openRTB user extension

---
 openrtb.go | 25 +++++++++++++++----------
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/openrtb.go b/openrtb.go
index a7e1136..91f4584 100644
--- a/openrtb.go
+++ b/openrtb.go
@@ -242,16 +242,16 @@ type Geo struct {
 // privacy policies. However, this user ID must be stable long enough to serve reasonably as the basis for
 // frequency capping and retargeting.
 type User struct {
-	ID         string    `json:"id,omitempty"`         // Unique consumer ID of this user on the exchange
-	BuyerID    string    `json:"buyerid,omitempty"`    // Buyer-specific ID for the user as mapped by the exchange for the buyer. At least one of buyeruid/buyerid or id is recommended. Valid for OpenRTB 2.3.
-	BuyerUID   string    `json:"buyeruid,omitempty"`   // Buyer-specific ID for the user as mapped by the exchange for the buyer. Same as BuyerID but valid for OpenRTB 2.2.
-	YOB        int       `json:"yob,omitempty"`        // Year of birth as a 4-digit integer.
-	Gender     string    `json:"gender,omitempty"`     // Gender ("M": male, "F" female, "O" Other)
-	Keywords   string    `json:"keywords,omitempty"`   // Comma separated list of keywords, interests, or intent
-	CustomData string    `json:"customdata,omitempty"` // Optional feature to pass bidder data that was set in the exchange's cookie. The string must be in base85 cookie safe characters and be in any format. Proper JSON encoding must be used to include "escaped" quotation marks.
-	Geo        *Geo      `json:"geo,omitempty"`
-	Data       []Data    `json:"data,omitempty"`
-	Ext        Extension `json:"ext,omitempty"`
+	ID         string        `json:"id,omitempty"`         // Unique consumer ID of this user on the exchange
+	BuyerID    string        `json:"buyerid,omitempty"`    // Buyer-specific ID for the user as mapped by the exchange for the buyer. At least one of buyeruid/buyerid or id is recommended. Valid for OpenRTB 2.3.
+	BuyerUID   string        `json:"buyeruid,omitempty"`   // Buyer-specific ID for the user as mapped by the exchange for the buyer. Same as BuyerID but valid for OpenRTB 2.2.
+	YOB        int           `json:"yob,omitempty"`        // Year of birth as a 4-digit integer.
+	Gender     string        `json:"gender,omitempty"`     // Gender ("M": male, "F" female, "O" Other)
+	Keywords   string        `json:"keywords,omitempty"`   // Comma separated list of keywords, interests, or intent
+	CustomData string        `json:"customdata,omitempty"` // Optional feature to pass bidder data that was set in the exchange's cookie. The string must be in base85 cookie safe characters and be in any format. Proper JSON encoding must be used to include "escaped" quotation marks.
+	Geo        *Geo          `json:"geo,omitempty"`
+	Data       []Data        `json:"data,omitempty"`
+	Ext        UserExtension `json:"ext,omitempty"`
 }
 
 // The data and segment objects together allow additional data about the user to be specified. This data
@@ -295,3 +295,8 @@ type Format struct {
 type RegExtension struct {
 	GDPR int `json:"gdpr,omitempty"`
 }
+
+// UserExtension Extension object for User
+type UserExtension struct {
+	Consent int `json:"consent,omitempty"`
+}

From 2358a68a6e03fc7548a6cf1447f89c6b798e9020 Mon Sep 17 00:00:00 2001
From: Yishu Yan <yishu@unity3d.com>
Date: Tue, 5 Mar 2019 14:17:06 -0800
Subject: [PATCH 08/54] The consent data type should be string not int

---
 openrtb.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/openrtb.go b/openrtb.go
index 91f4584..6d38ee2 100644
--- a/openrtb.go
+++ b/openrtb.go
@@ -298,5 +298,5 @@ type RegExtension struct {
 
 // UserExtension Extension object for User
 type UserExtension struct {
-	Consent int `json:"consent,omitempty"`
+	Consent string `json:"consent,omitempty"`
 }

From 3ad381836d4c8a6bd1405db7124c8cc3856e2ab3 Mon Sep 17 00:00:00 2001
From: bosong <bosong@unity3d.com>
Date: Thu, 13 Jun 2019 17:17:00 +0800
Subject: [PATCH 09/54] remove omitempty from connectiontype

---
 device.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/device.go b/device.go
index 7f1cc2b..ef02dea 100644
--- a/device.go
+++ b/device.go
@@ -26,7 +26,7 @@ type Device struct {
 	Language   string    `json:"language,omitempty"`       // Browser language
 	Carrier    string    `json:"carrier,omitempty"`        // Carrier or ISP derived from the IP address
 	MCCMNC     string    `json:"mccmnc,omitempty"`         // Mobile carrier as the concatenated MCC-MNC code (e.g., "310-005" identifies Verizon Wireless CDMA in the USA).
-	ConnType   int       `json:"connectiontype,omitempty"` // Network connection type.
+	ConnType   int       `json:"connectiontype"` // Network connection type.
 	IFA        string    `json:"ifa,omitempty"`            // Native identifier for advertisers
 	IDSHA1     string    `json:"didsha1,omitempty"`        // SHA1 hashed device ID
 	IDMD5      string    `json:"didmd5,omitempty"`         // MD5 hashed device ID

From fff1fada82c07d921873b07334d3ee72765efa83 Mon Sep 17 00:00:00 2001
From: bosong <bosong@unity3d.com>
Date: Thu, 13 Jun 2019 17:28:46 +0800
Subject: [PATCH 10/54] go fmt

---
 device.go | 60 +++++++++++++++++++++++++++----------------------------
 1 file changed, 30 insertions(+), 30 deletions(-)

diff --git a/device.go b/device.go
index ef02dea..89db377 100644
--- a/device.go
+++ b/device.go
@@ -4,35 +4,35 @@ package openrtb
 // platform, location, and carrier. This device can refer to a mobile handset, a desktop computer,
 // set top box or other digital device.
 type Device struct {
-	UA         string    `json:"ua,omitempty"`             // User agent
-	Geo        *Geo      `json:"geo,omitempty"`            // Location of the device assumed to be the user’s current location
-	DNT        int       `json:"dnt,omitempty"`            // "1": Do not track
-	LMT        int       `json:"lmt,omitempty"`            // "1": Limit Ad Tracking
-	IP         string    `json:"ip,omitempty"`             // IPv4
-	IPv6       string    `json:"ipv6,omitempty"`           // IPv6
-	DeviceType int       `json:"devicetype,omitempty"`     // The general type of device.
-	Make       string    `json:"make,omitempty"`           // Device make
-	Model      string    `json:"model,omitempty"`          // Device model
-	OS         string    `json:"os,omitempty"`             // Device OS
-	OSVer      string    `json:"osv,omitempty"`            // Device OS version
-	HwVer      string    `json:"hwv,omitempty"`            // Hardware version of the device (e.g., "5S" for iPhone 5S).
-	H          int       `json:"h,omitempty"`              // Physical height of the screen in pixels.
-	W          int       `json:"w,omitempty"`              // Physical width of the screen in pixels.
-	PPI        int       `json:"ppi,omitempty"`            // Screen size as pixels per linear inch.
-	PxRatio    float64   `json:"pxratio,omitempty"`        // The ratio of physical pixels to device independent pixels.
-	JS         int       `json:"js,omitempty"`             // Javascript status ("0": Disabled, "1": Enabled)
-	GeoFetch   int       `json:"geofetch,omitempty"`       // Indicates if the geolocation API will be available to JavaScript code running in the banner,
-	FlashVer   string    `json:"flashver,omitempty"`       // Flash version
-	Language   string    `json:"language,omitempty"`       // Browser language
-	Carrier    string    `json:"carrier,omitempty"`        // Carrier or ISP derived from the IP address
-	MCCMNC     string    `json:"mccmnc,omitempty"`         // Mobile carrier as the concatenated MCC-MNC code (e.g., "310-005" identifies Verizon Wireless CDMA in the USA).
-	ConnType   int       `json:"connectiontype"` // Network connection type.
-	IFA        string    `json:"ifa,omitempty"`            // Native identifier for advertisers
-	IDSHA1     string    `json:"didsha1,omitempty"`        // SHA1 hashed device ID
-	IDMD5      string    `json:"didmd5,omitempty"`         // MD5 hashed device ID
-	PIDSHA1    string    `json:"dpidsha1,omitempty"`       // SHA1 hashed platform device ID
-	PIDMD5     string    `json:"dpidmd5,omitempty"`        // MD5 hashed platform device ID
-	MacSHA1    string    `json:"macsha1,omitempty"`        // SHA1 hashed device ID; IMEI when available, else MEID or ESN
-	MacMD5     string    `json:"macmd5,omitempty"`         // MD5 hashed device ID; IMEI when available, else MEID or ESN
+	UA         string    `json:"ua,omitempty"`         // User agent
+	Geo        *Geo      `json:"geo,omitempty"`        // Location of the device assumed to be the user’s current location
+	DNT        int       `json:"dnt,omitempty"`        // "1": Do not track
+	LMT        int       `json:"lmt,omitempty"`        // "1": Limit Ad Tracking
+	IP         string    `json:"ip,omitempty"`         // IPv4
+	IPv6       string    `json:"ipv6,omitempty"`       // IPv6
+	DeviceType int       `json:"devicetype,omitempty"` // The general type of device.
+	Make       string    `json:"make,omitempty"`       // Device make
+	Model      string    `json:"model,omitempty"`      // Device model
+	OS         string    `json:"os,omitempty"`         // Device OS
+	OSVer      string    `json:"osv,omitempty"`        // Device OS version
+	HwVer      string    `json:"hwv,omitempty"`        // Hardware version of the device (e.g., "5S" for iPhone 5S).
+	H          int       `json:"h,omitempty"`          // Physical height of the screen in pixels.
+	W          int       `json:"w,omitempty"`          // Physical width of the screen in pixels.
+	PPI        int       `json:"ppi,omitempty"`        // Screen size as pixels per linear inch.
+	PxRatio    float64   `json:"pxratio,omitempty"`    // The ratio of physical pixels to device independent pixels.
+	JS         int       `json:"js,omitempty"`         // Javascript status ("0": Disabled, "1": Enabled)
+	GeoFetch   int       `json:"geofetch,omitempty"`   // Indicates if the geolocation API will be available to JavaScript code running in the banner,
+	FlashVer   string    `json:"flashver,omitempty"`   // Flash version
+	Language   string    `json:"language,omitempty"`   // Browser language
+	Carrier    string    `json:"carrier,omitempty"`    // Carrier or ISP derived from the IP address
+	MCCMNC     string    `json:"mccmnc,omitempty"`     // Mobile carrier as the concatenated MCC-MNC code (e.g., "310-005" identifies Verizon Wireless CDMA in the USA).
+	ConnType   int       `json:"connectiontype"`       // Network connection type.
+	IFA        string    `json:"ifa,omitempty"`        // Native identifier for advertisers
+	IDSHA1     string    `json:"didsha1,omitempty"`    // SHA1 hashed device ID
+	IDMD5      string    `json:"didmd5,omitempty"`     // MD5 hashed device ID
+	PIDSHA1    string    `json:"dpidsha1,omitempty"`   // SHA1 hashed platform device ID
+	PIDMD5     string    `json:"dpidmd5,omitempty"`    // MD5 hashed platform device ID
+	MacSHA1    string    `json:"macsha1,omitempty"`    // SHA1 hashed device ID; IMEI when available, else MEID or ESN
+	MacMD5     string    `json:"macmd5,omitempty"`     // MD5 hashed device ID; IMEI when available, else MEID or ESN
 	Ext        Extension `json:"ext,omitempty"`
 }

From 9fbc331ae3e794e64ccd52eb367af07a774a0e17 Mon Sep 17 00:00:00 2001
From: Vu Pham <vu@unity3d.com>
Date: Thu, 15 Aug 2019 19:36:55 -0700
Subject: [PATCH 11/54] [APIN-1859] Add CreativeType to ortb struct + tests for
 Loopme AR

---
 bid.go                      |  1 +
 bid_test.go                 | 38 +++++++++++++++++++++++++++++++++++++
 testdata/bid.loopme.ar.json | 25 ++++++++++++++++++++++++
 3 files changed, 64 insertions(+)
 create mode 100644 testdata/bid.loopme.ar.json

diff --git a/bid.go b/bid.go
index 5e7521d..50a97c7 100644
--- a/bid.go
+++ b/bid.go
@@ -44,6 +44,7 @@ type Bid struct {
 	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.
 	ContentType    string         `json:"-"`                        // content of the bid
 	MediaType      string         `json:"-"`                        // media of the impression e.g. video/display
+	CreativeType   string         `json:"crtype"`                   // CreativeType specifically used by Loopme Mraid AR
 	Ext            Extension      `json:"ext,omitempty"`
 }
 
diff --git a/bid_test.go b/bid_test.go
index 369d2bd..13d639e 100644
--- a/bid_test.go
+++ b/bid_test.go
@@ -37,3 +37,41 @@ var _ = Describe("Bid", func() {
 	})
 
 })
+
+var _ = Describe("Loopme AR Bid", func() {
+	var subject *Bid
+
+	BeforeEach(func() {
+		err := fixture("bid.loopme.ar", &subject)
+		Expect(err).NotTo(HaveOccurred())
+	})
+
+	It("should parse correctly", func() {
+		Expect(subject).To(Equal(&Bid{
+			ID:           "5d4b3b3be8250678c813f475",
+			ImpID:        "1",
+			Price:        29.7,
+			AdID:         "2056515",
+			NURL:         "https://us.tk0x1.com/sj/tr?et=BID_WIN&meta=MjA1NjUxNTo3Mjg0NDQ6NzFhY2I1ZDMtMmVkMi00MzdjLWJjYTItNjRiNDA4OWNkNjc0&ctx=CiQ3MWFjYjVkMy0yZWQyLTQzN2MtYmNhMi02NGI0MDg5Y2Q2NzQSAlJVGPy6LCDDwn0qCQgBEKDLmAEYCjjDwn1AAY8&ip=2.93.212.0&id=5d4b3b3be8250678c813f475&client_id=unity&a_ecp=29.7&a_price=${AUCTION_PRICE:BF}&name=imp_nurl",
+			AdMarkup:     "<img>",
+			AdvDomain:    []string{"unity.com"},
+			IURL:         "https://loopmeedge.net/assets/2013906/23e11b6c-2690-e3c0-aa99-9efd38cd1fa6.jpg",
+			CampaignID:   "2001626",
+			CreativeID:   "2056515",
+			Attr:         []int{99},
+			Protocol:     2,
+			Cat:          []string{"IAB19"},
+			LURL:         "https://us.tk0x1.com/sj/tr?et=BID_LOSS&meta=MjA1NjUxNTo3Mjg0NDQ6NzFhY2I1ZDMtMmVkMi00MzdjLWJjYTItNjRiNDA4OWNkNjc0&ctx=CiQ3MWFjYjVkMy0yZWQyLTQzN2MtYmNhMi02NGI0MDg5Y2Q2NzQSAlJVGPy6LCDDwn0qCQgBEKDLmAEYCjjDwn1AAY8&ip=2.93.212.0&id=5d4b3b3be8250678c813f475&client_id=unity&a_ecp=29.7&a_id=${AUCTION_ID}&a_bid_id=${AUCTION_BID_ID}&a_loss_id=${AUCTION_LOSS}",
+			H:            320,
+			W:            480,
+			CreativeType: "MRAID AR",
+		}))
+	})
+
+	It("should validate", func() {
+		Expect((&Bid{}).Validate()).To(Equal(ErrInvalidBidNoID))
+		Expect((&Bid{ID: "BIDID"}).Validate()).To(Equal(ErrInvalidBidNoImpID))
+		Expect(subject.Validate()).NotTo(HaveOccurred())
+	})
+
+})
diff --git a/testdata/bid.loopme.ar.json b/testdata/bid.loopme.ar.json
new file mode 100644
index 0000000..6b578e2
--- /dev/null
+++ b/testdata/bid.loopme.ar.json
@@ -0,0 +1,25 @@
+{
+  "id": "5d4b3b3be8250678c813f475",
+  "impid": "1",
+  "price": 29.7,
+  "adid": "2056515",
+  "nurl": "https://us.tk0x1.com/sj/tr?et=BID_WIN&meta=MjA1NjUxNTo3Mjg0NDQ6NzFhY2I1ZDMtMmVkMi00MzdjLWJjYTItNjRiNDA4OWNkNjc0&ctx=CiQ3MWFjYjVkMy0yZWQyLTQzN2MtYmNhMi02NGI0MDg5Y2Q2NzQSAlJVGPy6LCDDwn0qCQgBEKDLmAEYCjjDwn1AAY8&ip=2.93.212.0&id=5d4b3b3be8250678c813f475&client_id=unity&a_ecp=29.7&a_price=${AUCTION_PRICE:BF}&name=imp_nurl",
+  "adm": "<img>",
+  "adomain": [
+    "unity.com"
+  ],
+  "iurl": "https://loopmeedge.net/assets/2013906/23e11b6c-2690-e3c0-aa99-9efd38cd1fa6.jpg",
+  "cid": "2001626",
+  "crid": "2056515",
+  "attr": [
+    99
+  ],
+  "protocol": 2,
+  "cat": [
+    "IAB19"
+  ],
+  "lurl": "https://us.tk0x1.com/sj/tr?et=BID_LOSS&meta=MjA1NjUxNTo3Mjg0NDQ6NzFhY2I1ZDMtMmVkMi00MzdjLWJjYTItNjRiNDA4OWNkNjc0&ctx=CiQ3MWFjYjVkMy0yZWQyLTQzN2MtYmNhMi02NGI0MDg5Y2Q2NzQSAlJVGPy6LCDDwn0qCQgBEKDLmAEYCjjDwn1AAY8&ip=2.93.212.0&id=5d4b3b3be8250678c813f475&client_id=unity&a_ecp=29.7&a_id=${AUCTION_ID}&a_bid_id=${AUCTION_BID_ID}&a_loss_id=${AUCTION_LOSS}",
+  "h": 320,
+  "w": 480,
+  "crtype": "MRAID AR"
+}
\ No newline at end of file

From 5ec45f5da7937a9d7b3283b4cc556f91112f62d3 Mon Sep 17 00:00:00 2001
From: Vu Pham <vu@unity3d.com>
Date: Thu, 15 Aug 2019 19:46:17 -0700
Subject: [PATCH 12/54] Update urls

---
 bid_test.go                 | 6 +++---
 testdata/bid.loopme.ar.json | 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/bid_test.go b/bid_test.go
index 13d639e..738c652 100644
--- a/bid_test.go
+++ b/bid_test.go
@@ -52,16 +52,16 @@ var _ = Describe("Loopme AR Bid", func() {
 			ImpID:        "1",
 			Price:        29.7,
 			AdID:         "2056515",
-			NURL:         "https://us.tk0x1.com/sj/tr?et=BID_WIN&meta=MjA1NjUxNTo3Mjg0NDQ6NzFhY2I1ZDMtMmVkMi00MzdjLWJjYTItNjRiNDA4OWNkNjc0&ctx=CiQ3MWFjYjVkMy0yZWQyLTQzN2MtYmNhMi02NGI0MDg5Y2Q2NzQSAlJVGPy6LCDDwn0qCQgBEKDLmAEYCjjDwn1AAY8&ip=2.93.212.0&id=5d4b3b3be8250678c813f475&client_id=unity&a_ecp=29.7&a_price=${AUCTION_PRICE:BF}&name=imp_nurl",
+			NURL:         "https://us.fake-url.com/tr?et=BID_WIN&a_ecp=29.7&a_price=${AUCTION_PRICE:BF}&name=imp_nurl",
 			AdMarkup:     "<img>",
 			AdvDomain:    []string{"unity.com"},
-			IURL:         "https://loopmeedge.net/assets/2013906/23e11b6c-2690-e3c0-aa99-9efd38cd1fa6.jpg",
+			IURL:         "https://fake-url.net/assets/2690-e3c0-aa99-9efd38cd1fa6.jpg",
 			CampaignID:   "2001626",
 			CreativeID:   "2056515",
 			Attr:         []int{99},
 			Protocol:     2,
 			Cat:          []string{"IAB19"},
-			LURL:         "https://us.tk0x1.com/sj/tr?et=BID_LOSS&meta=MjA1NjUxNTo3Mjg0NDQ6NzFhY2I1ZDMtMmVkMi00MzdjLWJjYTItNjRiNDA4OWNkNjc0&ctx=CiQ3MWFjYjVkMy0yZWQyLTQzN2MtYmNhMi02NGI0MDg5Y2Q2NzQSAlJVGPy6LCDDwn0qCQgBEKDLmAEYCjjDwn1AAY8&ip=2.93.212.0&id=5d4b3b3be8250678c813f475&client_id=unity&a_ecp=29.7&a_id=${AUCTION_ID}&a_bid_id=${AUCTION_BID_ID}&a_loss_id=${AUCTION_LOSS}",
+			LURL:         "https://fake-url.com?et=BID_LOSS&meta=&a_id=${AUCTION_ID}&a_bid_id=${AUCTION_BID_ID}&a_loss_id=${AUCTION_LOSS}",
 			H:            320,
 			W:            480,
 			CreativeType: "MRAID AR",
diff --git a/testdata/bid.loopme.ar.json b/testdata/bid.loopme.ar.json
index 6b578e2..aec4012 100644
--- a/testdata/bid.loopme.ar.json
+++ b/testdata/bid.loopme.ar.json
@@ -3,12 +3,12 @@
   "impid": "1",
   "price": 29.7,
   "adid": "2056515",
-  "nurl": "https://us.tk0x1.com/sj/tr?et=BID_WIN&meta=MjA1NjUxNTo3Mjg0NDQ6NzFhY2I1ZDMtMmVkMi00MzdjLWJjYTItNjRiNDA4OWNkNjc0&ctx=CiQ3MWFjYjVkMy0yZWQyLTQzN2MtYmNhMi02NGI0MDg5Y2Q2NzQSAlJVGPy6LCDDwn0qCQgBEKDLmAEYCjjDwn1AAY8&ip=2.93.212.0&id=5d4b3b3be8250678c813f475&client_id=unity&a_ecp=29.7&a_price=${AUCTION_PRICE:BF}&name=imp_nurl",
+  "nurl": "https://us.fake-url.com/tr?et=BID_WIN&a_ecp=29.7&a_price=${AUCTION_PRICE:BF}&name=imp_nurl",
   "adm": "<img>",
   "adomain": [
     "unity.com"
   ],
-  "iurl": "https://loopmeedge.net/assets/2013906/23e11b6c-2690-e3c0-aa99-9efd38cd1fa6.jpg",
+  "iurl": "https://fake-url.net/assets/2690-e3c0-aa99-9efd38cd1fa6.jpg",
   "cid": "2001626",
   "crid": "2056515",
   "attr": [
@@ -18,7 +18,7 @@
   "cat": [
     "IAB19"
   ],
-  "lurl": "https://us.tk0x1.com/sj/tr?et=BID_LOSS&meta=MjA1NjUxNTo3Mjg0NDQ6NzFhY2I1ZDMtMmVkMi00MzdjLWJjYTItNjRiNDA4OWNkNjc0&ctx=CiQ3MWFjYjVkMy0yZWQyLTQzN2MtYmNhMi02NGI0MDg5Y2Q2NzQSAlJVGPy6LCDDwn0qCQgBEKDLmAEYCjjDwn1AAY8&ip=2.93.212.0&id=5d4b3b3be8250678c813f475&client_id=unity&a_ecp=29.7&a_id=${AUCTION_ID}&a_bid_id=${AUCTION_BID_ID}&a_loss_id=${AUCTION_LOSS}",
+  "lurl": "https://fake-url.com?et=BID_LOSS&meta=&a_id=${AUCTION_ID}&a_bid_id=${AUCTION_BID_ID}&a_loss_id=${AUCTION_LOSS}",
   "h": 320,
   "w": 480,
   "crtype": "MRAID AR"

From 9bd7d417f13301248edab4aed587451694ec93e6 Mon Sep 17 00:00:00 2001
From: Vu Pham <vu@unity3d.com>
Date: Mon, 19 Aug 2019 21:34:46 -0700
Subject: [PATCH 13/54] Add more constants to 5.6 API Frameworks

---
 openrtb.go | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/openrtb.go b/openrtb.go
index 6d38ee2..35786b4 100644
--- a/openrtb.go
+++ b/openrtb.go
@@ -56,6 +56,8 @@ const (
 	APIFrameworkMRAID1 = 3
 	APIFrameworkORMMA  = 4
 	APIFrameworkMRAID2 = 5
+	APIFrameworkMRAID3 = 6
+	APIFrameworkOMID1  = 7
 )
 
 // 5.7 Video Linearity

From 4ee8ff008d97ffc8a0531c0ca9c42aa15347ddad Mon Sep 17 00:00:00 2001
From: Vu Pham <vu@unity3d.com>
Date: Mon, 19 Aug 2019 21:41:23 -0700
Subject: [PATCH 14/54] Remove crtype (added to test loopme-ar)

---
 bid.go | 1 -
 1 file changed, 1 deletion(-)

diff --git a/bid.go b/bid.go
index 50a97c7..5e7521d 100644
--- a/bid.go
+++ b/bid.go
@@ -44,7 +44,6 @@ type Bid struct {
 	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.
 	ContentType    string         `json:"-"`                        // content of the bid
 	MediaType      string         `json:"-"`                        // media of the impression e.g. video/display
-	CreativeType   string         `json:"crtype"`                   // CreativeType specifically used by Loopme Mraid AR
 	Ext            Extension      `json:"ext,omitempty"`
 }
 

From 73603a0299b0373b0a7393d8e03f6988f90bd5b5 Mon Sep 17 00:00:00 2001
From: bosong <bosong@unity3d.com>
Date: Thu, 5 Sep 2019 15:02:27 +0800
Subject: [PATCH 15/54] fix empty string decoding issue

---
 numbers.go      | 2 +-
 numbers_test.go | 6 ++++++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/numbers.go b/numbers.go
index f0e45ef..515f6ff 100644
--- a/numbers.go
+++ b/numbers.go
@@ -36,7 +36,7 @@ type StringOrNumber string
 
 // UnmarshalJSON implements json.Unmarshaler
 func (n *StringOrNumber) UnmarshalJSON(data []byte) error {
-	if len(data) > 2 && data[0] == '"' && data[len(data)-1] == '"' {
+	if len(data) >= 2 && data[0] == '"' && data[len(data)-1] == '"' {
 		var v string
 		if err := json.Unmarshal(data, &v); err != nil {
 			return err
diff --git a/numbers_test.go b/numbers_test.go
index d4e1fa6..c3a7c0e 100644
--- a/numbers_test.go
+++ b/numbers_test.go
@@ -51,4 +51,10 @@ var _ = Describe("StringOrNumber", func() {
 		Expect(string(bin)).To(Equal(`"33"`))
 	})
 
+	It("should decode empty strings", func() {
+		var n StringOrNumber
+		Expect(json.Unmarshal([]byte(`""`), &n)).To(Succeed())
+		Expect(n).To(Equal(StringOrNumber("")))
+	})
+
 })

From f4a5673dea45766309bf64b3c668e5130dd2ac91 Mon Sep 17 00:00:00 2001
From: Vu Pham <vu@unity3d.com>
Date: Fri, 6 Sep 2019 16:48:53 -0700
Subject: [PATCH 16/54] Add IsOmEnabled flag to signal om creative from admob
 to sdk

---
 bid.go | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/bid.go b/bid.go
index 5e7521d..a504789 100644
--- a/bid.go
+++ b/bid.go
@@ -42,8 +42,9 @@ type Bid struct {
 	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.
-	ContentType    string         `json:"-"`                        // content of the bid
-	MediaType      string         `json:"-"`                        // media of the impression e.g. video/display
+	ContentType    string         `json:"-"`                        // Content of the bid
+	MediaType      string         `json:"-"`                        // Media of the impression e.g. video/display
+	IsOmEnabled    bool           `json:"-"`                        // Flag to send indicate to the Sdk whether or not to run om scripts
 	Ext            Extension      `json:"ext,omitempty"`
 }
 

From 16731070850c197863309f4150ad3ffad1177a03 Mon Sep 17 00:00:00 2001
From: Vu Pham <vu@unity3d.com>
Date: Fri, 11 Oct 2019 11:17:22 -0700
Subject: [PATCH 17/54] Update custom field to IsOMEnabled

---
 bid.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/bid.go b/bid.go
index a504789..3ce69c2 100644
--- a/bid.go
+++ b/bid.go
@@ -44,7 +44,7 @@ type Bid struct {
 	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.
 	ContentType    string         `json:"-"`                        // Content of the bid
 	MediaType      string         `json:"-"`                        // Media of the impression e.g. video/display
-	IsOmEnabled    bool           `json:"-"`                        // Flag to send indicate to the Sdk whether or not to run om scripts
+	IsOMEnabled    bool           `json:"-"`                        // Flag to send indicate to the Sdk whether or not to run om scripts
 	Ext            Extension      `json:"ext,omitempty"`
 }
 

From 820a4a861a52dff36ade571f39c796a64168da4e Mon Sep 17 00:00:00 2001
From: xuehui-zhu <xuehui.zhu@unity3d.com>
Date: Wed, 20 Nov 2019 14:52:49 -0800
Subject: [PATCH 18/54] [APIN-2109] add app.ext field

---
 bid_test.go  | 33 ++++++++++++++++-----------------
 inventory.go |  9 +++++----
 2 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/bid_test.go b/bid_test.go
index 738c652..efdb610 100644
--- a/bid_test.go
+++ b/bid_test.go
@@ -48,23 +48,22 @@ var _ = Describe("Loopme AR Bid", func() {
 
 	It("should parse correctly", func() {
 		Expect(subject).To(Equal(&Bid{
-			ID:           "5d4b3b3be8250678c813f475",
-			ImpID:        "1",
-			Price:        29.7,
-			AdID:         "2056515",
-			NURL:         "https://us.fake-url.com/tr?et=BID_WIN&a_ecp=29.7&a_price=${AUCTION_PRICE:BF}&name=imp_nurl",
-			AdMarkup:     "<img>",
-			AdvDomain:    []string{"unity.com"},
-			IURL:         "https://fake-url.net/assets/2690-e3c0-aa99-9efd38cd1fa6.jpg",
-			CampaignID:   "2001626",
-			CreativeID:   "2056515",
-			Attr:         []int{99},
-			Protocol:     2,
-			Cat:          []string{"IAB19"},
-			LURL:         "https://fake-url.com?et=BID_LOSS&meta=&a_id=${AUCTION_ID}&a_bid_id=${AUCTION_BID_ID}&a_loss_id=${AUCTION_LOSS}",
-			H:            320,
-			W:            480,
-			CreativeType: "MRAID AR",
+			ID:         "5d4b3b3be8250678c813f475",
+			ImpID:      "1",
+			Price:      29.7,
+			AdID:       "2056515",
+			NURL:       "https://us.fake-url.com/tr?et=BID_WIN&a_ecp=29.7&a_price=${AUCTION_PRICE:BF}&name=imp_nurl",
+			AdMarkup:   "<img>",
+			AdvDomain:  []string{"unity.com"},
+			IURL:       "https://fake-url.net/assets/2690-e3c0-aa99-9efd38cd1fa6.jpg",
+			CampaignID: "2001626",
+			CreativeID: "2056515",
+			Attr:       []int{99},
+			Protocol:   2,
+			Cat:        []string{"IAB19"},
+			LURL:       "https://fake-url.com?et=BID_LOSS&meta=&a_id=${AUCTION_ID}&a_bid_id=${AUCTION_BID_ID}&a_loss_id=${AUCTION_LOSS}",
+			H:          320,
+			W:          480,
 		}))
 	})
 
diff --git a/inventory.go b/inventory.go
index f119287..872b339 100644
--- a/inventory.go
+++ b/inventory.go
@@ -27,10 +27,11 @@ func (a *Inventory) GetPrivacyPolicy() int {
 // "site" object.
 type App struct {
 	Inventory
-	Bundle   string `json:"bundle,omitempty"`   // App bundle or package name
-	StoreURL string `json:"storeurl,omitempty"` // App store URL for an installed app
-	Ver      string `json:"ver,omitempty"`      // App version
-	Paid     int    `json:"paid,omitempty"`     // "1": Paid, "2": Free
+	Bundle   string    `json:"bundle,omitempty"`   // App bundle or package name
+	StoreURL string    `json:"storeurl,omitempty"` // App store URL for an installed app
+	Ver      string    `json:"ver,omitempty"`      // App version
+	Paid     int       `json:"paid,omitempty"`     // "1": Paid, "2": Free
+	Ext      Extension `json:"ext,omitempty"`      // Placeholder for exchange-specific extensions to OpenRTB
 }
 
 // A site object should be included if the ad supported content is part of a website (as opposed to

From 0c92d4eb8f6ec98b92429e28346cd0b61279920d Mon Sep 17 00:00:00 2001
From: xuehui-zhu <xuehui.zhu@unity3d.com>
Date: Mon, 2 Dec 2019 15:38:44 -0800
Subject: [PATCH 19/54] [APIN-2184] add field for CCPA

---
 openrtb.go | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/openrtb.go b/openrtb.go
index 35786b4..adfe34d 100644
--- a/openrtb.go
+++ b/openrtb.go
@@ -295,7 +295,8 @@ type Format struct {
 
 // RegExtension Extension object for Regulations
 type RegExtension struct {
-	GDPR int `json:"gdpr,omitempty"`
+	GDPR      int    `json:"gdpr,omitempty"`
+	USPrivacy string `json:"us_privacy,omitempty"`
 }
 
 // UserExtension Extension object for User

From 5fb8c657dbcb3f26cb060f121a952b4e873b4b56 Mon Sep 17 00:00:00 2001
From: Andrey Mishenkin <andrey.mishenkin@unity3d.com>
Date: Tue, 11 May 2021 14:29:17 -0700
Subject: [PATCH 20/54] APIN-3028 Add network 5G and map it to the
 connectionType in the bid request - added new Connection Type = 7

---
 openrtb.go | 1 +
 1 file changed, 1 insertion(+)

diff --git a/openrtb.go b/openrtb.go
index adfe34d..607ca08 100644
--- a/openrtb.go
+++ b/openrtb.go
@@ -172,6 +172,7 @@ const (
 	ConnTypeCell2G   = 4
 	ConnTypeCell3G   = 5
 	ConnTypeCell4G   = 6
+	ConnTypeCell5G   = 7
 )
 
 // 5.19 No-Bid Reason Codes

From c6d46b5acae3b37d74879421b7b8b99ac15221aa Mon Sep 17 00:00:00 2001
From: Satinder Singh <satinder@unity3d.com>
Date: Wed, 9 Jun 2021 09:41:32 -0700
Subject: [PATCH 21/54] Add sdk data

---
 openrtb.go | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/openrtb.go b/openrtb.go
index 607ca08..a5de1d1 100644
--- a/openrtb.go
+++ b/openrtb.go
@@ -302,5 +302,13 @@ type RegExtension struct {
 
 // UserExtension Extension object for User
 type UserExtension struct {
-	Consent string `json:"consent,omitempty"`
+	Consent string  `json:"consent,omitempty"`
+	SdkData SdkData `json:"sdkdata,omitempty"`
+}
+
+// SdkData object for UserExtension. Required for direct demand header bidding integration
+type SdkData struct {
+	Seq    int32 `json:"seq,omitempty"`    // Number of times Header Bidding same prevaluation token has been requested by Mediation SDK
+	Loads  int32 `json:"loads,omitempty"`  // Number of times same prevaluation token has been used to load AdM
+	Starts int32 `json:"starts,omitempty"` // Number of times starts has been registered for the same prevaluation token
 }

From 8532334da1d3a88f308a1f8c864bcd0674854afa Mon Sep 17 00:00:00 2001
From: Rourke White <rourke.white@unity3d.com>
Date: Thu, 1 Jul 2021 11:10:06 -0500
Subject: [PATCH 22/54] [APIN-3345] adds field `lgpd` to the regulation
 extension

---
 openrtb.go | 1 +
 1 file changed, 1 insertion(+)

diff --git a/openrtb.go b/openrtb.go
index a5de1d1..a3dc76f 100644
--- a/openrtb.go
+++ b/openrtb.go
@@ -297,6 +297,7 @@ type Format struct {
 // RegExtension Extension object for Regulations
 type RegExtension struct {
 	GDPR      int    `json:"gdpr,omitempty"`
+	LGPD      bool   `json:"lgpd,omitempty"`
 	USPrivacy string `json:"us_privacy,omitempty"`
 }
 

From 74ee72035747274206616733390f8efe2137965e Mon Sep 17 00:00:00 2001
From: Satinder Singh <satinder@unity3d.com>
Date: Wed, 14 Jul 2021 09:04:10 -0700
Subject: [PATCH 23/54] Remove OmitEmpty from SDKData

---
 openrtb.go | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/openrtb.go b/openrtb.go
index a3dc76f..6d14661 100644
--- a/openrtb.go
+++ b/openrtb.go
@@ -309,7 +309,7 @@ type UserExtension struct {
 
 // SdkData object for UserExtension. Required for direct demand header bidding integration
 type SdkData struct {
-	Seq    int32 `json:"seq,omitempty"`    // Number of times Header Bidding same prevaluation token has been requested by Mediation SDK
-	Loads  int32 `json:"loads,omitempty"`  // Number of times same prevaluation token has been used to load AdM
-	Starts int32 `json:"starts,omitempty"` // Number of times starts has been registered for the same prevaluation token
+	Seq    int32 `json:"seq"`    // Number of times Header Bidding same prevaluation token has been requested by Mediation SDK
+	Loads  int32 `json:"loads"`  // Number of times same prevaluation token has been used to load AdM
+	Starts int32 `json:"starts"` // Number of times starts has been registered for the same prevaluation token
 }

From 255e2145ca0eb6929cbfc4ead938675081eb88d8 Mon Sep 17 00:00:00 2001
From: Jake Uskoski <jake.uskoski@unity.com>
Date: Thu, 4 Nov 2021 15:34:03 -0400
Subject: [PATCH 24/54] PIPL: Add PIPL regulation to extensions for legal
 context

---
 openrtb.go | 1 +
 1 file changed, 1 insertion(+)

diff --git a/openrtb.go b/openrtb.go
index 6d14661..15c4f23 100644
--- a/openrtb.go
+++ b/openrtb.go
@@ -298,6 +298,7 @@ type Format struct {
 type RegExtension struct {
 	GDPR      int    `json:"gdpr,omitempty"`
 	LGPD      bool   `json:"lgpd,omitempty"`
+	PIPL      bool   `json:"pipl,omitempty"`
 	USPrivacy string `json:"us_privacy,omitempty"`
 }
 

From 88511fd7df53a566da01523e480f4218ea45b541 Mon Sep 17 00:00:00 2001
From: Patrik Marjanen <patrik@unity3d.com>
Date: Fri, 20 May 2022 13:46:53 +0300
Subject: [PATCH 25/54] Add AppStartTime to UserExtension struct.

---
 openrtb.go | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/openrtb.go b/openrtb.go
index 15c4f23..ec9915b 100644
--- a/openrtb.go
+++ b/openrtb.go
@@ -304,8 +304,9 @@ type RegExtension struct {
 
 // UserExtension Extension object for User
 type UserExtension struct {
-	Consent string  `json:"consent,omitempty"`
-	SdkData SdkData `json:"sdkdata,omitempty"`
+	Consent      string  `json:"consent,omitempty"`
+	SdkData      SdkData `json:"sdkdata,omitempty"`
+	AppStartTime int     `json:"appStartTime,omitempty"`
 }
 
 // SdkData object for UserExtension. Required for direct demand header bidding integration

From 57653eab03ea2acc0153dd3550fc9ea6d0d4a827 Mon Sep 17 00:00:00 2001
From: Patrik Marjanen <patrik@unity3d.com>
Date: Fri, 20 May 2022 14:43:09 +0300
Subject: [PATCH 26/54] Change AppStartTime to be of type int64

---
 openrtb.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/openrtb.go b/openrtb.go
index ec9915b..48de831 100644
--- a/openrtb.go
+++ b/openrtb.go
@@ -306,7 +306,7 @@ type RegExtension struct {
 type UserExtension struct {
 	Consent      string  `json:"consent,omitempty"`
 	SdkData      SdkData `json:"sdkdata,omitempty"`
-	AppStartTime int     `json:"appStartTime,omitempty"`
+	AppStartTime int64   `json:"appStartTime,omitempty"`
 }
 
 // SdkData object for UserExtension. Required for direct demand header bidding integration

From 930a00cde7aa724370fdd03c6e691e1dd2dda37d Mon Sep 17 00:00:00 2001
From: Zephan Johnson <zephan.johnson@unity3d.com>
Date: Mon, 23 May 2022 14:01:29 -0600
Subject: [PATCH 27/54] banner vcm field to allow using banners as endcards

---
 banner.go | 1 +
 1 file changed, 1 insertion(+)

diff --git a/banner.go b/banner.go
index e4b2a03..4b34d49 100644
--- a/banner.go
+++ b/banner.go
@@ -22,5 +22,6 @@ type Banner struct {
 	TopFrame int       `json:"topframe,omitempty"` // Default: 0 ("1": Delivered in top frame, "0": Elsewhere)
 	ExpDir   []int     `json:"expdir,omitempty"`   // Specify properties for an expandable ad
 	Api      []int     `json:"api,omitempty"`      // List of supported API frameworks
+	VCM      int       `json:"vcm,omitempty"`      // Represents the relationship with video. 0 = concurrent, 1 = end-card
 	Ext      Extension `json:"ext,omitempty"`
 }

From 4f4f7ca319397f4ee6d9e7eea217836fdc60fa2b Mon Sep 17 00:00:00 2001
From: Zephan Johnson <zephan.johnson@unity3d.com>
Date: Tue, 21 Jun 2022 15:19:09 -0600
Subject: [PATCH 28/54] Add OAID device field to openrtb

---
 device.go      | 1 +
 device_test.go | 1 +
 2 files changed, 2 insertions(+)

diff --git a/device.go b/device.go
index 89db377..a2b231a 100644
--- a/device.go
+++ b/device.go
@@ -34,5 +34,6 @@ type Device struct {
 	PIDMD5     string    `json:"dpidmd5,omitempty"`    // MD5 hashed platform device ID
 	MacSHA1    string    `json:"macsha1,omitempty"`    // SHA1 hashed device ID; IMEI when available, else MEID or ESN
 	MacMD5     string    `json:"macmd5,omitempty"`     // MD5 hashed device ID; IMEI when available, else MEID or ESN
+	OAID       string    `json:"OAID,omitempty"`       // Open Advertising Tracking ID
 	Ext        Extension `json:"ext,omitempty"`
 }
diff --git a/device_test.go b/device_test.go
index c713c3f..a43d8ec 100644
--- a/device_test.go
+++ b/device_test.go
@@ -39,6 +39,7 @@ var _ = Describe("Device", func() {
 			ConnType:   ConnTypeCell,
 			MCCMNC:     "722-341",
 			DeviceType: DeviceTypeMobile,
+			OAID:       "1fe9a970-efbb-29e0-0bdd-f5dbbf751ab5",
 		}))
 	})
 })

From 7973f1febcd24ca166cf9823e9a1ee01001c4d3c Mon Sep 17 00:00:00 2001
From: Zephan Johnson <zephan.johnson@unity3d.com>
Date: Tue, 21 Jun 2022 15:34:40 -0600
Subject: [PATCH 29/54] Update oaid field name to be lowercase

---
 device.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/device.go b/device.go
index a2b231a..460e4d6 100644
--- a/device.go
+++ b/device.go
@@ -34,6 +34,6 @@ type Device struct {
 	PIDMD5     string    `json:"dpidmd5,omitempty"`    // MD5 hashed platform device ID
 	MacSHA1    string    `json:"macsha1,omitempty"`    // SHA1 hashed device ID; IMEI when available, else MEID or ESN
 	MacMD5     string    `json:"macmd5,omitempty"`     // MD5 hashed device ID; IMEI when available, else MEID or ESN
-	OAID       string    `json:"OAID,omitempty"`       // Open Advertising Tracking ID
+	OAID       string    `json:"oaid,omitempty"`       // Open Advertising Tracking ID
 	Ext        Extension `json:"ext,omitempty"`
 }

From 6e29e895adf247a2b924592a7ad77422b5d86cba Mon Sep 17 00:00:00 2001
From: damirt <newdeadsoul@gmail.com>
Date: Tue, 19 Jul 2022 19:57:22 +0300
Subject: [PATCH 30/54] Add user.ext.sessionId

---
 openrtb.go | 1 +
 1 file changed, 1 insertion(+)

diff --git a/openrtb.go b/openrtb.go
index 48de831..9ffb52b 100644
--- a/openrtb.go
+++ b/openrtb.go
@@ -307,6 +307,7 @@ type UserExtension struct {
 	Consent      string  `json:"consent,omitempty"`
 	SdkData      SdkData `json:"sdkdata,omitempty"`
 	AppStartTime int64   `json:"appStartTime,omitempty"`
+	SessionID    string  `json:"sessionId,omitempty"`
 }
 
 // SdkData object for UserExtension. Required for direct demand header bidding integration

From 4b8e1a35196e93270627b11c77cc4d61258c7fba Mon Sep 17 00:00:00 2001
From: CarolynU <carolyn.chen@unity3d.com>
Date: Wed, 31 May 2023 15:41:19 -0700
Subject: [PATCH 31/54] update

---
 impression.go      | 1 +
 impression_test.go | 6 +-----
 2 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/impression.go b/impression.go
index 35ea4d2..d13930f 100644
--- a/impression.go
+++ b/impression.go
@@ -35,6 +35,7 @@ type Impression struct {
 	ContentType       string         `json:"-"`                           // Used to attribute bid to a content - not sent in request
 	MediaType         string         `json:"-"`                           // media of the impression e.g. video/display
 	Ext               Extension      `json:"ext,omitempty"`
+	Rewarded          bool           `json:"rwdd,omitempty"` //Indicates whether the user receives a reward for viewing the ad
 }
 
 func (imp *Impression) assetCount() int {
diff --git a/impression_test.go b/impression_test.go
index c7a3b89..ce6b620 100644
--- a/impression_test.go
+++ b/impression_test.go
@@ -1,10 +1,5 @@
 package openrtb
 
-import (
-	. "github.com/onsi/ginkgo"
-	. "github.com/onsi/gomega"
-)
-
 var _ = Describe("Impression", func() {
 	var subject *Impression
 
@@ -43,6 +38,7 @@ var _ = Describe("Impression", func() {
 					},
 				},
 			},
+			Rewarded: false,
 		}))
 	})
 

From 236ba553a65df6b1eabae9dc310b6512c6064871 Mon Sep 17 00:00:00 2001
From: CarolynU <carolyn.chen@unity3d.com>
Date: Wed, 31 May 2023 16:13:26 -0700
Subject: [PATCH 32/54] Update impression_test.go

---
 impression_test.go | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/impression_test.go b/impression_test.go
index ce6b620..8d21ff0 100644
--- a/impression_test.go
+++ b/impression_test.go
@@ -1,5 +1,10 @@
 package openrtb
 
+import (
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+)
+
 var _ = Describe("Impression", func() {
 	var subject *Impression
 

From 42f367357fee653590fec4f6a460d2dbdd1c3877 Mon Sep 17 00:00:00 2001
From: CarolynU <carolyn.chen@unity3d.com>
Date: Fri, 2 Jun 2023 17:35:11 -0700
Subject: [PATCH 33/54] update

---
 impression.go      | 2 +-
 impression_test.go | 7 +------
 2 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/impression.go b/impression.go
index d13930f..ba706ab 100644
--- a/impression.go
+++ b/impression.go
@@ -35,7 +35,7 @@ type Impression struct {
 	ContentType       string         `json:"-"`                           // Used to attribute bid to a content - not sent in request
 	MediaType         string         `json:"-"`                           // media of the impression e.g. video/display
 	Ext               Extension      `json:"ext,omitempty"`
-	Rewarded          bool           `json:"rwdd,omitempty"` //Indicates whether the user receives a reward for viewing the ad
+	Rewarded          int            `json:"rwdd,omitempty"` //Indicates whether the user receives a reward for viewing the ad
 }
 
 func (imp *Impression) assetCount() int {
diff --git a/impression_test.go b/impression_test.go
index 8d21ff0..af45a1e 100644
--- a/impression_test.go
+++ b/impression_test.go
@@ -1,10 +1,5 @@
 package openrtb
 
-import (
-	. "github.com/onsi/ginkgo"
-	. "github.com/onsi/gomega"
-)
-
 var _ = Describe("Impression", func() {
 	var subject *Impression
 
@@ -43,7 +38,7 @@ var _ = Describe("Impression", func() {
 					},
 				},
 			},
-			Rewarded: false,
+			Rewarded: 0,
 		}))
 	})
 

From 6b334125868e1d889c6254739cf6d4d9fd11672d Mon Sep 17 00:00:00 2001
From: CarolynU <carolyn.chen@unity3d.com>
Date: Fri, 2 Jun 2023 17:40:22 -0700
Subject: [PATCH 34/54] Update impression_test.go

---
 impression_test.go | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/impression_test.go b/impression_test.go
index af45a1e..e7a104f 100644
--- a/impression_test.go
+++ b/impression_test.go
@@ -1,5 +1,10 @@
 package openrtb
 
+import (
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+)
+
 var _ = Describe("Impression", func() {
 	var subject *Impression
 

From 042ac9bce6517dd2a80b04185a1ba95c3606d1ba Mon Sep 17 00:00:00 2001
From: CarolynU <carolyn.chen@unity3d.com>
Date: Thu, 15 Jun 2023 14:48:34 -0700
Subject: [PATCH 35/54] Update impression.go

---
 impression.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/impression.go b/impression.go
index ba706ab..50aea68 100644
--- a/impression.go
+++ b/impression.go
@@ -35,7 +35,7 @@ type Impression struct {
 	ContentType       string         `json:"-"`                           // Used to attribute bid to a content - not sent in request
 	MediaType         string         `json:"-"`                           // media of the impression e.g. video/display
 	Ext               Extension      `json:"ext,omitempty"`
-	Rewarded          int            `json:"rwdd,omitempty"` //Indicates whether the user receives a reward for viewing the ad
+	Rewarded          int            `json:"rwdd"` //Indicates whether the user receives a reward for viewing the ad
 }
 
 func (imp *Impression) assetCount() int {

From 5e3bbac8c70c7439a5e78a57e0ef881c7d29433d Mon Sep 17 00:00:00 2001
From: CarolynU <carolyn.chen@unity3d.com>
Date: Thu, 10 Aug 2023 15:17:37 -0700
Subject: [PATCH 36/54] Update source.go

---
 source.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source.go b/source.go
index e187215..7ea8f66 100644
--- a/source.go
+++ b/source.go
@@ -2,7 +2,7 @@ package openrtb
 
 // Source object describes the nature and behavior of the entity that is the source of the bid request upstream from the exchange.
 type Source struct {
-	FinalSaleDecision int       `json:"fd,omitempty"`     // Entity responsible for the final impression sale decision, where 0 = exchange, 1 = upstream source.
+	FinalSaleDecision *int      `json:"fd,omitempty"`     // Entity responsible for the final impression sale decision, where 0 = exchange, 1 = upstream source.
 	TransactionID     string    `json:"tid,omitempty"`    // Transaction ID that must be common across all participants in this bid request (e.g., potentially multiple exchanges).
 	PaymentChain      string    `json:"pchain,omitempty"` // Payment ID chain string containing embedded syntax described in the TAG Payment ID Protocol v1.0.
 	Ext               Extension `json:"ext,omitempty"`    // Placeholder for exchange-specific extensions to OpenRTB.

From 406dad2d3aff6a653e48898933a4a25e93a2d5f1 Mon Sep 17 00:00:00 2001
From: CarolynU <carolyn.chen@unity3d.com>
Date: Mon, 23 Oct 2023 10:47:10 -0700
Subject: [PATCH 37/54] Update source.go

---
 source.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source.go b/source.go
index 7ea8f66..615ceb8 100644
--- a/source.go
+++ b/source.go
@@ -2,7 +2,7 @@ package openrtb
 
 // Source object describes the nature and behavior of the entity that is the source of the bid request upstream from the exchange.
 type Source struct {
-	FinalSaleDecision *int      `json:"fd,omitempty"`     // Entity responsible for the final impression sale decision, where 0 = exchange, 1 = upstream source.
+	FinalSaleDecision int       `json:"fd"`               // Entity responsible for the final impression sale decision, where 0 = exchange, 1 = upstream source.
 	TransactionID     string    `json:"tid,omitempty"`    // Transaction ID that must be common across all participants in this bid request (e.g., potentially multiple exchanges).
 	PaymentChain      string    `json:"pchain,omitempty"` // Payment ID chain string containing embedded syntax described in the TAG Payment ID Protocol v1.0.
 	Ext               Extension `json:"ext,omitempty"`    // Placeholder for exchange-specific extensions to OpenRTB.

From 8288bbc25f6a5180949d519e5cd6a50f88c53e7c Mon Sep 17 00:00:00 2001
From: Rourke White <rourke.white@unity3d.com>
Date: Mon, 25 Mar 2024 16:52:30 -0500
Subject: [PATCH 38/54] fix go mod

---
 go.mod | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/go.mod b/go.mod
index 5d8e195..305b62c 100644
--- a/go.mod
+++ b/go.mod
@@ -1,3 +1,3 @@
-module github.com/bsm/openrtb/v3
+module github.com/UnityTech/openrtb
 
 go 1.13

From 54bcae90b81c0f654f4ab58433efc04db896a5ba Mon Sep 17 00:00:00 2001
From: Rourke White <rourke.white@unity3d.com>
Date: Mon, 25 Mar 2024 16:57:28 -0500
Subject: [PATCH 39/54] fix seatbid test

---
 seatbid_test.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/seatbid_test.go b/seatbid_test.go
index 9f73349..f768c1c 100644
--- a/seatbid_test.go
+++ b/seatbid_test.go
@@ -4,7 +4,7 @@ import (
 	"errors"
 	"testing"
 
-	. "github.com/bsm/openrtb/v3"
+	. "github.com/UnityTech/openrtb"
 )
 
 func TestSeatBid_Validate(t *testing.T) {

From 0d1b208a772b6b353a9001d0e03f887746d765f0 Mon Sep 17 00:00:00 2001
From: Rourke White <rourke.white@unity3d.com>
Date: Mon, 25 Mar 2024 17:36:15 -0500
Subject: [PATCH 40/54] fix quantity test

---
 quantity_test.go | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/quantity_test.go b/quantity_test.go
index 0ec9b10..d22bc4f 100644
--- a/quantity_test.go
+++ b/quantity_test.go
@@ -3,6 +3,8 @@ package openrtb_test
 import (
 	"reflect"
 	"testing"
+
+	. "github.com/UnityTech/openrtb"
 )
 
 func TestQuantity(t *testing.T) {

From f9fae6e92bb36e35cd30022f5e38651e2fc959eb Mon Sep 17 00:00:00 2001
From: Rourke White <rourke.white@unity3d.com>
Date: Mon, 25 Mar 2024 19:48:31 -0500
Subject: [PATCH 41/54] fix extension marshaling and tests

---
 extension.go                 | 23 +++++++++++++++++++++
 extension_test.go            | 39 ++++++++++++++++++++++++++++++++++++
 openrtb.go                   |  4 ----
 testdata/content.quoted.json |  2 +-
 testdata/device.json         |  3 ++-
 testdata/impression.json     |  3 ++-
 6 files changed, 67 insertions(+), 7 deletions(-)
 create mode 100644 extension.go
 create mode 100644 extension_test.go

diff --git a/extension.go b/extension.go
new file mode 100644
index 0000000..4398ecb
--- /dev/null
+++ b/extension.go
@@ -0,0 +1,23 @@
+package openrtb
+
+import (
+	"encoding/json"
+	"errors"
+)
+
+// Extension is a raw encoded JSON value.
+// It implements Marshaler and Unmarshaler, defined in encoding/json package
+type Extension json.RawMessage
+
+// MarshalJSON returns e as the JSON encoding of e.
+func (e Extension) MarshalJSON() ([]byte, error) {
+	return json.RawMessage(e).MarshalJSON()
+}
+
+// UnmarshalJSON sets *e to a copy of data.
+func (e *Extension) UnmarshalJSON(data []byte) error {
+	if e == nil {
+		return errors.New("openrtb.Extension: UnmarshalJSON on nil pointer")
+	}
+	return (*json.RawMessage)(e).UnmarshalJSON(data)
+}
diff --git a/extension_test.go b/extension_test.go
new file mode 100644
index 0000000..2c4b407
--- /dev/null
+++ b/extension_test.go
@@ -0,0 +1,39 @@
+package openrtb_test
+
+import (
+	"encoding/json"
+	"reflect"
+	"testing"
+
+	. "github.com/UnityTech/openrtb"
+)
+
+func TestExtension(t *testing.T) {
+	var _ json.Marshaler = (Extension)(nil)
+	var _ json.Unmarshaler = (*Extension)(nil)
+
+	t.Run("should marshal JSON", func(t *testing.T) {
+		subject := Extension(`{"foo":"bar"}`)
+
+		got, err := json.Marshal(subject)
+		if err != nil {
+			t.Fatal(err.Error())
+		}
+		exp := []byte(`{"foo":"bar"}`)
+		if !reflect.DeepEqual(exp, got) {
+			t.Errorf("expected %+v, got %+v", exp, got)
+		}
+	})
+
+	t.Run("should unmarshal JSON", func(t *testing.T) {
+		subject := Extension([]byte{})
+		err := json.Unmarshal([]byte(`{"foo":"bar"}`), &subject)
+		if err != nil {
+			t.Fatal(err.Error())
+		}
+		exp := Extension(`{"foo":"bar"}`)
+		if got := subject; !reflect.DeepEqual(exp, got) {
+			t.Errorf("expected %+v, got %+v", exp, got)
+		}
+	})
+}
diff --git a/openrtb.go b/openrtb.go
index 8967e41..b529185 100644
--- a/openrtb.go
+++ b/openrtb.go
@@ -1,7 +1,5 @@
 package openrtb
 
-import "encoding/json"
-
 // ContentCategory as defined in section 5.1
 type ContentCategory string
 
@@ -841,8 +839,6 @@ type ChannelEntity struct {
 	Ext    Extension `json:"ext,omitempty"`
 }
 
-type Extension json.RawMessage
-
 // RegExtension Extension object for Regulations
 type RegExtension struct {
 	GDPR      int    `json:"gdpr,omitempty"`
diff --git a/testdata/content.quoted.json b/testdata/content.quoted.json
index 67733eb..e88e1d8 100644
--- a/testdata/content.quoted.json
+++ b/testdata/content.quoted.json
@@ -9,7 +9,7 @@
   "len": 129,
   "series": "book reading",
   "videoquality": 2,
-  "context": "1",
+  "context": 1,
   "season": "1",
   "sourcerelationship": 0,
   "id": "eb9f13ede5fd225333971523f6042f9d"
diff --git a/testdata/device.json b/testdata/device.json
index 98b7e55..bcba212 100644
--- a/testdata/device.json
+++ b/testdata/device.json
@@ -22,5 +22,6 @@
   "js": 1,
   "connectiontype": 3,
   "mccmnc": "722-341",
-  "devicetype": 1
+  "devicetype": 1,
+  "oaid": "1fe9a970-efbb-29e0-0bdd-f5dbbf751ab5"
 }
diff --git a/testdata/impression.json b/testdata/impression.json
index 02535f3..b0db1e8 100644
--- a/testdata/impression.json
+++ b/testdata/impression.json
@@ -30,5 +30,6 @@
   },
   "qty": {
     "multiplier": 1.0
-  }
+  },
+  "rwdd": 1
 }

From f4bcdb81c29ceedb415790f7470da1ad3dab06a6 Mon Sep 17 00:00:00 2001
From: rourkewhite <62619147+rourkewhite@users.noreply.github.com>
Date: Tue, 26 Mar 2024 11:29:47 -0700
Subject: [PATCH 42/54] update go module to v3, to match version tag (#36)

---
 README.md                        | 6 ++++--
 audio_test.go                    | 2 +-
 banner_test.go                   | 2 +-
 bid_test.go                      | 2 +-
 bidrequest_test.go               | 2 +-
 bidresponse_test.go              | 2 +-
 content_test.go                  | 2 +-
 device_test.go                   | 2 +-
 extension_test.go                | 2 +-
 go.mod                           | 4 ++--
 impression_test.go               | 2 +-
 inventory_test.go                | 2 +-
 metric_test.go                   | 2 +-
 native/request/asset.go          | 2 +-
 native/request/data.go           | 2 +-
 native/request/image.go          | 2 +-
 native/request/request.go        | 2 +-
 native/request/request_test.go   | 4 ++--
 native/request/title.go          | 2 +-
 native/request/video.go          | 2 +-
 native/response/asset.go         | 2 +-
 native/response/data.go          | 2 +-
 native/response/image.go         | 2 +-
 native/response/link.go          | 2 +-
 native/response/response.go      | 2 +-
 native/response/response_test.go | 2 +-
 native/response/title.go         | 2 +-
 native_test.go                   | 2 +-
 numbers_test.go                  | 2 +-
 pmp_test.go                      | 2 +-
 quantity_test.go                 | 2 +-
 seatbid_test.go                  | 2 +-
 source_test.go                   | 2 +-
 video_test.go                    | 2 +-
 34 files changed, 39 insertions(+), 37 deletions(-)

diff --git a/README.md b/README.md
index 12f487b..2485a67 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@ Requires Go 1.8+ for proper `json.RawMessage` marshaling.
 To install, use `go get`:
 
 ```shell
-go get github.com/UnityTech/openrtb
+go get github.com/UnityTech/openrtb/v3
 ```
 
 ## Usage
@@ -22,9 +22,11 @@ go get github.com/UnityTech/openrtb
 package main
 
 import (
+  "encoding/json"
   "log"
+  "os"
 
-  "github.com/UnityTech/openrtb"
+  "github.com/UnityTech/openrtb/v3"
 )
 
 func main() {
diff --git a/audio_test.go b/audio_test.go
index 6cd95bd..d6ccf58 100644
--- a/audio_test.go
+++ b/audio_test.go
@@ -5,7 +5,7 @@ import (
 	"reflect"
 	"testing"
 
-	. "github.com/UnityTech/openrtb"
+	. "github.com/UnityTech/openrtb/v3"
 )
 
 func TestAudio(t *testing.T) {
diff --git a/banner_test.go b/banner_test.go
index 8ed96f9..72b5c93 100644
--- a/banner_test.go
+++ b/banner_test.go
@@ -4,7 +4,7 @@ import (
 	"reflect"
 	"testing"
 
-	. "github.com/UnityTech/openrtb"
+	. "github.com/UnityTech/openrtb/v3"
 )
 
 func TestBanner(t *testing.T) {
diff --git a/bid_test.go b/bid_test.go
index 46b4492..9836be8 100644
--- a/bid_test.go
+++ b/bid_test.go
@@ -5,7 +5,7 @@ import (
 	"reflect"
 	"testing"
 
-	. "github.com/UnityTech/openrtb"
+	. "github.com/UnityTech/openrtb/v3"
 )
 
 func TestBid(t *testing.T) {
diff --git a/bidrequest_test.go b/bidrequest_test.go
index b2630ba..bbb9023 100644
--- a/bidrequest_test.go
+++ b/bidrequest_test.go
@@ -5,7 +5,7 @@ import (
 	"reflect"
 	"testing"
 
-	. "github.com/UnityTech/openrtb"
+	. "github.com/UnityTech/openrtb/v3"
 )
 
 func TestBidRequest(t *testing.T) {
diff --git a/bidresponse_test.go b/bidresponse_test.go
index d858f57..21b86dc 100644
--- a/bidresponse_test.go
+++ b/bidresponse_test.go
@@ -5,7 +5,7 @@ import (
 	"reflect"
 	"testing"
 
-	. "github.com/UnityTech/openrtb"
+	. "github.com/UnityTech/openrtb/v3"
 )
 
 func TestBidResponse(t *testing.T) {
diff --git a/content_test.go b/content_test.go
index d02e9f8..289ca62 100644
--- a/content_test.go
+++ b/content_test.go
@@ -4,7 +4,7 @@ import (
 	"reflect"
 	"testing"
 
-	. "github.com/UnityTech/openrtb"
+	. "github.com/UnityTech/openrtb/v3"
 )
 
 func TestContent(t *testing.T) {
diff --git a/device_test.go b/device_test.go
index 14a41d1..d7f8b95 100644
--- a/device_test.go
+++ b/device_test.go
@@ -4,7 +4,7 @@ import (
 	"reflect"
 	"testing"
 
-	. "github.com/UnityTech/openrtb"
+	. "github.com/UnityTech/openrtb/v3"
 )
 
 func TestDevice(t *testing.T) {
diff --git a/extension_test.go b/extension_test.go
index 2c4b407..70de18d 100644
--- a/extension_test.go
+++ b/extension_test.go
@@ -5,7 +5,7 @@ import (
 	"reflect"
 	"testing"
 
-	. "github.com/UnityTech/openrtb"
+	. "github.com/UnityTech/openrtb/v3"
 )
 
 func TestExtension(t *testing.T) {
diff --git a/go.mod b/go.mod
index 305b62c..204a70e 100644
--- a/go.mod
+++ b/go.mod
@@ -1,3 +1,3 @@
-module github.com/UnityTech/openrtb
+module github.com/UnityTech/openrtb/v3
 
-go 1.13
+go 1.18
diff --git a/impression_test.go b/impression_test.go
index 7498c4a..6a1cc2b 100644
--- a/impression_test.go
+++ b/impression_test.go
@@ -5,7 +5,7 @@ import (
 	"reflect"
 	"testing"
 
-	. "github.com/UnityTech/openrtb"
+	. "github.com/UnityTech/openrtb/v3"
 )
 
 func TestImpression(t *testing.T) {
diff --git a/inventory_test.go b/inventory_test.go
index dfbfa60..4bda401 100644
--- a/inventory_test.go
+++ b/inventory_test.go
@@ -4,7 +4,7 @@ import (
 	"reflect"
 	"testing"
 
-	. "github.com/UnityTech/openrtb"
+	. "github.com/UnityTech/openrtb/v3"
 )
 
 func TestApp(t *testing.T) {
diff --git a/metric_test.go b/metric_test.go
index e6d1522..3f256ec 100644
--- a/metric_test.go
+++ b/metric_test.go
@@ -4,7 +4,7 @@ import (
 	"reflect"
 	"testing"
 
-	. "github.com/UnityTech/openrtb"
+	. "github.com/UnityTech/openrtb/v3"
 )
 
 func TestMetric(t *testing.T) {
diff --git a/native/request/asset.go b/native/request/asset.go
index 43024da..136ea25 100644
--- a/native/request/asset.go
+++ b/native/request/asset.go
@@ -1,6 +1,6 @@
 package request
 
-import "github.com/UnityTech/openrtb"
+import "github.com/UnityTech/openrtb/v3"
 
 // Asset is the main container object for each asset requested or supported by Exchange
 // on behalf of the rendering client.  Only one of the {title,img,video,data}
diff --git a/native/request/data.go b/native/request/data.go
index 39e677f..66a86e2 100644
--- a/native/request/data.go
+++ b/native/request/data.go
@@ -1,6 +1,6 @@
 package request
 
-import "github.com/UnityTech/openrtb"
+import "github.com/UnityTech/openrtb/v3"
 
 // DataTypeID enum.
 type DataTypeID int
diff --git a/native/request/image.go b/native/request/image.go
index dc7de3f..8f950d7 100644
--- a/native/request/image.go
+++ b/native/request/image.go
@@ -1,6 +1,6 @@
 package request
 
-import "github.com/UnityTech/openrtb"
+import "github.com/UnityTech/openrtb/v3"
 
 // ImageTypeID enum.
 type ImageTypeID int
diff --git a/native/request/request.go b/native/request/request.go
index 924dfa2..8946010 100644
--- a/native/request/request.go
+++ b/native/request/request.go
@@ -1,6 +1,6 @@
 package request
 
-import "github.com/UnityTech/openrtb"
+import "github.com/UnityTech/openrtb/v3"
 
 // LayoutID enum.
 type LayoutID int
diff --git a/native/request/request_test.go b/native/request/request_test.go
index 48f2cd5..8bd33c2 100644
--- a/native/request/request_test.go
+++ b/native/request/request_test.go
@@ -6,8 +6,8 @@ import (
 	"reflect"
 	"testing"
 
-	"github.com/UnityTech/openrtb"
-	. "github.com/UnityTech/openrtb/native/request"
+	"github.com/UnityTech/openrtb/v3"
+	. "github.com/UnityTech/openrtb/v3/native/request"
 )
 
 func TestRequest(t *testing.T) {
diff --git a/native/request/title.go b/native/request/title.go
index 48ddb16..bdaa000 100644
--- a/native/request/title.go
+++ b/native/request/title.go
@@ -1,6 +1,6 @@
 package request
 
-import "github.com/UnityTech/openrtb"
+import "github.com/UnityTech/openrtb/v3"
 
 // Title is the native title object.
 type Title struct {
diff --git a/native/request/video.go b/native/request/video.go
index 9d9edeb..a59cb65 100644
--- a/native/request/video.go
+++ b/native/request/video.go
@@ -1,6 +1,6 @@
 package request
 
-import "github.com/UnityTech/openrtb"
+import "github.com/UnityTech/openrtb/v3"
 
 // Video is the native video object.
 // TODO unclear if its the same as imp.video https://github.com/openrtb/OpenRTB/issues/26
diff --git a/native/response/asset.go b/native/response/asset.go
index b1efd2d..d0846a0 100644
--- a/native/response/asset.go
+++ b/native/response/asset.go
@@ -1,6 +1,6 @@
 package response
 
-import "github.com/UnityTech/openrtb"
+import "github.com/UnityTech/openrtb/v3"
 
 // Asset corresponds to the Asset Object in the request. The main container object for
 // each asset requested or supported by Exchange on behalf of the rendering
diff --git a/native/response/data.go b/native/response/data.go
index 8736074..b90136e 100644
--- a/native/response/data.go
+++ b/native/response/data.go
@@ -1,6 +1,6 @@
 package response
 
-import "github.com/UnityTech/openrtb"
+import "github.com/UnityTech/openrtb/v3"
 
 // Data object contains response data.
 type Data struct {
diff --git a/native/response/image.go b/native/response/image.go
index eb49c3b..276f250 100644
--- a/native/response/image.go
+++ b/native/response/image.go
@@ -1,6 +1,6 @@
 package response
 
-import "github.com/UnityTech/openrtb"
+import "github.com/UnityTech/openrtb/v3"
 
 // Image object contains response image.
 type Image struct {
diff --git a/native/response/link.go b/native/response/link.go
index 7abb0f7..5bf5798 100644
--- a/native/response/link.go
+++ b/native/response/link.go
@@ -1,6 +1,6 @@
 package response
 
-import "github.com/UnityTech/openrtb"
+import "github.com/UnityTech/openrtb/v3"
 
 // Link object contains response link.
 type Link struct {
diff --git a/native/response/response.go b/native/response/response.go
index 7305815..9d6ea06 100644
--- a/native/response/response.go
+++ b/native/response/response.go
@@ -1,6 +1,6 @@
 package response
 
-import "github.com/UnityTech/openrtb"
+import "github.com/UnityTech/openrtb/v3"
 
 // Response is the native object is the top level JSON object which identifies a native response.
 type Response struct {
diff --git a/native/response/response_test.go b/native/response/response_test.go
index 6e102ea..908524d 100644
--- a/native/response/response_test.go
+++ b/native/response/response_test.go
@@ -6,7 +6,7 @@ import (
 	"reflect"
 	"testing"
 
-	. "github.com/UnityTech/openrtb/native/response"
+	. "github.com/UnityTech/openrtb/v3/native/response"
 )
 
 func TestResponse(t *testing.T) {
diff --git a/native/response/title.go b/native/response/title.go
index 873aaf7..fda13d3 100644
--- a/native/response/title.go
+++ b/native/response/title.go
@@ -1,6 +1,6 @@
 package response
 
-import "github.com/UnityTech/openrtb"
+import "github.com/UnityTech/openrtb/v3"
 
 // Title wraps title information.
 type Title struct {
diff --git a/native_test.go b/native_test.go
index fe9e2b1..57e43cf 100644
--- a/native_test.go
+++ b/native_test.go
@@ -4,7 +4,7 @@ import (
 	"reflect"
 	"testing"
 
-	. "github.com/UnityTech/openrtb"
+	. "github.com/UnityTech/openrtb/v3"
 )
 
 func TestNative(t *testing.T) {
diff --git a/numbers_test.go b/numbers_test.go
index 9079a07..543ad6c 100644
--- a/numbers_test.go
+++ b/numbers_test.go
@@ -4,7 +4,7 @@ import (
 	"encoding/json"
 	"testing"
 
-	. "github.com/UnityTech/openrtb"
+	. "github.com/UnityTech/openrtb/v3"
 )
 
 func TestNumberOrString(t *testing.T) {
diff --git a/pmp_test.go b/pmp_test.go
index 6e55d02..7a2b690 100644
--- a/pmp_test.go
+++ b/pmp_test.go
@@ -6,7 +6,7 @@ import (
 	"reflect"
 	"testing"
 
-	. "github.com/UnityTech/openrtb"
+	. "github.com/UnityTech/openrtb/v3"
 )
 
 func TestPMP(t *testing.T) {
diff --git a/quantity_test.go b/quantity_test.go
index d22bc4f..54a1e41 100644
--- a/quantity_test.go
+++ b/quantity_test.go
@@ -4,7 +4,7 @@ import (
 	"reflect"
 	"testing"
 
-	. "github.com/UnityTech/openrtb"
+	. "github.com/UnityTech/openrtb/v3"
 )
 
 func TestQuantity(t *testing.T) {
diff --git a/seatbid_test.go b/seatbid_test.go
index f768c1c..fcb2f09 100644
--- a/seatbid_test.go
+++ b/seatbid_test.go
@@ -4,7 +4,7 @@ import (
 	"errors"
 	"testing"
 
-	. "github.com/UnityTech/openrtb"
+	. "github.com/UnityTech/openrtb/v3"
 )
 
 func TestSeatBid_Validate(t *testing.T) {
diff --git a/source_test.go b/source_test.go
index 2bfb2b1..d4f9f3f 100644
--- a/source_test.go
+++ b/source_test.go
@@ -4,7 +4,7 @@ import (
 	"reflect"
 	"testing"
 
-	. "github.com/UnityTech/openrtb"
+	. "github.com/UnityTech/openrtb/v3"
 )
 
 func TestSource(t *testing.T) {
diff --git a/video_test.go b/video_test.go
index e3f7a98..8f8f5cf 100644
--- a/video_test.go
+++ b/video_test.go
@@ -5,7 +5,7 @@ import (
 	"reflect"
 	"testing"
 
-	. "github.com/UnityTech/openrtb"
+	. "github.com/UnityTech/openrtb/v3"
 )
 
 func TestVideo(t *testing.T) {

From 67ef78ab2dab0b19e1dbffff92267a8e7962ff80 Mon Sep 17 00:00:00 2001
From: rourkewhite <62619147+rourkewhite@users.noreply.github.com>
Date: Tue, 26 Mar 2024 12:43:50 -0700
Subject: [PATCH 43/54] use RegExtension regs.ext as it was prior to pulling in
 upstream changes (#37)

---
 openrtb.go | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/openrtb.go b/openrtb.go
index b529185..d44666d 100644
--- a/openrtb.go
+++ b/openrtb.go
@@ -756,10 +756,10 @@ type Segment struct {
 // coppa flag signals whether or not the request falls under the United States Federal Trade Commission's
 // regulations for the United States Children's Online Privacy Protection Act ("COPPA").
 type Regulations struct {
-	Coppa     int       `json:"coppa,omitempty"`      // Flag indicating if this request is subject to the COPPA regulations established by the USA FTC, where 0 = no, 1 = yes.
-	GDPR      int       `json:"gdpr,omitempty"`       // Flag that indicates whether or not the request is subject to GDPR regulations 0 = No, 1 = Yes, omission indicates Unknown.
-	USPrivacy string    `json:"us_privacy,omitempty"` // Communicates signals regarding consumer privacy under US privacy regulation.
-	Ext       Extension `json:"ext,omitempty"`
+	Coppa     int          `json:"coppa,omitempty"`      // Flag indicating if this request is subject to the COPPA regulations established by the USA FTC, where 0 = no, 1 = yes.
+	GDPR      int          `json:"gdpr,omitempty"`       // Flag that indicates whether or not the request is subject to GDPR regulations 0 = No, 1 = Yes, omission indicates Unknown.
+	USPrivacy string       `json:"us_privacy,omitempty"` // Communicates signals regarding consumer privacy under US privacy regulation.
+	Ext       RegExtension `json:"ext,omitempty"`
 }
 
 // Format object represents an allowed size (i.e., height and width combination) for a banner impression.

From 9c12cfbec33e8fba11b11f535f3b73f8840a0654 Mon Sep 17 00:00:00 2001
From: Vibhore Bhatnagar <vibhore.bhatnagar@unity3d.com>
Date: Wed, 10 Apr 2024 12:08:16 -0400
Subject: [PATCH 44/54] Adds custom type to handle incoming bool/int fields for
 lgpd

---
 numbers.go | 25 +++++++++++++++++++++++++
 openrtb.go |  8 ++++----
 2 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/numbers.go b/numbers.go
index 515f6ff..46ee57b 100644
--- a/numbers.go
+++ b/numbers.go
@@ -2,6 +2,7 @@ package openrtb
 
 import (
 	"encoding/json"
+	"errors"
 	"strconv"
 )
 
@@ -51,3 +52,27 @@ func (n *StringOrNumber) UnmarshalJSON(data []byte) error {
 	}
 	return nil
 }
+
+// BoolOrNumber attemps to fix OpenRTB incompatibilities where a field is expected as bool but the spec expects int values. This was not seen till now, but some mediation partners will follow the spec closely.
+type BoolOrNumber bool
+
+// UnmarshalJSON implements json.Unmarshaler
+func (b *BoolOrNumber) UnmarshalJSON(data []byte) error {
+	var val interface{}
+	if err := json.Unmarshal(data, &val); err != nil {
+		return err
+	}
+
+	switch v := val.(type) {
+	case bool:
+		*b = BoolOrNumber(v)
+	case float64:
+		// When unmarshaling JSON into an interface value, Unmarshal stores JSON numbers in the interface value float64
+		*b = BoolOrNumber(v != 0)
+	default:
+
+		return errors.New("BoolOrInt: invalid type")
+	}
+
+	return nil
+}
diff --git a/openrtb.go b/openrtb.go
index d44666d..64049e0 100644
--- a/openrtb.go
+++ b/openrtb.go
@@ -841,10 +841,10 @@ type ChannelEntity struct {
 
 // RegExtension Extension object for Regulations
 type RegExtension struct {
-	GDPR      int    `json:"gdpr,omitempty"`
-	LGPD      bool   `json:"lgpd,omitempty"`
-	PIPL      bool   `json:"pipl,omitempty"`
-	USPrivacy string `json:"us_privacy,omitempty"`
+	GDPR      int          `json:"gdpr,omitempty"`
+	LGPD      BoolOrNumber `json:"lgpd,omitempty"`
+	PIPL      BoolOrNumber `json:"pipl,omitempty"`
+	USPrivacy string       `json:"us_privacy,omitempty"`
 }
 
 // UserExtension Extension object for User

From 654ad240a01725dee3024a6ea55566f87773eba6 Mon Sep 17 00:00:00 2001
From: CarolynU <carolyn.chen@unity3d.com>
Date: Wed, 29 May 2024 10:30:50 -0700
Subject: [PATCH 45/54] Update video.go

---
 video.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/video.go b/video.go
index dd74b64..2df18b5 100644
--- a/video.go
+++ b/video.go
@@ -26,7 +26,7 @@ type Video struct {
 	H               int               `json:"h,omitempty"`              // Height of the player in pixels
 	StartDelay      int               `json:"startdelay,omitempty"`     // Indicates the start delay in seconds
 	Linearity       int               `json:"linearity,omitempty"`      // Indicates whether the ad impression is linear or non-linear
-	Skip            int               `json:"skip,omitempty"`           // Indicates if the player will allow the video to be skipped, where 0 = no, 1 = yes.
+	Skip            int               `json:"skip"`                     // Indicates if the player will allow the video to be skipped, where 0 = no, 1 = yes.
 	SkipMin         int               `json:"skipmin,omitempty"`        // Videos of total duration greater than this number of seconds can be skippable
 	SkipAfter       int               `json:"skipafter,omitempty"`      // Number of seconds a video must play before skipping is enabled
 	Sequence        int               `json:"sequence,omitempty"`       // Default: 1

From 3576ea5050b66176c3e325b4b9f3beaae344712f Mon Sep 17 00:00:00 2001
From: CarolynU <carolyn.chen@unity3d.com>
Date: Wed, 29 May 2024 11:38:24 -0700
Subject: [PATCH 46/54] Update impression.go

---
 impression.go | 1 +
 1 file changed, 1 insertion(+)

diff --git a/impression.go b/impression.go
index 2f93b16..092c78c 100644
--- a/impression.go
+++ b/impression.go
@@ -25,6 +25,7 @@ type Impression struct {
 	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
+	Clickbrowser      int            `json:"clickbrowser,omitempty"`      // Indicates the type of browser opened upon clicking the creative in an app, where 0 = embedded, 1 = native
 	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

From 08fc47eb31f2024fdda081efb36f90c2f887db13 Mon Sep 17 00:00:00 2001
From: CarolynU <carolyn.chen@unity3d.com>
Date: Wed, 29 May 2024 11:40:13 -0700
Subject: [PATCH 47/54] Update impression.go

---
 impression.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/impression.go b/impression.go
index 092c78c..c0d1c66 100644
--- a/impression.go
+++ b/impression.go
@@ -25,7 +25,7 @@ type Impression struct {
 	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
-	Clickbrowser      int            `json:"clickbrowser,omitempty"`      // Indicates the type of browser opened upon clicking the creative in an app, where 0 = embedded, 1 = native
+	Clickbrowser      int            `json:"clickbrowser"`                // Indicates the type of browser opened upon clicking the creative in an app, where 0 = embedded, 1 = native
 	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

From a7c09965a31c4f4b5805a59096ef89ed919bbb0b Mon Sep 17 00:00:00 2001
From: CarolynU <carolyn.chen@unity3d.com>
Date: Wed, 29 May 2024 11:56:52 -0700
Subject: [PATCH 48/54] Update impression.go

---
 impression.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/impression.go b/impression.go
index c0d1c66..5b1cbfb 100644
--- a/impression.go
+++ b/impression.go
@@ -25,7 +25,7 @@ type Impression struct {
 	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
-	Clickbrowser      int            `json:"clickbrowser"`                // Indicates the type of browser opened upon clicking the creative in an app, where 0 = embedded, 1 = native
+	Clickbrowser      *int           `json:"clickbrowser"`                // Indicates the type of browser opened upon clicking the creative in an app, where 0 = embedded, 1 = native
 	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

From dd9f2172a8cdc0dc7daa3376c60abdb2064a098e Mon Sep 17 00:00:00 2001
From: CarolynU <carolyn.chen@unity3d.com>
Date: Tue, 11 Feb 2025 02:05:04 -0800
Subject: [PATCH 49/54] Update source.go

---
 source.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source.go b/source.go
index e187215..615ceb8 100644
--- a/source.go
+++ b/source.go
@@ -2,7 +2,7 @@ package openrtb
 
 // Source object describes the nature and behavior of the entity that is the source of the bid request upstream from the exchange.
 type Source struct {
-	FinalSaleDecision int       `json:"fd,omitempty"`     // Entity responsible for the final impression sale decision, where 0 = exchange, 1 = upstream source.
+	FinalSaleDecision int       `json:"fd"`               // Entity responsible for the final impression sale decision, where 0 = exchange, 1 = upstream source.
 	TransactionID     string    `json:"tid,omitempty"`    // Transaction ID that must be common across all participants in this bid request (e.g., potentially multiple exchanges).
 	PaymentChain      string    `json:"pchain,omitempty"` // Payment ID chain string containing embedded syntax described in the TAG Payment ID Protocol v1.0.
 	Ext               Extension `json:"ext,omitempty"`    // Placeholder for exchange-specific extensions to OpenRTB.

From b8cbaa243ecbf8bfbd520f851d976dc24ab229a8 Mon Sep 17 00:00:00 2001
From: CarolynU <carolyn.chen@unity3d.com>
Date: Tue, 11 Feb 2025 02:19:55 -0800
Subject: [PATCH 50/54] lint

---
 audio_test.go | 2 +-
 bid_test.go   | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/audio_test.go b/audio_test.go
index d6ccf58..9ae00df 100644
--- a/audio_test.go
+++ b/audio_test.go
@@ -56,7 +56,7 @@ func TestAudio_Validate(t *testing.T) {
 		},
 		CompanionType: []int{VASTCompanionStatic, VASTCompanionHTML},
 	}
-	if exp, got := ErrInvalidAudioNoMimes, subject.Validate(); !errors.Is(exp, got) {
+	if exp, got := ErrInvalidAudioNoMimes, subject.Validate(); !errors.Is(got, exp) {
 		t.Fatalf("expected %v, got %v", exp, got)
 	}
 }
diff --git a/bid_test.go b/bid_test.go
index 9836be8..fed7861 100644
--- a/bid_test.go
+++ b/bid_test.go
@@ -35,11 +35,11 @@ func TestBid(t *testing.T) {
 
 func TestBid_Validate(t *testing.T) {
 	subject := &Bid{}
-	if exp, got := ErrInvalidBidNoID, subject.Validate(); !errors.Is(exp, got) {
+	if exp, got := ErrInvalidBidNoID, subject.Validate(); !errors.Is(got, exp) {
 		t.Fatalf("expected %v, got %v", exp, got)
 	}
 	subject = &Bid{ID: "BIDID"}
-	if exp, got := ErrInvalidBidNoImpID, subject.Validate(); !errors.Is(exp, got) {
+	if exp, got := ErrInvalidBidNoImpID, subject.Validate(); !errors.Is(got, exp) {
 		t.Fatalf("expected %v, got %v", exp, got)
 	}
 }

From 329bb02b8262e0529371637ed7a202b7856ad044 Mon Sep 17 00:00:00 2001
From: CarolynU <carolyn.chen@unity3d.com>
Date: Tue, 11 Feb 2025 02:25:57 -0800
Subject: [PATCH 51/54] update

---
 bidrequest_test.go  | 6 +++---
 bidresponse_test.go | 4 ++--
 impression_test.go  | 4 ++--
 seatbid_test.go     | 2 +-
 video_test.go       | 6 +++---
 5 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/bidrequest_test.go b/bidrequest_test.go
index bbb9023..59419fb 100644
--- a/bidrequest_test.go
+++ b/bidrequest_test.go
@@ -74,15 +74,15 @@ func TestBidRequest_complex(t *testing.T) {
 
 func TestBidRequest_Validate(t *testing.T) {
 	subject := &BidRequest{}
-	if exp, got := ErrInvalidReqNoID, subject.Validate(); !errors.Is(exp, got) {
+	if exp, got := ErrInvalidReqNoID, subject.Validate(); !errors.Is(got, exp) {
 		t.Fatalf("expected %v, got %v", exp, got)
 	}
 	subject = &BidRequest{ID: "RID"}
-	if exp, got := ErrInvalidReqNoImps, subject.Validate(); !errors.Is(exp, got) {
+	if exp, got := ErrInvalidReqNoImps, subject.Validate(); !errors.Is(got, exp) {
 		t.Fatalf("expected %v, got %v", exp, got)
 	}
 	subject = &BidRequest{ID: "A", Imp: []Impression{{ID: "1"}}, Site: &Site{}, App: &App{}}
-	if exp, got := ErrInvalidReqMultiInv, subject.Validate(); !errors.Is(exp, got) {
+	if exp, got := ErrInvalidReqMultiInv, subject.Validate(); !errors.Is(got, exp) {
 		t.Fatalf("expected %v, got %v", exp, got)
 	}
 }
diff --git a/bidresponse_test.go b/bidresponse_test.go
index 21b86dc..bc3de35 100644
--- a/bidresponse_test.go
+++ b/bidresponse_test.go
@@ -56,11 +56,11 @@ func TestBidResponse_complex(t *testing.T) {
 
 func TestBidResponse_Validate(t *testing.T) {
 	subject := &BidResponse{}
-	if exp, got := ErrInvalidRespNoID, subject.Validate(); !errors.Is(exp, got) {
+	if exp, got := ErrInvalidRespNoID, subject.Validate(); !errors.Is(got, exp) {
 		t.Fatalf("expected %v, got %v", exp, got)
 	}
 	subject = &BidResponse{ID: "RID"}
-	if exp, got := ErrInvalidRespNoSeatBids, subject.Validate(); !errors.Is(exp, got) {
+	if exp, got := ErrInvalidRespNoSeatBids, subject.Validate(); !errors.Is(got, exp) {
 		t.Fatalf("expected %v, got %v", exp, got)
 	}
 }
diff --git a/impression_test.go b/impression_test.go
index 6a1cc2b..3a4cc2c 100644
--- a/impression_test.go
+++ b/impression_test.go
@@ -55,11 +55,11 @@ func TestImpression(t *testing.T) {
 
 func TestImpression_Validate(t *testing.T) {
 	subject := &Impression{}
-	if exp, got := ErrInvalidImpNoID, subject.Validate(); !errors.Is(exp, got) {
+	if exp, got := ErrInvalidImpNoID, subject.Validate(); !errors.Is(got, exp) {
 		t.Fatalf("expected %v, got %v", exp, got)
 	}
 	subject = &Impression{ID: "IMPID", Banner: &Banner{}, Video: &Video{}}
-	if exp, got := ErrInvalidImpMultiAssets, subject.Validate(); !errors.Is(exp, got) {
+	if exp, got := ErrInvalidImpMultiAssets, subject.Validate(); !errors.Is(got, exp) {
 		t.Fatalf("expected %v, got %v", exp, got)
 	}
 }
diff --git a/seatbid_test.go b/seatbid_test.go
index fcb2f09..0590c85 100644
--- a/seatbid_test.go
+++ b/seatbid_test.go
@@ -9,7 +9,7 @@ import (
 
 func TestSeatBid_Validate(t *testing.T) {
 	subject := &SeatBid{}
-	if exp, got := ErrInvalidSeatBidBid, subject.Validate(); !errors.Is(exp, got) {
+	if exp, got := ErrInvalidSeatBidBid, subject.Validate(); !errors.Is(got, exp) {
 		t.Fatalf("expected %v, got %v", exp, got)
 	}
 }
diff --git a/video_test.go b/video_test.go
index 8f8f5cf..12037df 100644
--- a/video_test.go
+++ b/video_test.go
@@ -52,11 +52,11 @@ func TestVideo(t *testing.T) {
 
 func TestVideo_Validate(t *testing.T) {
 	subject := &Video{}
-	if exp, got := ErrInvalidVideoNoMimes, subject.Validate(); !errors.Is(exp, got) {
+	if exp, got := ErrInvalidVideoNoMimes, subject.Validate(); !errors.Is(got, exp) {
 		t.Fatalf("expected %v, got %v", exp, got)
 	}
 	subject = &Video{Mimes: []string{"video/mp4"}}
-	if exp, got := ErrInvalidVideoNoLinearity, subject.Validate(); !errors.Is(exp, got) {
+	if exp, got := ErrInvalidVideoNoLinearity, subject.Validate(); !errors.Is(got, exp) {
 		t.Fatalf("expected %v, got %v", exp, got)
 	}
 	subject = &Video{
@@ -65,7 +65,7 @@ func TestVideo_Validate(t *testing.T) {
 		Linearity:   VideoLinearityNonLinear,
 		Mimes:       []string{"video/mp4"},
 	}
-	if exp, got := ErrInvalidVideoNoProtocols, subject.Validate(); !errors.Is(exp, got) {
+	if exp, got := ErrInvalidVideoNoProtocols, subject.Validate(); !errors.Is(got, exp) {
 		t.Fatalf("expected %v, got %v", exp, got)
 	}
 }

From f01a90ec5b8258761ecaa7fe3b48c8f3a00057ec Mon Sep 17 00:00:00 2001
From: CarolynU <carolyn.chen@unity3d.com>
Date: Tue, 11 Feb 2025 02:26:48 -0800
Subject: [PATCH 52/54] Revert "Merge pull request #42 from
 UnityTech/PPS-361-3"

This reverts commit fa14158d27fe913ddf46feff69eb851156c40d1d, reversing
changes made to 8433537345efbe1f364258ea232237a1a9ec98ee.
---
 impression.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/impression.go b/impression.go
index 5b1cbfb..c0d1c66 100644
--- a/impression.go
+++ b/impression.go
@@ -25,7 +25,7 @@ type Impression struct {
 	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
-	Clickbrowser      *int           `json:"clickbrowser"`                // Indicates the type of browser opened upon clicking the creative in an app, where 0 = embedded, 1 = native
+	Clickbrowser      int            `json:"clickbrowser"`                // Indicates the type of browser opened upon clicking the creative in an app, where 0 = embedded, 1 = native
 	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

From ac6483d80c96c39409409e26b15e229ec76446ca Mon Sep 17 00:00:00 2001
From: Rourke White <62619147+rourkewhite@users.noreply.github.com>
Date: Thu, 6 Mar 2025 16:47:52 -0800
Subject: [PATCH 53/54] make UserExtension SdkData optional (#44)

---
 openrtb.go | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/openrtb.go b/openrtb.go
index 64049e0..103ce92 100644
--- a/openrtb.go
+++ b/openrtb.go
@@ -849,10 +849,10 @@ type RegExtension struct {
 
 // UserExtension Extension object for User
 type UserExtension struct {
-	Consent      string  `json:"consent,omitempty"`
-	SdkData      SdkData `json:"sdkdata,omitempty"`
-	AppStartTime int64   `json:"appStartTime,omitempty"`
-	SessionID    string  `json:"sessionId,omitempty"`
+	Consent      string   `json:"consent,omitempty"`
+	SdkData      *SdkData `json:"sdkdata,omitempty"`
+	AppStartTime int64    `json:"appStartTime,omitempty"`
+	SessionID    string   `json:"sessionId,omitempty"`
 }
 
 // SdkData object for UserExtension. Required for direct demand header bidding integration

From 569894c96ffc239d34417f54580fd471e365a14e Mon Sep 17 00:00:00 2001
From: Rourke White <62619147+rourkewhite@users.noreply.github.com>
Date: Tue, 3 Jun 2025 15:11:40 -0700
Subject: [PATCH 54/54] update User object to OpenRTB 2.6 for EIDs (#45)

---
 openrtb.go | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/openrtb.go b/openrtb.go
index 103ce92..ed67aac 100644
--- a/openrtb.go
+++ b/openrtb.go
@@ -728,6 +728,8 @@ type User struct {
 	CustomData string        `json:"customdata,omitempty"` // Optional feature to pass bidder data that was set in the exchange's cookie. The string must be in base85 cookie safe characters and be in any format. Proper JSON encoding must be used to include "escaped" quotation marks.
 	Geo        *Geo          `json:"geo,omitempty"`
 	Data       []Data        `json:"data,omitempty"`
+	Consent    string        `json:"consent,omitempty"` // GDPR TCF consent string
+	EIDs       []EID         `json:"eids,omitempty"`
 	Ext        UserExtension `json:"ext,omitempty"`
 }
 
@@ -752,6 +754,21 @@ type Segment struct {
 	Ext   Extension `json:"ext,omitempty"`
 }
 
+// EID (Extended ID) support in the OpenRTB specification allows buyers to use audience data in real-time
+// bidding. This object can contain one or more UIDs from a single source or a technology provider.
+type EID struct {
+	Source string    `json:"source,omitempty"` // Source or technology provider responsible for the set of included IDs. Expressed as a top-level domain.
+	UIDs   []UID     `json:"uids,omitempty"`   // Array of extended ID UID objects from the given source.
+	Ext    Extension `json:"ext,omitempty"`
+}
+
+// UID objects contain a single user identifier provided as part of extended identifiers.
+type UID struct {
+	ID        string    `json:"id,omitempty"`    // The identifier for the user.
+	AgentType int       `json:"atype,omitempty"` // Type of user agent the ID is from.
+	Ext       Extension `json:"ext,omitempty"`
+}
+
 // Regulations object contains any legal, governmental, or industry regulations that apply to the request. The
 // coppa flag signals whether or not the request falls under the United States Federal Trade Commission's
 // regulations for the United States Children's Online Privacy Protection Act ("COPPA").
