Repository: prebid/prebid-server
Pull request #1358 (2020-06-16 12:03:26)

Log account id and all bidder names when recovering from OpenRTB auction bidder…
… panic (#446)


Patch:
diff --git a/.travis.yml b/.travis.yml
index ea2c46c4..692141f7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,9 +1,8 @@
 language: go
 
 go:
-  - '1.12'
   - '1.13'
-  - '1.14'
+  - '1.14.2'
 
 go_import_path: github.com/prebid/prebid-server
 
diff --git a/Dockerfile b/Dockerfile
index a8fea9c3..2c60b9e3 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -3,8 +3,8 @@ RUN apt-get update && \
     apt-get -y upgrade && \
     apt-get install -y wget
 RUN cd /tmp && \
-    wget https://dl.google.com/go/go1.12.7.linux-amd64.tar.gz && \
-    tar -xf go1.12.7.linux-amd64.tar.gz && \
+    wget https://dl.google.com/go/go1.14.2.linux-amd64.tar.gz && \
+    tar -xf go1.14.2.linux-amd64.tar.gz && \
     mv go /usr/local
 RUN mkdir -p /app/prebid-server/
 WORKDIR /app/prebid-server/
diff --git a/README.md b/README.md
index a59bf5f6..b69e7e76 100644
--- a/README.md
+++ b/README.md
@@ -18,9 +18,10 @@ For more information, see:
 
 ## Installation
 
-First install [Go 1.12](https://golang.org/doc/install) latest version.
+First install [Go](https://golang.org/doc/install) version 1.13 or newer.
+
 Note that prebid-server is using [Go modules](https://blog.golang.org/using-go-modules).
-If using Go version <1.13 and are inside GOPATH `GO111MODULE` needs to be set to `GO111MODULE=on`.
+We officially support the most recent two major versions of the Go runtime. However, if you'd like to use a version <1.13 and are inside GOPATH `GO111MODULE` needs to be set to `GO111MODULE=on`.
 
 Download and prepare Prebid Server:
 
diff --git a/adapters/adocean/adocean.go b/adapters/adocean/adocean.go
index 514aeb38..8740712b 100644
--- a/adapters/adocean/adocean.go
+++ b/adapters/adocean/adocean.go
@@ -7,6 +7,7 @@ import (
 	"net/http"
 	"net/url"
 	"regexp"
+	"sort"
 	"strconv"
 	"strings"
 	"text/template"
@@ -19,7 +20,7 @@ import (
 	"github.com/prebid/prebid-server/openrtb_ext"
 )
 
-const adapterVersion = "1.0.0"
+const adapterVersion = "1.1.0"
 const maxUriLength = 8000
 const measurementCode = `
 	<script>
@@ -51,6 +52,12 @@ type ResponseAdUnit struct {
 	Error    string `json:"error"`
 }
 
+type requestData struct {
+	Url        *url.URL
+	Headers    *http.Header
+	SlaveSizes map[string]string
+}
+
 func NewAdOceanBidder(client *http.Client, endpointTemplateString string) *AdOceanAdapter {
 	a := &adapters.HTTPAdapter{Client: client}
 	endpointTemplate, err := template.New("endpointTemplate").Parse(endpointTemplateString)
@@ -89,44 +96,59 @@ func (a *AdOceanAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *adap
 		}
 	}
 
-	var httpRequests []*adapters.RequestData
 	var errors []error
-
+	var err error
+	requestsData := make([]*requestData, 0, len(request.Imp))
 	for _, auction := range request.Imp {
-		newHttpRequest, err := a.makeRequest(httpRequests, &auction, request, consentString)
+		requestsData, err = a.addNewBid(requestsData, &auction, request, consentString)
 		if err != nil {
 			errors = append(errors, err)
-		} else if newHttpRequest != nil {
-			httpRequests = append(httpRequests, newHttpRequest)
 		}
 	}
 
+	httpRequests := make([]*adapters.RequestData, 0, len(requestsData))
+	for _, requestData := range requestsData {
+		httpRequests = append(httpRequests, &adapters.RequestData{
+			Method:  "GET",
+			Uri:     requestData.Url.String(),
+			Headers: *requestData.Headers,
+		})
+	}
+
 	return httpRequests, errors
 }
 
-func (a *AdOceanAdapter) makeRequest(existingRequests []*adapters.RequestData, imp *openrtb.Imp, request *openrtb.BidRequest, consentString string) (*adapters.RequestData, error) {
+func (a *AdOceanAdapter) addNewBid(
+	requestsData []*requestData,
+	imp *openrtb.Imp,
+	request *openrtb.BidRequest,
+	consentString string,
+) ([]*requestData, error) {
 	var bidderExt adapters.ExtImpBidder
 	if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil {
-		return nil, &errortypes.BadInput{
+		return requestsData, &errortypes.BadInput{
 			Message: "Error parsing bidderExt object",
 		}
 	}
 
 	var adOceanExt openrtb_ext.ExtImpAdOcean
 	if err := json.Unmarshal(bidderExt.Bidder, &adOceanExt); err != nil {
-		return nil, &errortypes.BadInput{
+		return requestsData, &errortypes.BadInput{
 			Message: "Error parsing adOceanExt parameters",
 		}
 	}
 
-	addedToExistingRequest := addToExistingRequest(existingRequests, &adOceanExt, imp.ID)
+	addedToExistingRequest := addToExistingRequest(requestsData, &adOceanExt, imp, (request.Test == 1))
 	if addedToExistingRequest {
-		return nil, nil
+		return requestsData, nil
 	}
 
-	url, err := a.makeURL(&adOceanExt, imp.ID, request, consentString)
+	slaveSizes := map[string]string{}
+	slaveSizes[adOceanExt.SlaveID] = getImpSizes(imp)
+
+	url, err := a.makeURL(&adOceanExt, imp, request, slaveSizes, consentString)
 	if err != nil {
-		return nil, err
+		return requestsData, err
 	}
 
 	headers := http.Header{}
@@ -147,54 +169,63 @@ func (a *AdOceanAdapter) makeRequest(existingRequests []*adapters.RequestData, i
 		headers.Add("Referer", request.Site.Page)
 	}
 
-	return &adapters.RequestData{
-		Method:  "GET",
-		Uri:     url,
-		Headers: headers,
-	}, nil
+	requestsData = append(requestsData, &requestData{
+		Url:        url,
+		Headers:    &headers,
+		SlaveSizes: slaveSizes,
+	})
+
+	return requestsData, nil
 }
 
-func addToExistingRequest(existingRequests []*adapters.RequestData, newParams *openrtb_ext.ExtImpAdOcean, auctionID string) bool {
-requestsLoop:
-	for _, request := range existingRequests {
-		endpointURL, _ := url.Parse(request.Uri)
-		queryParams := endpointURL.Query()
+func addToExistingRequest(requestsData []*requestData, newParams *openrtb_ext.ExtImpAdOcean, imp *openrtb.Imp, testImp bool) bool {
+	auctionID := imp.ID
+
+	for _, requestData := range requestsData {
+		queryParams := requestData.Url.Query()
 		masterID := queryParams["id"][0]
 
 		if masterID == newParams.MasterID {
-			aids := queryParams["aid"]
-			for _, aid := range aids {
-				slaveID := strings.SplitN(aid, ":", 2)[0]
-				if slaveID == newParams.SlaveID {
-					continue requestsLoop
-				}
+			if _, has := requestData.SlaveSizes[newParams.SlaveID]; has {
+				continue
 			}
 
 			queryParams.Add("aid", newParams.SlaveID+":"+auctionID)
-			endpointURL.RawQuery = queryParams.Encode()
-			newUri := endpointURL.String()
-			if len(newUri) < maxUriLength {
-				request.Uri = newUri
+			requestData.SlaveSizes[newParams.SlaveID] = getImpSizes(imp)
+			setSlaveSizesParam(&queryParams, requestData.SlaveSizes, testImp)
+
+			newUrl := *(requestData.Url)
+			newUrl.RawQuery = queryParams.Encode()
+			if len(newUrl.String()) < maxUriLength {
+				requestData.Url = &newUrl
 				return true
 			}
+
+			delete(requestData.SlaveSizes, newParams.SlaveID)
 		}
 	}
 
 	return false
 }
 
-func (a *AdOceanAdapter) makeURL(params *openrtb_ext.ExtImpAdOcean, auctionID string, request *openrtb.BidRequest, consentString string) (string, error) {
+func (a *AdOceanAdapter) makeURL(
+	params *openrtb_ext.ExtImpAdOcean,
+	imp *openrtb.Imp,
+	request *openrtb.BidRequest,
+	slaveSizes map[string]string,
+	consentString string,
+) (*url.URL, error) {
 	endpointParams := macros.EndpointTemplateParams{Host: params.EmitterDomain}
 	host, err := macros.ResolveMacros(a.endpointTemplate, endpointParams)
 	if err != nil {
-		return "", &errortypes.BadInput{
+		return nil, &errortypes.BadInput{
 			Message: "Unable to parse endpoint url template: " + err.Error(),
 		}
 	}
 
 	endpointURL, err := url.Parse(host)
 	if err != nil {
-		return "", &errortypes.BadInput{
+		return nil, &errortypes.BadInput{
 			Message: "Malformed URL: " + err.Error(),
 		}
 	}
@@ -205,6 +236,7 @@ func (a *AdOceanAdapter) makeURL(params *openrtb_ext.ExtImpAdOcean, auctionID st
 	}
 	endpointURL.Path = "/_" + strconv.Itoa(randomizedPart) + "/ad.json"
 
+	auctionID := imp.ID
 	queryParams := url.Values{}
 	queryParams.Add("pbsrv_v", adapterVersion)
 	queryParams.Add("id", params.MasterID)
@@ -218,9 +250,58 @@ func (a *AdOceanAdapter) makeURL(params *openrtb_ext.ExtImpAdOcean, auctionID st
 	if request.User != nil && request.User.BuyerUID != "" {
 		queryParams.Add("hcuserid", request.User.BuyerUID)
 	}
+
+	setSlaveSizesParam(&queryParams, slaveSizes, (request.Test == 1))
 	endpointURL.RawQuery = queryParams.Encode()
 
-	return endpointURL.String(), nil
+	return endpointURL, nil
+}
+
+func getImpSizes(imp *openrtb.Imp) string {
+	if imp.Banner == nil {
+		return ""
+	}
+
+	if len(imp.Banner.Format) > 0 {
+		sizes := make([]string, len(imp.Banner.Format))
+		for i, format := range imp.Banner.Format {
+			sizes[i] = strconv.FormatUint(format.W, 10) + "x" + strconv.FormatUint(format.H, 10)
+		}
+
+		return strings.Join(sizes, "_")
+	}
+
+	if imp.Banner.W != nil && imp.Banner.H != nil {
+		return strconv.FormatUint(*imp.Banner.W, 10) + "x" + strconv.FormatUint(*imp.Banner.H, 10)
+	}
+
+	return ""
+}
+
+func setSlaveSizesParam(queryParams *url.Values, slaveSizes map[string]string, orderByKey bool) {
+	sizeValues := make([]string, 0, len(slaveSizes))
+	slaveIDs := make([]string, 0, len(slaveSizes))
+	for k := range slaveSizes {
+		slaveIDs = append(slaveIDs, k)
+	}
+
+	if orderByKey {
+		sort.Strings(slaveIDs)
+	}
+
+	for _, slaveID := range slaveIDs {
+		sizes := slaveSizes[slaveID]
+		if sizes == "" {
+			continue
+		}
+
+		rawSlaveID := strings.Replace(slaveID, "adocean", "", 1)
+		sizeValues = append(sizeValues, rawSlaveID+"~"+sizes)
+	}
+
+	if len(sizeValues) > 0 {
+		queryParams.Set("aosspsizes", strings.Join(sizeValues, "-"))
+	}
 }
 
 func (a *AdOceanAdapter) MakeBids(
diff --git a/adapters/avocet/avocet.go b/adapters/avocet/avocet.go
new file mode 100644
index 00000000..918fc23e
--- /dev/null
+++ b/adapters/avocet/avocet.go
@@ -0,0 +1,124 @@
+package avocet
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+
+	"github.com/mxmCherry/openrtb"
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/errortypes"
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+// AvocetAdapter implements a adapters.Bidder compatible with the Avocet advertising platform.
+type AvocetAdapter struct {
+	// Endpoint is a http endpoint to use when making requests to the Avocet advertising platform.
+	Endpoint string
+}
+
+func (a *AvocetAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
+	if len(request.Imp) == 0 {
+		return nil, nil
+	}
+
+	headers := http.Header{}
+	headers.Add("Content-Type", "application/json;charset=utf-8")
+	headers.Add("Accept", "application/json")
+	body, err := json.Marshal(request)
+	if err != nil {
+		return nil, []error{&errortypes.FailedToRequestBids{
+			Message: err.Error(),
+		}}
+	}
+	reqData := &adapters.RequestData{
+		Method:  http.MethodPost,
+		Uri:     a.Endpoint,
+		Body:    body,
+		Headers: headers,
+	}
+	return []*adapters.RequestData{reqData}, nil
+}
+
+type avocetBidExt struct {
+	Avocet avocetBidExtension `json:"avocet"`
+}
+
+type avocetBidExtension struct {
+	Duration     int `json:"duration"`
+	DealPriority int `json:"deal_priority"`
+}
+
+func (a *AvocetAdapter) MakeBids(internalRequest *openrtb.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+
+	if response.StatusCode == http.StatusNoContent {
+		return nil, nil
+	}
+
+	if response.StatusCode != http.StatusOK {
+		var errStr string
+		if len(response.Body) > 0 {
+			errStr = string(response.Body)
+		} else {
+			errStr = "no response body"
+		}
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: fmt.Sprintf("received status code: %v error: %s", response.StatusCode, errStr),
+		}}
+	}
+
+	var br openrtb.BidResponse
+	err := json.Unmarshal(response.Body, &br)
+	if err != nil {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: err.Error(),
+		}}
+	}
+	var errs []error
+
+	bidResponse := adapters.NewBidderResponseWithBidsCapacity(5)
+	for i := range br.SeatBid {
+		for j := range br.SeatBid[i].Bid {
+			var ext avocetBidExt
+			if len(br.SeatBid[i].Bid[j].Ext) > 0 {
+				err := json.Unmarshal(br.SeatBid[i].Bid[j].Ext, &ext)
+				if err != nil {
+					errs = append(errs, err)
+					continue
+				}
+			}
+			tbid := &adapters.TypedBid{
+				Bid:          &br.SeatBid[i].Bid[j],
+				DealPriority: ext.Avocet.DealPriority,
+			}
+			tbid.BidType = getBidType(br.SeatBid[i].Bid[j], ext)
+			if tbid.BidType == openrtb_ext.BidTypeVideo {
+				tbid.BidVideo = &openrtb_ext.ExtBidPrebidVideo{
+					Duration: ext.Avocet.Duration,
+				}
+			}
+			bidResponse.Bids = append(bidResponse.Bids, tbid)
+		}
+	}
+	return bidResponse, nil
+}
+
+// getBidType returns the openrtb_ext.BidType for the provided bid.
+func getBidType(bid openrtb.Bid, ext avocetBidExt) openrtb_ext.BidType {
+	if ext.Avocet.Duration != 0 {
+		return openrtb_ext.BidTypeVideo
+	}
+	switch bid.API {
+	case openrtb.APIFrameworkVPAID10, openrtb.APIFrameworkVPAID20:
+		return openrtb_ext.BidTypeVideo
+	default:
+		return openrtb_ext.BidTypeBanner
+	}
+}
+
+// NewAvocetAdapter returns a new AvocetAdapter using the provided endpoint.
+func NewAvocetAdapter(endpoint string) *AvocetAdapter {
+	return &AvocetAdapter{
+		Endpoint: endpoint,
+	}
+}
diff --git a/adapters/avocet/avocet/exemplary/banner.json b/adapters/avocet/avocet/exemplary/banner.json
new file mode 100644
index 00000000..b5e308ea
--- /dev/null
+++ b/adapters/avocet/avocet/exemplary/banner.json
@@ -0,0 +1,106 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            },
+            {
+              "w": 300,
+              "h": 600
+            }
+          ]
+        },
+        "ext": {
+          "bidder": {
+            "placement": "5ea9601ac865f911007f1b6a"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "https://bid.staging.avct.cloud/ortb/bid/5e722ee9bd6df11d063a8013",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "banner": {
+                "format": [
+                  {
+                    "w": 300,
+                    "h": 250
+                  },
+                  {
+                    "w": 300,
+                    "h": 600
+                  }
+                ]
+              },
+              "ext": {
+                "bidder": {
+                  "placement": "5ea9601ac865f911007f1b6a"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "bidid": "dd87f80c-16a0-43c8-a673-b94b3ea4d417",
+          "id": "test-request-id",
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "adm": "<iframe src=\"http://ads.staging.avct.cloud/sv?pp=${AUCTION_PRICE}&uuid=0df2c449-6d85-4179-b5d5-37f2f91caa24&ty=h&crid=5b51e49634f2021f127ff7c9&tacid=5b51e4ed89654741306813a8&aid=749d36d7-c993-455f-aefd-ffd8a7e3ccf_0&accid=5b51dd1634f2021f127ff7c0&brid=5b51e20f34f2021f127ff7c4&ioid=5b51e22089654741306813a1&caid=5b51e2d689654741306813a4&it=1&iobsid=496e8cff35b2c0110029534d&ext_aid=749d36d7-c993-455f-aefd-ffd8a7e3ccf_0&bp=15.64434783&bt=1591874537316649768&h=250&w=300&vpr=0&vdp=0&domain=example.com&gco=54510b3b816269000061a0f7&stid=542d2c1615e3c013de53a6e2&glat=0&glong=0&bip4=3232238090&ext_siid=5ea89200c865f911007f1b0e&ext_pid=1&ext_sid=5ea84df8c865f911007f1ade&ext_plid=5ea9601ac865f911007f1b6a&optv=latest:latest&invsrc=5e722ee9bd6df11d063a8013&ug=0d&ca=0&biid=requestd-54644474bf-l7gx4|eu-central-1-staging&reg=eu-central-1&ck=1_5d99a849\" height=\"250\" width=\"300\" marginwidth=0 marginheight=0 hspace=0 vspace=0 frameborder=0 scrolling=\"no\"></iframe>",
+                  "adomain": ["avocet.io"],
+                  "cid": "5b51e2d689654741306813a4",
+                  "crid": "5b51e49634f2021f127ff7c9",
+                  "h": 250,
+                  "id": "bc708396-9202-437b-b726-08b9864cb8b8",
+                  "impid": "test-imp-id",
+                  "iurl": "https://cdn.staging.avocet.io/snapshots/5b51dd1634f2021f127ff7c0/5b51e49634f2021f127ff7c9.jpeg",
+                  "language": "en",
+                  "price": 15.64434783,
+                  "w": 300
+                }
+              ],
+              "seat": "TEST_SEAT_ID"
+            }
+          ]
+        }
+      }
+    }
+  ],
+
+  "expectedBids": [
+    {
+      "bid": {
+        "adm": "<iframe src=\"http://ads.staging.avct.cloud/sv?pp=${AUCTION_PRICE}&uuid=0df2c449-6d85-4179-b5d5-37f2f91caa24&ty=h&crid=5b51e49634f2021f127ff7c9&tacid=5b51e4ed89654741306813a8&aid=749d36d7-c993-455f-aefd-ffd8a7e3ccf_0&accid=5b51dd1634f2021f127ff7c0&brid=5b51e20f34f2021f127ff7c4&ioid=5b51e22089654741306813a1&caid=5b51e2d689654741306813a4&it=1&iobsid=496e8cff35b2c0110029534d&ext_aid=749d36d7-c993-455f-aefd-ffd8a7e3ccf_0&bp=15.64434783&bt=1591874537316649768&h=250&w=300&vpr=0&vdp=0&domain=example.com&gco=54510b3b816269000061a0f7&stid=542d2c1615e3c013de53a6e2&glat=0&glong=0&bip4=3232238090&ext_siid=5ea89200c865f911007f1b0e&ext_pid=1&ext_sid=5ea84df8c865f911007f1ade&ext_plid=5ea9601ac865f911007f1b6a&optv=latest:latest&invsrc=5e722ee9bd6df11d063a8013&ug=0d&ca=0&biid=requestd-54644474bf-l7gx4|eu-central-1-staging&reg=eu-central-1&ck=1_5d99a849\" height=\"250\" width=\"300\" marginwidth=0 marginheight=0 hspace=0 vspace=0 frameborder=0 scrolling=\"no\"></iframe>",
+        "adomain": ["avocet.io"],
+        "cid": "5b51e2d689654741306813a4",
+        "crid": "5b51e49634f2021f127ff7c9",
+        "h": 250,
+        "id": "bc708396-9202-437b-b726-08b9864cb8b8",
+        "impid": "test-imp-id",
+        "iurl": "https://cdn.staging.avocet.io/snapshots/5b51dd1634f2021f127ff7c0/5b51e49634f2021f127ff7c9.jpeg",
+        "language": "en",
+        "price": 15.64434783,
+        "w": 300
+      },
+      "type": "banner"
+    }
+  ]
+}
diff --git a/adapters/avocet/avocet/exemplary/video.json b/adapters/avocet/avocet/exemplary/video.json
new file mode 100644
index 00000000..2398256b
--- /dev/null
+++ b/adapters/avocet/avocet/exemplary/video.json
@@ -0,0 +1,104 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "video": {
+          "mimes": ["video/mp4"],
+          "protocols": [2, 5],
+          "w": 1920,
+          "h": 1080
+        },
+        "ext": {
+          "bidder": {
+            "placement": "5ea9601ac865f911007f1b6a"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "https://bid.staging.avct.cloud/ortb/bid/5e722ee9bd6df11d063a8013",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "video": {
+                "mimes": ["video/mp4"],
+                "protocols": [2, 5],
+                "w": 1920,
+                "h": 1080
+              },
+              "ext": {
+                "bidder": {
+                  "placement": "5ea9601ac865f911007f1b6a"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "bidid": "a0eec3aa-f9f6-42fb-9aa4-f1b5656d4f42",
+          "id": "749d36d7-c993-455f-aefd-ffd8a7e3ccf",
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "adm": "<VAST version=\"3.0\"><Ad id=\"5ec530e32d57fe1100f17d87\"><Wrapper><AdSystem>Avocet</AdSystem><VASTAdTagURI><![CDATA[http://ads.staging.avct.cloud/vast?x=1&uuid=0df2c449-6d85-4179-b5d5-37f2f91caa24&ty=h&crid=5ec530e32d57fe1100f17d87&tacid=5ec531d32d57fe1100f17d89&aid=749d36d7-c993-455f-aefd-ffd8a7e3ccf_0&accid=5b51dd1634f2021f127ff7c0&brid=5b51e20f34f2021f127ff7c4&ioid=5b51e22089654741306813a1&caid=5b51e2d689654741306813a4&it=2&iobsid=496e8cff35b2c0110029534d&ext_aid=749d36d7-c993-455f-aefd-ffd8a7e3ccf_0&bp=15.64434783&bt=1591875033134290518&h=396&w=600&vpr=0&vdp=0&domain=example.com&gco=54510b3b816269000061a0f7&stid=542d2c1615e3c013de53a6e2&glat=0&glong=0&bip4=3232238090&ext_siid=5ea89200c865f911007f1b0e&ext_pid=1&ext_sid=5ea84df8c865f911007f1ade&ext_plid=5ea9601ac865f911007f1b6a&optv=latest:latest&invsrc=5e722ee9bd6df11d063a8013&ug=0d&ca=0&biid=requestd-54644474bf-l7gx4|eu-central-1-staging&reg=eu-central-1&pixel=1&ck=1_c343bf14]]></VASTAdTagURI><Impression><![CDATA[http://ads.staging.avct.cloud/sv?pp=${AUCTION_PRICE}&uuid=0df2c449-6d85-4179-b5d5-37f2f91caa24&ty=h&crid=5ec530e32d57fe1100f17d87&tacid=5ec531d32d57fe1100f17d89&aid=749d36d7-c993-455f-aefd-ffd8a7e3ccf_0&accid=5b51dd1634f2021f127ff7c0&brid=5b51e20f34f2021f127ff7c4&ioid=5b51e22089654741306813a1&caid=5b51e2d689654741306813a4&it=2&iobsid=496e8cff35b2c0110029534d&ext_aid=749d36d7-c993-455f-aefd-ffd8a7e3ccf_0&bp=15.64434783&bt=1591875033134290518&h=396&w=600&vpr=0&vdp=0&domain=example.com&gco=54510b3b816269000061a0f7&stid=542d2c1615e3c013de53a6e2&glat=0&glong=0&bip4=3232238090&ext_siid=5ea89200c865f911007f1b0e&ext_pid=1&ext_sid=5ea84df8c865f911007f1ade&ext_plid=5ea9601ac865f911007f1b6a&optv=latest:latest&invsrc=5e722ee9bd6df11d063a8013&ug=0d&ca=0&biid=requestd-54644474bf-l7gx4|eu-central-1-staging&reg=eu-central-1&pixel=1&ck=1_c343bf14]]></Impression><Creatives><Creative AdId=\"5ec530e32d57fe1100f17d87\"><Linear><TrackingEvents></TrackingEvents><VideoClicks></VideoClicks></Linear></Creative></Creatives></Wrapper></Ad></VAST>",
+                  "adomain": ["avocet.io"],
+                  "cid": "5b51e2d689654741306813a4",
+                  "crid": "5ec530e32d57fe1100f17d87",
+                  "h": 396,
+                  "id": "3d4c2d45-5a8c-43b8-9e15-4f48ac45204f",
+                  "impid": "dfp-ad--top-above-nav",
+                  "iurl": "https://cdn.staging.avocet.io/snapshots/5b51dd1634f2021f127ff7c0/5ec530e32d57fe1100f17d87.jpeg",
+                  "language": "en",
+                  "price": 15.64434783,
+                  "w": 600,
+                  "ext": {
+                    "avocet": {
+                      "duration": 30
+                    }
+                  }
+                }
+              ],
+              "seat": "TEST_SEAT_ID"
+            }
+          ]
+        }
+      }
+    }
+  ],
+
+  "expectedBids": [
+    {
+      "bid": {
+        "adm": "<VAST version=\"3.0\"><Ad id=\"5ec530e32d57fe1100f17d87\"><Wrapper><AdSystem>Avocet</AdSystem><VASTAdTagURI><![CDATA[http://ads.staging.avct.cloud/vast?x=1&uuid=0df2c449-6d85-4179-b5d5-37f2f91caa24&ty=h&crid=5ec530e32d57fe1100f17d87&tacid=5ec531d32d57fe1100f17d89&aid=749d36d7-c993-455f-aefd-ffd8a7e3ccf_0&accid=5b51dd1634f2021f127ff7c0&brid=5b51e20f34f2021f127ff7c4&ioid=5b51e22089654741306813a1&caid=5b51e2d689654741306813a4&it=2&iobsid=496e8cff35b2c0110029534d&ext_aid=749d36d7-c993-455f-aefd-ffd8a7e3ccf_0&bp=15.64434783&bt=1591875033134290518&h=396&w=600&vpr=0&vdp=0&domain=example.com&gco=54510b3b816269000061a0f7&stid=542d2c1615e3c013de53a6e2&glat=0&glong=0&bip4=3232238090&ext_siid=5ea89200c865f911007f1b0e&ext_pid=1&ext_sid=5ea84df8c865f911007f1ade&ext_plid=5ea9601ac865f911007f1b6a&optv=latest:latest&invsrc=5e722ee9bd6df11d063a8013&ug=0d&ca=0&biid=requestd-54644474bf-l7gx4|eu-central-1-staging&reg=eu-central-1&pixel=1&ck=1_c343bf14]]></VASTAdTagURI><Impression><![CDATA[http://ads.staging.avct.cloud/sv?pp=${AUCTION_PRICE}&uuid=0df2c449-6d85-4179-b5d5-37f2f91caa24&ty=h&crid=5ec530e32d57fe1100f17d87&tacid=5ec531d32d57fe1100f17d89&aid=749d36d7-c993-455f-aefd-ffd8a7e3ccf_0&accid=5b51dd1634f2021f127ff7c0&brid=5b51e20f34f2021f127ff7c4&ioid=5b51e22089654741306813a1&caid=5b51e2d689654741306813a4&it=2&iobsid=496e8cff35b2c0110029534d&ext_aid=749d36d7-c993-455f-aefd-ffd8a7e3ccf_0&bp=15.64434783&bt=1591875033134290518&h=396&w=600&vpr=0&vdp=0&domain=example.com&gco=54510b3b816269000061a0f7&stid=542d2c1615e3c013de53a6e2&glat=0&glong=0&bip4=3232238090&ext_siid=5ea89200c865f911007f1b0e&ext_pid=1&ext_sid=5ea84df8c865f911007f1ade&ext_plid=5ea9601ac865f911007f1b6a&optv=latest:latest&invsrc=5e722ee9bd6df11d063a8013&ug=0d&ca=0&biid=requestd-54644474bf-l7gx4|eu-central-1-staging&reg=eu-central-1&pixel=1&ck=1_c343bf14]]></Impression><Creatives><Creative AdId=\"5ec530e32d57fe1100f17d87\"><Linear><TrackingEvents></TrackingEvents><VideoClicks></VideoClicks></Linear></Creative></Creatives></Wrapper></Ad></VAST>",
+        "adomain": ["avocet.io"],
+        "cid": "5b51e2d689654741306813a4",
+        "crid": "5ec530e32d57fe1100f17d87",
+        "h": 396,
+        "id": "3d4c2d45-5a8c-43b8-9e15-4f48ac45204f",
+        "impid": "dfp-ad--top-above-nav",
+        "iurl": "https://cdn.staging.avocet.io/snapshots/5b51dd1634f2021f127ff7c0/5ec530e32d57fe1100f17d87.jpeg",
+        "language": "en",
+        "price": 15.64434783,
+        "w": 600,
+        "ext": {
+          "avocet": {
+            "duration": 30
+          }
+        }
+      },
+      "type": "video"
+    }
+  ]
+}
diff --git a/adapters/avocet/usersync.go b/adapters/avocet/usersync.go
new file mode 100644
index 00000000..f1075ab3
--- /dev/null
+++ b/adapters/avocet/usersync.go
@@ -0,0 +1,12 @@
+package avocet
+
+import (
+	"text/template"
+
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/usersync"
+)
+
+func NewAvocetSyncer(temp *template.Template) usersync.Usersyncer {
+	return adapters.NewSyncer("avocet", 63, temp, adapters.SyncTypeRedirect)
+}
diff --git a/adapters/consumable/consumable.go b/adapters/consumable/consumable.go
index 1fa23377..243f1b80 100644
--- a/adapters/consumable/consumable.go
+++ b/adapters/consumable/consumable.go
@@ -268,8 +268,11 @@ func (a *ConsumableAdapter) MakeBids(
 			//bid.referrer = utils.getTopWindowUrl();
 
 			bidderResponse.Bids = append(bidderResponse.Bids, &adapters.TypedBid{
-				Bid:     &bid,
-				BidType: getMediaTypeForImp(getImp(bid.ImpID, internalRequest.Imp)),
+				Bid: &bid,
+				// Consumable units are always HTML, never VAST.
+				// From Prebid's point of view, this means that Consumable units
+				// are always "banners".
+				BidType: openrtb_ext.BidTypeBanner,
 			})
 		}
 	}
@@ -303,16 +306,6 @@ func extractExtensions(impression openrtb.Imp) (*adapters.ExtImpBidder, *openrtb
 	return &bidderExt, &consumableExt, nil
 }
 
-func getMediaTypeForImp(imp *openrtb.Imp) openrtb_ext.BidType {
-	// TODO: Whatever logic we need here possibly as follows - may always be Video when we bid
-	if imp.Banner != nil {
-		return openrtb_ext.BidTypeBanner
-	} else if imp.Video != nil {
-		return openrtb_ext.BidTypeVideo
-	}
-	return openrtb_ext.BidTypeVideo
-}
-
 func testConsumableBidder(testClock instant, endpoint string) *ConsumableAdapter {
 	return &ConsumableAdapter{testClock, endpoint}
 }
diff --git a/config/config.go b/config/config.go
index 0f470c6a..01de9b1a 100755
--- a/config/config.go
+++ b/config/config.go
@@ -567,6 +567,7 @@ func (cfg *Configuration) setDerivedDefaults() {
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAdvangelists, "https://nep.advangelists.com/xp/user-sync?acctid={aid}&&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dadvangelists%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAJA, "https://ad.as.amanad.adtdp.com/v1/sync/ssp?ssp=4&gdpr={{.GDPR}}&us_privacy={{.USPrivacy}}&redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Daja%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%25s")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAppnexus, "https://ib.adnxs.com/getuid?"+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dadnxs%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID")
+	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderAvocet, "https://ads.avct.cloud/getuid?&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&url="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Davocet%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7B%7BUUID%7D%7D")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderBeachfront, "https://sync.bfmio.com/sync_s2s?gdpr={{.GDPR}}&us_privacy={{.USPrivacy}}&url="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dbeachfront%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%5Bio_cid%5D")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderBeintoo, "https://ib.beintoo.com/um?ssp=pbs&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dbeintoo%26uid%3D%24UID")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderBrightroll, "https://pr-bh.ybp.yahoo.com/sync/appnexusprebidserver/?gdpr={{.GDPR}}&euconsent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&url="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dbrightroll%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID")
@@ -772,6 +773,7 @@ func SetupViper(v *viper.Viper, filename string) {
 	v.SetDefault("adapters.applogy.endpoint", "http://rtb.applogy.com/v1/prebid")
 	v.SetDefault("adapters.appnexus.endpoint", "http://ib.adnxs.com/openrtb2") // Docs: https://wiki.appnexus.com/display/supply/Incoming+Bid+Request+from+SSPs
 	v.SetDefault("adapters.appnexus.platform_id", "5")
+	v.SetDefault("adapters.avocet.disabled", true)
 	v.SetDefault("adapters.beachfront.endpoint", "https://display.bfmio.com/prebid_display")
 	v.SetDefault("adapters.beachfront.extra_info", "{\"video_endpoint\":\"https://reachms.bfmio.com/bid.json?exchange_id\"}")
 	v.SetDefault("adapters.beintoo.endpoint", "https://ib.beintoo.com/um")
diff --git a/docs/bidders/avocet.md b/docs/bidders/avocet.md
new file mode 100644
index 00000000..6aa67391
--- /dev/null
+++ b/docs/bidders/avocet.md
@@ -0,0 +1,5 @@
+# Avocet Bidder
+
+Please contact Avocet at info@avocet.io if you would like to get started selling inventory via the Avocet platform.
+
+**Note:** Avocet is disabled by default. Please enable it in the app config if you wish to use it. This can be done by setting `adapters.avocet.disabled` to `false` and by setting `adapters.avocet.endpoint` to a valid Avocet endpoint url.
\ No newline at end of file
diff --git a/exchange/adapter_map.go b/exchange/adapter_map.go
index 2ea8f7fb..6e771236 100755
--- a/exchange/adapter_map.go
+++ b/exchange/adapter_map.go
@@ -25,6 +25,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/applogy"
 	"github.com/prebid/prebid-server/adapters/appnexus"
 	"github.com/prebid/prebid-server/adapters/audienceNetwork"
+	"github.com/prebid/prebid-server/adapters/avocet"
 	"github.com/prebid/prebid-server/adapters/beachfront"
 	"github.com/prebid/prebid-server/adapters/beintoo"
 	"github.com/prebid/prebid-server/adapters/brightroll"
@@ -106,6 +107,7 @@ func newAdapterMap(client *http.Client, cfg *config.Configuration, infos adapter
 		openrtb_ext.BidderAJA:          aja.NewAJABidder(cfg.Adapters[string(openrtb_ext.BidderAJA)].Endpoint),
 		openrtb_ext.BidderApplogy:      applogy.NewApplogyBidder(cfg.Adapters[string(openrtb_ext.BidderApplogy)].Endpoint),
 		openrtb_ext.BidderAppnexus:     appnexus.NewAppNexusBidder(client, cfg.Adapters[string(openrtb_ext.BidderAppnexus)].Endpoint, cfg.Adapters[string(openrtb_ext.BidderAppnexus)].PlatformID),
+		openrtb_ext.BidderAvocet:       avocet.NewAvocetAdapter(cfg.Adapters[string(openrtb_ext.BidderAvocet)].Endpoint),
 		openrtb_ext.BidderBeachfront:   beachfront.NewBeachfrontBidder(cfg.Adapters[string(openrtb_ext.BidderBeachfront)].Endpoint, cfg.Adapters[string(openrtb_ext.BidderBeachfront)].ExtraAdapterInfo),
 		openrtb_ext.BidderBeintoo:      beintoo.NewBeintooBidder(cfg.Adapters[string(openrtb_ext.BidderBeintoo)].Endpoint),
 		openrtb_ext.BidderBrightroll:   brightroll.NewBrightrollBidder(cfg.Adapters[string(openrtb_ext.BidderBrightroll)].Endpoint),
diff --git a/exchange/bidder.go b/exchange/bidder.go
index f9b4a522..df9f0a3b 100644
--- a/exchange/bidder.go
+++ b/exchange/bidder.go
@@ -389,7 +389,20 @@ func (bidder *bidderAdapter) doTimeoutNotification(timeoutBidder adapters.Timeou
 			}
 		} else {
 			bidder.me.RecordTimeoutNotice(false)
+			if bidder.DebugConfig.TimeoutNotification.Log {
+				msg := fmt.Sprintf("TimeoutNotification: Failed to make timeout request: method(%s), uri(%s), error(%s)", toReq.Method, toReq.Uri, err.Error())
+				util.LogRandomSample(msg, glog.Warningf, bidder.DebugConfig.TimeoutNotification.SamplingRate)
+			}
+		}
+	} else if bidder.DebugConfig.TimeoutNotification.Log {
+		reqJSON, err := json.Marshal(req)
+		var msg string
+		if err == nil {
+			msg = fmt.Sprintf("TimeoutNotification: Failed to generate timeout request: error(%s), bidder request(%s)", errL[0].Error(), string(reqJSON))
+		} else {
+			msg = fmt.Sprintf("TimeoutNotification: Failed to generate timeout request: error(%s), bidder request marshal failed(%s)", errL[0].Error(), err.Error())
 		}
+		util.LogRandomSample(msg, glog.Warningf, bidder.DebugConfig.TimeoutNotification.SamplingRate)
 	}
 
 }
diff --git a/exchange/exchange.go b/exchange/exchange.go
index 84ae35d6..d7eab0f4 100644
--- a/exchange/exchange.go
+++ b/exchange/exchange.go
@@ -303,7 +303,7 @@ func (e *exchange) getAllBids(ctx context.Context, cleanRequests map[openrtb_ext
 	for bidderName, req := range cleanRequests {
 		// Here we actually call the adapters and collect the bids.
 		coreBidder := resolveBidder(string(bidderName), aliases)
-		bidderRunner := e.recoverSafely(func(aName openrtb_ext.BidderName, coreBidder openrtb_ext.BidderName, request *openrtb.BidRequest, bidlabels *pbsmetrics.AdapterLabels, conversions currencies.Conversions) {
+		bidderRunner := e.recoverSafely(cleanRequests, func(aName openrtb_ext.BidderName, coreBidder openrtb_ext.BidderName, request *openrtb.BidRequest, bidlabels *pbsmetrics.AdapterLabels, conversions currencies.Conversions) {
 			// Passing in aName so a doesn't change out from under the go routine
 			if bidlabels.Adapter == "" {
 				glog.Errorf("Exchange: bidlables for %s (%s) missing adapter string", aName, coreBidder)
@@ -373,11 +373,24 @@ func (e *exchange) getAllBids(ctx context.Context, cleanRequests map[openrtb_ext
 	return adapterBids, adapterExtra, bidsFound
 }
 
-func (e *exchange) recoverSafely(inner func(openrtb_ext.BidderName, openrtb_ext.BidderName, *openrtb.BidRequest, *pbsmetrics.AdapterLabels, currencies.Conversions), chBids chan *bidResponseWrapper) func(openrtb_ext.BidderName, openrtb_ext.BidderName, *openrtb.BidRequest, *pbsmetrics.AdapterLabels, currencies.Conversions) {
+func (e *exchange) recoverSafely(cleanRequests map[openrtb_ext.BidderName]*openrtb.BidRequest, inner func(openrtb_ext.BidderName, openrtb_ext.BidderName, *openrtb.BidRequest, *pbsmetrics.AdapterLabels, currencies.Conversions), chBids chan *bidResponseWrapper) func(openrtb_ext.BidderName, openrtb_ext.BidderName, *openrtb.BidRequest, *pbsmetrics.AdapterLabels, currencies.Conversions) {
 	return func(aName openrtb_ext.BidderName, coreBidder openrtb_ext.BidderName, request *openrtb.BidRequest, bidlabels *pbsmetrics.AdapterLabels, conversions currencies.Conversions) {
 		defer func() {
 			if r := recover(); r != nil {
-				glog.Errorf("OpenRTB auction recovered panic from Bidder %s: %v. Stack trace is: %v", coreBidder, r, string(debug.Stack()))
+
+				allBidders := ""
+				sb := strings.Builder{}
+				for k := range cleanRequests {
+					sb.WriteString(string(k))
+					sb.WriteString(",")
+				}
+				if sb.Len() > 0 {
+					allBidders = sb.String()[:sb.Len()-1]
+				}
+
+				glog.Errorf("OpenRTB auction recovered panic from Bidder %s: %v. "+
+					"Account id: %s, All Bidders: %s, Stack trace is: %v",
+					coreBidder, r, bidlabels.PubID, allBidders, string(debug.Stack()))
 				e.me.RecordAdapterPanic(*bidlabels)
 				// Let the master request know that there is no data here
 				brw := new(bidResponseWrapper)
diff --git a/go.mod b/go.mod
index 0224057e..72bb9b74 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
 module github.com/prebid/prebid-server
 
-go 1.12
+go 1.13
 
 require (
 	github.com/BurntSushi/toml v0.3.1 // indirect
diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go
index 659c6616..416f36d1 100755
--- a/openrtb_ext/bidders.go
+++ b/openrtb_ext/bidders.go
@@ -40,6 +40,7 @@ const (
 	BidderApplogy          BidderName = "applogy"
 	BidderAppnexus         BidderName = "appnexus"
 	BidderAdoppler         BidderName = "adoppler"
+	BidderAvocet           BidderName = "avocet"
 	BidderBeachfront       BidderName = "beachfront"
 	BidderBeintoo          BidderName = "beintoo"
 	BidderBrightroll       BidderName = "brightroll"
@@ -118,6 +119,7 @@ var BidderMap = map[string]BidderName{
 	"applogy":           BidderApplogy,
 	"appnexus":          BidderAppnexus,
 	"adoppler":          BidderAdoppler,
+	"avocet":            BidderAvocet,
 	"beachfront":        BidderBeachfront,
 	"beintoo":           BidderBeintoo,
 	"brightroll":        BidderBrightroll,
diff --git a/openrtb_ext/imp_avocet.go b/openrtb_ext/imp_avocet.go
new file mode 100644
index 00000000..7c9ca8c6
--- /dev/null
+++ b/openrtb_ext/imp_avocet.go
@@ -0,0 +1,7 @@
+package openrtb_ext
+
+// ExtImpAvocet defines the contract for bidrequest.imp[i].ext.avocet
+type ExtImpAvocet struct {
+	Placement     string `json:"placement,omitempty"`
+	PlacementCode string `json:"placement_code,omitempty"`
+}
diff --git a/static/adapter/appnexus/opts.json b/static/adapter/appnexus/opts.json
index 7bb297e0..41ee3c8f 100644
--- a/static/adapter/appnexus/opts.json
+++ b/static/adapter/appnexus/opts.json
@@ -5,13 +5,14 @@
     "3": "IAB10-1",
     "4": "IAB2-3",
     "5": "IAB19-8",
+    "6": "IAB22-1",
     "7": "IAB18-1",
-    "8": "IAB14-1",
+    "8": "IAB12-3",
     "9": "IAB5-1",
     "10": "IAB4-5",
     "11": "IAB13-4",
-    "13": "IAB19-2",
     "12": "IAB8-7",
+    "13": "IAB9-7",
     "14": "IAB7-1",
     "15": "IAB20-18",
     "16": "IAB10-7",
@@ -20,33 +21,79 @@
     "19": "IAB18-4",
     "20": "IAB1-5",
     "21": "IAB1-6",
-    "22": "IAB19-28",
+    "22": "IAB3-4",
     "23": "IAB19-13",
     "24": "IAB22-2",
     "25": "IAB3-9",
-    "26": "IAB17-26",
+    "26": "IAB17-18",
     "27": "IAB19-6",
     "28": "IAB1-7",
-    "29": "IAB9-5",
+    "29": "IAB9-30",
     "30": "IAB20-7",
     "31": "IAB20-17",
     "32": "IAB7-32",
     "33": "IAB16-5",
     "34": "IAB19-34",
+    "35": "IAB11-5",
+    "36": "IAB12-3",
     "37": "IAB11-4",
+    "38": "IAB12-3",
     "39": "IAB9-30",
     "41": "IAB7-44",
+    "42": "IAB7-1",
+    "43": "IAB7-30",
+    "50": "IAB19-30",
     "51": "IAB17-12",
+    "52": "IAB19-30",
     "53": "IAB3-1",
     "55": "IAB13-2",
+    "56": "IAB19-30",
+    "57": "IAB19-30",
+    "58": "IAB7-39",
+    "59": "IAB22-1",
+    "60": "IAB7-39",
     "61": "IAB21-3",
-    "62": "IAB6-4",
-    "63": "IAB15-10",
+    "62": "IAB5-1",
+    "63": "IAB12-3",
+    "64": "IAB20-18",
     "65": "IAB11-2",
+    "66": "IAB17-18",
     "67": "IAB9-9",
-    "69": "IAB7-1",
-    "71": "IAB22-2",
+    "68": "IAB9-5",
+    "69": "IAB7-44",
+    "71": "IAB22-3",
+    "73": "IAB19-30",
     "74": "IAB8-5",
-    "87": "IAB3-7"
-  }
+    "78": "IAB22-1",
+    "85": "IAB12-2",
+    "86": "IAB22-3",
+    "87": "IAB11-3",
+    "112": "IAB7-32",
+    "113": "IAB7-32",
+    "114": "IAB7-32",
+    "115": "IAB7-32",
+    "118": "IAB9-5",
+    "119": "IAB9-5",
+    "120": "IAB9-5",
+    "121": "IAB9-5",
+    "122": "IAB9-5",
+    "123": "IAB9-5",
+    "124": "IAB9-5",
+    "125": "IAB9-5",
+    "126": "IAB9-5",
+    "127": "IAB22-1",
+    "132": "IAB1-2",
+    "133": "IAB19-30",
+    "137": "IAB3-9",
+    "138": "IAB19-3",
+    "140": "IAB2-3",
+    "141": "IAB2-1",
+    "142": "IAB2-3",
+    "143": "IAB17-13",
+    "166": "IAB11-4",
+    "175": "IAB3-1",
+    "176": "IAB13-4",
+    "182": "IAB8-9",
+    "183": "IAB3-5"
+    }
 }
diff --git a/static/bidder-info/avocet.yaml b/static/bidder-info/avocet.yaml
new file mode 100644
index 00000000..ea98982d
--- /dev/null
+++ b/static/bidder-info/avocet.yaml
@@ -0,0 +1,11 @@
+maintainer:
+  email: "developers@avocet.io"
+capabilities:
+  app:
+    mediaTypes:
+      - banner
+      - video
+  site:
+    mediaTypes:
+      - banner
+      - video
diff --git a/static/bidder-params/avocet.json b/static/bidder-params/avocet.json
new file mode 100644
index 00000000..f27e5950
--- /dev/null
+++ b/static/bidder-params/avocet.json
@@ -0,0 +1,24 @@
+{
+  "$schema": "http://json-schema.org/draft-04/schema#",
+  "title": "Avocet Adapter Params",
+  "description": "A schema which validates params accepted by the Avocet adapter",
+  "type": "object",
+  "properties": {
+    "placement": {
+      "type": "string",
+      "description": "An Avocet placement ID"
+    },
+    "placement_code": {
+      "type": "string",
+      "description": "An Avocet placement external code"
+    }
+  },
+  "oneOf": [
+    {
+      "required": ["placement"]
+    },
+    {
+      "required": ["placement_code"]
+    }
+  ]
+}
diff --git a/static/category-mapping/freewheel/freewheel.json b/static/category-mapping/freewheel/freewheel.json
index 7eebcce0..1c4a4fa2 100644
--- a/static/category-mapping/freewheel/freewheel.json
+++ b/static/category-mapping/freewheel/freewheel.json
@@ -3,1176 +3,1180 @@
     "id": "404",
     "name": "Publishing"
   },
-  "IAB1-2": {
-    "id": "392",
-    "name": "Entertainment"
-  },
-  "IAB1-5": {
-    "id": "419",
-    "name": "Filmed Entertainment"
-  },
-  "IAB1-6": {
-    "id": "392",
-    "name": "Entertainment"
-  },
-  "IAB1-7": {
-    "id": "392",
-    "name": "Entertainment"
-  },
-  "IAB2-1": {
-    "id": "399",
-    "name": "Automotive"
-  },
-  "IAB2-2": {
-    "id": "399",
-    "name": "Automotive"
-  },
-  "IAB2-3": {
-    "id": "399",
-    "name": "Automotive"
-  },
-  "IAB2-4": {
-    "id": "399",
-    "name": "Automotive"
-  },
-  "IAB2-5": {
-    "id": "399",
-    "name": "Automotive"
-  },
-  "IAB2-6": {
-    "id": "399",
-    "name": "Automotive"
-  },
-  "IAB2-7": {
-    "id": "399",
-    "name": "Automotive"
-  },
-  "IAB2-8": {
-    "id": "399",
-    "name": "Automotive"
-  },
-  "IAB2-9": {
-    "id": "399",
-    "name": "Automotive"
-  },
-  "IAB2-10": {
-    "id": "399",
-    "name": "Automotive"
-  },
-  "IAB2-11": {
-    "id": "399",
-    "name": "Automotive"
-  },
-  "IAB2-12": {
-    "id": "399",
-    "name": "Automotive"
-  },
-  "IAB2-13": {
-    "id": "399",
-    "name": "Automotive"
-  },
-  "IAB2-14": {
-    "id": "399",
-    "name": "Automotive"
-  },
-  "IAB2-15": {
-    "id": "399",
-    "name": "Automotive"
-  },
-  "IAB2-16": {
-    "id": "399",
-    "name": "Automotive"
-  },
-  "IAB2-17": {
-    "id": "399",
-    "name": "Automotive"
-  },
-  "IAB2-18": {
-    "id": "399",
-    "name": "Automotive"
-  },
-  "IAB2-19": {
-    "id": "399",
-    "name": "Automotive"
-  },
-  "IAB2-20": {
-    "id": "399",
-    "name": "Automotive"
-  },
-  "IAB2-21": {
-    "id": "399",
-    "name": "Automotive"
-  },
-  "IAB2-22": {
-    "id": "399",
-    "name": "Automotive"
-  },
-  "IAB2-23": {
-    "id": "399",
-    "name": "Automotive"
-  },
-  "IAB3-1": {
-    "id": "393",
-    "name": "Business Services"
-  },
-  "IAB3-2": {
-    "id": "393",
-    "name": "Business Services"
-  },
-  "IAB3-3": {
-    "id": "393",
-    "name": "Business Services"
-  },
-  "IAB3-4": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB3-5": {
-    "id": "393",
-    "name": "Business Services"
-  },
-  "IAB3-6": {
-    "id": "393",
-    "name": "Business Services"
-  },
-  "IAB3-7": {
-    "id": "398",
-    "name": "Government/Municipal"
-  },
-  "IAB3-8": {
-    "id": "393",
-    "name": "Business Services"
-  },
-  "IAB3-9": {
-    "id": "393",
-    "name": "Business Services"
-  },
-  "IAB3-10": {
-    "id": "393",
-    "name": "Business Services"
-  },
-  "IAB3-11": {
-    "id": "393",
-    "name": "Business Services"
-  },
-  "IAB3-12": {
-    "id": "393",
-    "name": "Business Services"
-  },
-  "IAB4-1": {
-    "id": "393",
-    "name": "Business Services"
-  },
-  "IAB4-2": {
-    "id": "405",
-    "name": "Educational Services"
-  },
-  "IAB4-3": {
-    "id": "405",
-    "name": "Educational Services"
-  },
-  "IAB4-4": {
-    "id": "393",
-    "name": "Business Services"
-  },
-  "IAB4-5": {
-    "id": "393",
-    "name": "Business Services"
-  },
-  "IAB4-6": {
-    "id": "393",
-    "name": "Business Services"
-  },
-  "IAB4-7": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB4-8": {
-    "id": "405",
-    "name": "Educational Services"
-  },
-  "IAB4-9": {
-    "id": "417",
-    "name": "Telecommunications"
-  },
-  "IAB4-10": {
-    "id": "429",
-    "name": "Military"
-  },
-  "IAB4-11": {
-    "id": "393",
-    "name": "Business Services"
-  },
-  "IAB5-1": {
-    "id": "405",
-    "name": "Educational Services"
-  },
-  "IAB5-2": {
-    "id": "405",
-    "name": "Educational Services"
-  },
-  "IAB5-3": {
-    "id": "405",
-    "name": "Educational Services"
-  },
-  "IAB5-4": {
-    "id": "405",
-    "name": "Educational Services"
-  },
-  "IAB5-5": {
-    "id": "405",
-    "name": "Educational Services"
-  },
-  "IAB5-6": {
-    "id": "405",
-    "name": "Educational Services"
-  },
-  "IAB5-7": {
-    "id": "405",
-    "name": "Educational Services"
-  },
-  "IAB5-8": {
-    "id": "405",
-    "name": "Educational Services"
-  },
-  "IAB5-9": {
-    "id": "405",
-    "name": "Educational Services"
-  },
-  "IAB5-10": {
-    "id": "405",
-    "name": "Educational Services"
-  },
-  "IAB5-11": {
-    "id": "405",
-    "name": "Educational Services"
-  },
-  "IAB5-12": {
-    "id": "405",
-    "name": "Educational Services"
-  },
-  "IAB5-13": {
-    "id": "405",
-    "name": "Educational Services"
-  },
-  "IAB5-14": {
-    "id": "405",
-    "name": "Educational Services"
-  },
-  "IAB5-15": {
-    "id": "405",
-    "name": "Educational Services"
-  },
-  "IAB7-1": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-2": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-3": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-4": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-5": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-6": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-7": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-8": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-9": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-10": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-11": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-12": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-13": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-14": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-15": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-16": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-17": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-18": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-19": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-20": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-21": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-22": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-23": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-24": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-25": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-26": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-27": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-28": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-29": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-30": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-31": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-32": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-33": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-34": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-35": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-36": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-37": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-38": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-39": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-40": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-41": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-42": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-43": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-44": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB7-45": {
-    "id": "406",
-    "name": "Health Care Services"
-  },
-  "IAB8-1": {
-    "id": "394",
-    "name": "Food"
-  },
-  "IAB8-2": {
-    "id": "394",
-    "name": "Food"
-  },
-  "IAB8-3": {
-    "id": "394",
-    "name": "Food"
-  },
-  "IAB8-4": {
-    "id": "394",
-    "name": "Food"
-  },
-  "IAB8-5": {
-    "id": "400",
-    "name": "Beer/Wine/Liquor"
-  },
-  "IAB8-6": {
-    "id": "401",
-    "name": "Beverages"
-  },
-  "IAB8-7": {
-    "id": "394",
-    "name": "Food"
-  },
-  "IAB8-8": {
-    "id": "394",
-    "name": "Food"
-  },
-  "IAB8-9": {
-    "id": "407",
-    "name": "Restaurant/Fast Food"
-  },
-  "IAB8-10": {
-    "id": "394",
-    "name": "Food"
-  },
-  "IAB8-11": {
-    "id": "394",
-    "name": "Food"
-  },
-  "IAB8-12": {
-    "id": "394",
-    "name": "Food"
-  },
-  "IAB8-13": {
-    "id": "394",
-    "name": "Food"
-  },
-  "IAB8-14": {
-    "id": "394",
-    "name": "Food"
-  },
-  "IAB8-15": {
-    "id": "394",
-    "name": "Food"
-  },
-  "IAB8-16": {
-    "id": "394",
-    "name": "Food"
-  },
-  "IAB8-17": {
-    "id": "394",
-    "name": "Food"
-  },
-  "IAB8-18": {
-    "id": "400",
-    "name": "Beer/Wine/Liquor"
-  },
-  "IAB9-1": {
-    "id": "392",
-    "name": "Entertainment"
-  },
-  "IAB9-3": {
-    "id": "418",
-    "name": "Jewelry"
-  },
-  "IAB9-5": {
-    "id": "413",
-    "name": "Gaming"
-  },
-  "IAB9-6": {
-    "id": "412",
-    "name": "Household Products"
-  },
-  "IAB9-9": {
-    "id": "426",
-    "name": "Tobacco"
-  },
-  "IAB9-11": {
-    "id": "404",
-    "name": "Publishing"
-  },
-  "IAB9-15": {
-    "id": "404",
-    "name": "Publishing"
-  },
-  "IAB9-16": {
-    "id": "392",
-    "name": "Entertainment"
-  },
-  "IAB9-18": {
-    "id": "393",
-    "name": "Business Services"
-  },
-  "IAB9-19": {
-    "id": "418",
-    "name": "Jewelry"
-  },
-  "IAB9-23": {
-    "id": "424",
-    "name": "Photographic Equipment"
-  },
-  "IAB9-24": {
-    "id": "392",
-    "name": "Entertainment"
-  },
-  "IAB9-25": {
-    "id": "392",
-    "name": "Entertainment"
-  },
-  "IAB9-30": {
-    "id": "413",
-    "name": "Gaming"
-  },
-  "IAB10-1": {
-    "id": "415",
-    "name": "Appliances"
-  },
-  "IAB10-5": {
-    "id": "434",
-    "name": "Home Furnishings"
-  },
-  "IAB10-6": {
-    "id": "434",
-    "name": "Home Furnishings"
-  },
-  "IAB10-7": {
-    "id": "434",
-    "name": "Home Furnishings"
-  },
-  "IAB10-8": {
-    "id": "393",
-    "name": "Business Services"
-  },
-  "IAB10-9": {
-    "id": "434",
-    "name": "Home Furnishings"
-  },
-  "IAB11-1": {
-    "id": "398",
-    "name": "Government/Municipal"
-  },
-  "IAB11-2": {
-    "id": "398",
-    "name": "Government/Municipal"
-  },
-  "IAB11-3": {
-    "id": "398",
-    "name": "Government/Municipal"
-  },
-  "IAB11-4": {
-    "id": "398",
-    "name": "Government/Municipal"
-  },
-  "IAB11-5": {
-    "id": "398",
-    "name": "Government/Municipal"
-  },
-  "IAB12-1": {
-    "id": "438",
-    "name": "News"
-  },
-  "IAB12-2": {
-    "id": "438",
-    "name": "News"
-  },
-  "IAB12-3": {
-    "id": "438",
-    "name": "News"
-  },
-  "IAB13-1": {
-    "id": "393",
-    "name": "Business Services"
-  },
-  "IAB13-2": {
-    "id": "393",
-    "name": "Business Services"
-  },
-  "IAB13-3": {
-    "id": "438",
-    "name": "News"
-  },
-  "IAB13-4": {
-    "id": "391",
-    "name": "Financial Services"
-  },
-  "IAB13-5": {
-    "id": "393",
-    "name": "Business Services"
-  },
-  "IAB13-6": {
-    "id": "436",
-    "name": "Insurance"
-  },
-  "IAB13-7": {
-    "id": "393",
-    "name": "Business Services"
-  },
-  "IAB13-8": {
-    "id": "393",
-    "name": "Business Services"
-  },
-  "IAB13-9": {
-    "id": "393",
-    "name": "Business Services"
-  },
-  "IAB13-10": {
-    "id": "393",
-    "name": "Business Services"
-  },
-  "IAB13-11": {
-    "id": "393",
-    "name": "Business Services"
-  },
-  "IAB13-12": {
-    "id": "393",
-    "name": "Business Services"
-  },
-  "IAB16-1": {
-    "id": "423",
-    "name": "Pet Food/Supplies"
-  },
-  "IAB16-2": {
-    "id": "423",
-    "name": "Pet Food/Supplies"
-  },
-  "IAB16-3": {
-    "id": "423",
-    "name": "Pet Food/Supplies"
-  },
-  "IAB16-4": {
-    "id": "423",
-    "name": "Pet Food/Supplies"
-  },
-  "IAB16-5": {
-    "id": "423",
-    "name": "Pet Food/Supplies"
-  },
-  "IAB16-6": {
-    "id": "423",
-    "name": "Pet Food/Supplies"
-  },
-  "IAB16-7": {
-    "id": "423",
-    "name": "Pet Food/Supplies"
-  },
-  "IAB17-1": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-2": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-3": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-4": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-5": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-6": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-7": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-8": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-9": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-10": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-11": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-12": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-13": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-14": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-15": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-16": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-17": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-18": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-19": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-20": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-21": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-22": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-23": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-24": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-25": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-26": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-27": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-28": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-29": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-30": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-31": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-32": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-33": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-34": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-35": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-36": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-37": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-38": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-39": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-40": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-41": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-42": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-43": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB17-44": {
-    "id": "425",
-    "name": "Professional Sports"
-  },
-  "IAB18-1": {
-    "id": "411",
-    "name": "Cosmetics/Toiletries"
-  },
-  "IAB18-2": {
-    "id": "397",
-    "name": "Apparel"
-  },
-  "IAB18-3": {
-    "id": "397",
-    "name": "Apparel"
-  },
-  "IAB18-4": {
-    "id": "418",
-    "name": "Jewelry"
-  },
-  "IAB18-5": {
-    "id": "397",
-    "name": "Apparel"
-  },
-  "IAB18-6": {
-    "id": "397",
-    "name": "Apparel"
-  },
-  "IAB19-2": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-3": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-4": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-5": {
-    "id": "424",
-    "name": "Photographic Equipment"
-  },
-  "IAB19-6": {
-    "id": "417",
-    "name": "Telecommunications"
-  },
-  "IAB19-7": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-8": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-9": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-10": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-11": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-12": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-13": {
-    "id": "404",
-    "name": "Publishing"
-  },
-  "IAB19-14": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-15": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-16": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-17": {
-    "id": "419",
-    "name": "Filmed Entertainment"
-  },
-  "IAB19-18": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-19": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-20": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-21": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-22": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-23": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-24": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-25": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-26": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-27": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-28": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-29": {
-    "id": "392",
-    "name": "Entertainment"
-  },
-  "IAB19-30": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-31": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-32": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-33": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-34": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-35": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB19-36": {
-    "id": "409",
-    "name": "Computing Product"
-  },
-  "IAB20-1": {
-    "id": "395",
-    "name": "Travel/Hotels/Airlines"
-  },
-  "IAB20-2": {
-    "id": "395",
-    "name": "Travel/Hotels/Airlines"
-  },
-  "IAB20-3": {
-    "id": "395",
-    "name": "Travel/Hotels/Airlines"
-  },
-  "IAB20-4": {
-    "id": "395",
-    "name": "Travel/Hotels/Airlines"
-  },
-  "IAB20-5": {
-    "id": "395",
-    "name": "Travel/Hotels/Airlines"
-  },
-  "IAB20-6": {
-    "id": "395",
-    "name": "Travel/Hotels/Airlines"
-  },
-  "IAB20-7": {
-    "id": "395",
-    "name": "Travel/Hotels/Airlines"
-  },
-  "IAB20-8": {
-    "id": "395",
-    "name": "Travel/Hotels/Airlines"
-  },
-  "IAB20-9": {
-    "id": "395",
-    "name": "Travel/Hotels/Airlines"
-  },
-  "IAB20-10": {
-    "id": "395",
-    "name": "Travel/Hotels/Airlines"
-  },
-  "IAB20-11": {
-    "id": "395",
-    "name": "Travel/Hotels/Airlines"
-  },
-  "IAB20-12": {
-    "id": "395",
-    "name": "Travel/Hotels/Airlines"
-  },
-  "IAB20-13": {
-    "id": "395",
-    "name": "Travel/Hotels/Airlines"
-  },
-  "IAB20-14": {
-    "id": "395",
-    "name": "Travel/Hotels/Airlines"
-  },
-  "IAB20-15": {
-    "id": "395",
-    "name": "Travel/Hotels/Airlines"
-  },
-  "IAB20-16": {
-    "id": "395",
-    "name": "Travel/Hotels/Airlines"
-  },
-  "IAB20-17": {
-    "id": "395",
-    "name": "Travel/Hotels/Airlines"
-  },
-  "IAB20-18": {
-    "id": "395",
-    "name": "Travel/Hotels/Airlines"
-  },
-  "IAB20-19": {
-    "id": "395",
-    "name": "Travel/Hotels/Airlines"
-  },
-  "IAB20-20": {
-    "id": "395",
-    "name": "Travel/Hotels/Airlines"
-  },
-  "IAB20-21": {
-    "id": "395",
-    "name": "Travel/Hotels/Airlines"
-  },
-  "IAB20-22": {
-    "id": "395",
-    "name": "Travel/Hotels/Airlines"
-  },
-  "IAB20-23": {
-    "id": "395",
-    "name": "Travel/Hotels/Airlines"
-  },
-  "IAB20-24": {
-    "id": "395",
-    "name": "Travel/Hotels/Airlines"
-  },
-  "IAB20-25": {
-    "id": "395",
-    "name": "Travel/Hotels/Airlines"
-  },
-  "IAB20-26": {
-    "id": "395",
-    "name": "Travel/Hotels/Airlines"
-  },
-  "IAB20-27": {
-    "id": "395",
-    "name": "Travel/Hotels/Airlines"
-  },
-  "IAB21-1": {
-    "id": "416",
-    "name": "Real Estate"
-  },
-  "IAB21-2": {
-    "id": "416",
-    "name": "Real Estate"
-  },
-  "IAB21-3": {
-    "id": "416",
-    "name": "Real Estate"
-  },
-  "IAB22-1": {
-    "id": "416",
-    "name": "Real Estate"
-  },
-  "IAB22-2": {
-    "id": "416",
-    "name": "Real Estate"
-  },
-  "IAB22-3": {
-    "id": "416",
-    "name": "Real Estate"
-  }
+	"IAB1-2": {
+		"id": "392",
+		"name": "Entertainment"
+	},
+	"IAB1-5": {
+		"id": "419",
+		"name": "Filmed Entertainment"
+	},
+	"IAB1-6": {
+		"id": "392",
+		"name": "Entertainment"
+	},
+	"IAB1-7": {
+		"id": "392",
+		"name": "Entertainment"
+	},
+	"IAB2-1": {
+		"id": "399",
+		"name": "Automotive"
+	},
+	"IAB2-2": {
+		"id": "399",
+		"name": "Automotive"
+	},
+	"IAB2-3": {
+		"id": "399",
+		"name": "Automotive"
+	},
+	"IAB2-4": {
+		"id": "399",
+		"name": "Automotive"
+	},
+	"IAB2-5": {
+		"id": "399",
+		"name": "Automotive"
+	},
+	"IAB2-6": {
+		"id": "399",
+		"name": "Automotive"
+	},
+	"IAB2-7": {
+		"id": "399",
+		"name": "Automotive"
+	},
+	"IAB2-8": {
+		"id": "399",
+		"name": "Automotive"
+	},
+	"IAB2-9": {
+		"id": "399",
+		"name": "Automotive"
+	},
+	"IAB2-10": {
+		"id": "399",
+		"name": "Automotive"
+	},
+	"IAB2-11": {
+		"id": "399",
+		"name": "Automotive"
+	},
+	"IAB2-12": {
+		"id": "399",
+		"name": "Automotive"
+	},
+	"IAB2-13": {
+		"id": "399",
+		"name": "Automotive"
+	},
+	"IAB2-14": {
+		"id": "399",
+		"name": "Automotive"
+	},
+	"IAB2-15": {
+		"id": "399",
+		"name": "Automotive"
+	},
+	"IAB2-16": {
+		"id": "399",
+		"name": "Automotive"
+	},
+	"IAB2-17": {
+		"id": "399",
+		"name": "Automotive"
+	},
+	"IAB2-18": {
+		"id": "399",
+		"name": "Automotive"
+	},
+	"IAB2-19": {
+		"id": "399",
+		"name": "Automotive"
+	},
+	"IAB2-20": {
+		"id": "399",
+		"name": "Automotive"
+	},
+	"IAB2-21": {
+		"id": "399",
+		"name": "Automotive"
+	},
+	"IAB2-22": {
+		"id": "399",
+		"name": "Automotive"
+	},
+	"IAB2-23": {
+		"id": "399",
+		"name": "Automotive"
+	},
+	"IAB3-1": {
+		"id": "393",
+		"name": "Business Services"
+	},
+	"IAB3-2": {
+		"id": "393",
+		"name": "Business Services"
+	},
+	"IAB3-3": {
+		"id": "393",
+		"name": "Business Services"
+	},
+	"IAB3-4": {
+		"id": "408",
+		"name": "Office Equipment/Supplies"
+	},
+	"IAB3-5": {
+		"id": "390",
+		"name": "Manufacturing"
+	},
+	"IAB3-6": {
+		"id": "393",
+		"name": "Business Services"
+	},
+	"IAB3-7": {
+		"id": "398",
+		"name": "Government/Municipal"
+	},
+	"IAB3-8": {
+		"id": "393",
+		"name": "Business Services"
+	},
+	"IAB3-9": {
+		"id": "393",
+		"name": "Business Services"
+	},
+	"IAB3-10": {
+		"id": "393",
+		"name": "Business Services"
+	},
+	"IAB3-11": {
+		"id": "393",
+		"name": "Business Services"
+	},
+	"IAB3-12": {
+		"id": "393",
+		"name": "Business Services"
+	},
+	"IAB4-1": {
+		"id": "393",
+		"name": "Business Services"
+	},
+	"IAB4-2": {
+		"id": "405",
+		"name": "Educational Services"
+	},
+	"IAB4-3": {
+		"id": "405",
+		"name": "Educational Services"
+	},
+	"IAB4-4": {
+		"id": "393",
+		"name": "Business Services"
+	},
+	"IAB4-5": {
+		"id": "393",
+		"name": "Business Services"
+	},
+	"IAB4-6": {
+		"id": "393",
+		"name": "Business Services"
+	},
+	"IAB4-7": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB4-8": {
+		"id": "405",
+		"name": "Educational Services"
+	},
+	"IAB4-9": {
+		"id": "417",
+		"name": "Telecommunications"
+	},
+	"IAB4-10": {
+		"id": "429",
+		"name": "Military"
+	},
+	"IAB4-11": {
+		"id": "393",
+		"name": "Business Services"
+	},
+	"IAB5-1": {
+		"id": "405",
+		"name": "Educational Services"
+	},
+	"IAB5-2": {
+		"id": "405",
+		"name": "Educational Services"
+	},
+	"IAB5-3": {
+		"id": "405",
+		"name": "Educational Services"
+	},
+	"IAB5-4": {
+		"id": "405",
+		"name": "Educational Services"
+	},
+	"IAB5-5": {
+		"id": "405",
+		"name": "Educational Services"
+	},
+	"IAB5-6": {
+		"id": "405",
+		"name": "Educational Services"
+	},
+	"IAB5-7": {
+		"id": "405",
+		"name": "Educational Services"
+	},
+	"IAB5-8": {
+		"id": "405",
+		"name": "Educational Services"
+	},
+	"IAB5-9": {
+		"id": "405",
+		"name": "Educational Services"
+	},
+	"IAB5-10": {
+		"id": "405",
+		"name": "Educational Services"
+	},
+	"IAB5-11": {
+		"id": "405",
+		"name": "Educational Services"
+	},
+	"IAB5-12": {
+		"id": "405",
+		"name": "Educational Services"
+	},
+	"IAB5-13": {
+		"id": "405",
+		"name": "Educational Services"
+	},
+	"IAB5-14": {
+		"id": "405",
+		"name": "Educational Services"
+	},
+	"IAB5-15": {
+		"id": "405",
+		"name": "Educational Services"
+	},
+	"IAB7-1": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-2": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-3": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-4": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-5": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-6": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-7": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-8": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-9": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-10": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-11": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-12": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-13": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-14": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-15": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-16": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-17": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-18": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-19": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-20": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-21": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-22": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-23": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-24": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-25": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-26": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-27": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-28": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-29": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-30": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-31": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-32": {
+		"id": "402",
+		"name": "Pharmaceuticals"
+	},
+	"IAB7-33": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-34": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-35": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-36": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-37": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-38": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-39": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-40": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-41": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-42": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-43": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB7-44": {
+		"id": "433",
+		"name": "Drug Stores"
+	},
+	"IAB7-45": {
+		"id": "406",
+		"name": "Health Care Services"
+	},
+	"IAB8-1": {
+		"id": "394",
+		"name": "Food"
+	},
+	"IAB8-2": {
+		"id": "394",
+		"name": "Food"
+	},
+	"IAB8-3": {
+		"id": "394",
+		"name": "Food"
+	},
+	"IAB8-4": {
+		"id": "394",
+		"name": "Food"
+	},
+	"IAB8-5": {
+		"id": "400",
+		"name": "Beer/Wine/Liquor"
+	},
+	"IAB8-6": {
+		"id": "401",
+		"name": "Beverages"
+	},
+	"IAB8-7": {
+		"id": "394",
+		"name": "Food"
+	},
+	"IAB8-8": {
+		"id": "394",
+		"name": "Food"
+	},
+	"IAB8-9": {
+		"id": "407",
+		"name": "Restaurant/Fast Food"
+	},
+	"IAB8-10": {
+		"id": "394",
+		"name": "Food"
+	},
+	"IAB8-11": {
+		"id": "394",
+		"name": "Food"
+	},
+	"IAB8-12": {
+		"id": "394",
+		"name": "Food"
+	},
+	"IAB8-13": {
+		"id": "394",
+		"name": "Food"
+	},
+	"IAB8-14": {
+		"id": "394",
+		"name": "Food"
+	},
+	"IAB8-15": {
+		"id": "394",
+		"name": "Food"
+	},
+	"IAB8-16": {
+		"id": "394",
+		"name": "Food"
+	},
+	"IAB8-17": {
+		"id": "394",
+		"name": "Food"
+	},
+	"IAB8-18": {
+		"id": "400",
+		"name": "Beer/Wine/Liquor"
+	},
+	"IAB9-1": {
+		"id": "392",
+		"name": "Entertainment"
+	},
+	"IAB9-3": {
+		"id": "418",
+		"name": "Jewelry"
+	},
+	"IAB9-5": {
+		"id": "414",
+		"name": "Gambling"
+	},
+	"IAB9-6": {
+		"id": "412",
+		"name": "Household Products"
+	},
+	"IAB9-7": {
+		"id": "413",
+		"name": "Gaming"
+	},
+	"IAB9-9": {
+		"id": "426",
+		"name": "Tobacco"
+	},
+	"IAB9-11": {
+		"id": "404",
+		"name": "Publishing"
+	},
+	"IAB9-15": {
+		"id": "404",
+		"name": "Publishing"
+	},
+	"IAB9-16": {
+		"id": "392",
+		"name": "Entertainment"
+	},
+	"IAB9-18": {
+		"id": "393",
+		"name": "Business Services"
+	},
+	"IAB9-19": {
+		"id": "418",
+		"name": "Jewelry"
+	},
+	"IAB9-23": {
+		"id": "424",
+		"name": "Photographic Equipment"
+	},
+	"IAB9-24": {
+		"id": "392",
+		"name": "Entertainment"
+	},
+	"IAB9-25": {
+		"id": "392",
+		"name": "Entertainment"
+	},
+	"IAB9-30": {
+		"id": "427",
+		"name": "Toys/Games"
+	},
+	"IAB10-1": {
+		"id": "415",
+		"name": "Appliances"
+	},
+	"IAB10-5": {
+		"id": "434",
+		"name": "Home Furnishings"
+	},
+	"IAB10-6": {
+		"id": "434",
+		"name": "Home Furnishings"
+	},
+	"IAB10-7": {
+		"id": "434",
+		"name": "Home Furnishings"
+	},
+	"IAB10-8": {
+		"id": "393",
+		"name": "Business Services"
+	},
+	"IAB10-9": {
+		"id": "434",
+		"name": "Home Furnishings"
+	},
+	"IAB11-1": {
+		"id": "398",
+		"name": "Government/Municipal"
+	},
+	"IAB11-2": {
+		"id": "398",
+		"name": "Government/Municipal"
+	},
+	"IAB11-3": {
+		"id": "398",
+		"name": "Government/Municipal"
+	},
+	"IAB11-4": {
+		"id": "398",
+		"name": "Government/Municipal"
+	},
+	"IAB11-5": {
+		"id": "421",
+		"name": "Associations"
+	},
+	"IAB12-1": {
+		"id": "438",
+		"name": "News"
+	},
+	"IAB12-2": {
+		"id": "438",
+		"name": "News"
+	},
+	"IAB12-3": {
+		"id": "438",
+		"name": "News"
+	},
+	"IAB13-1": {
+		"id": "393",
+		"name": "Business Services"
+	},
+	"IAB13-2": {
+		"id": "393",
+		"name": "Business Services"
+	},
+	"IAB13-3": {
+		"id": "438",
+		"name": "News"
+	},
+	"IAB13-4": {
+		"id": "391",
+		"name": "Financial Services"
+	},
+	"IAB13-5": {
+		"id": "393",
+		"name": "Business Services"
+	},
+	"IAB13-6": {
+		"id": "436",
+		"name": "Insurance"
+	},
+	"IAB13-7": {
+		"id": "393",
+		"name": "Business Services"
+	},
+	"IAB13-8": {
+		"id": "393",
+		"name": "Business Services"
+	},
+	"IAB13-9": {
+		"id": "393",
+		"name": "Business Services"
+	},
+	"IAB13-10": {
+		"id": "393",
+		"name": "Business Services"
+	},
+	"IAB13-11": {
+		"id": "393",
+		"name": "Business Services"
+	},
+	"IAB13-12": {
+		"id": "393",
+		"name": "Business Services"
+	},
+	"IAB16-1": {
+		"id": "423",
+		"name": "Pet Food/Supplies"
+	},
+	"IAB16-2": {
+		"id": "423",
+		"name": "Pet Food/Supplies"
+	},
+	"IAB16-3": {
+		"id": "423",
+		"name": "Pet Food/Supplies"
+	},
+	"IAB16-4": {
+		"id": "423",
+		"name": "Pet Food/Supplies"
+	},
+	"IAB16-5": {
+		"id": "423",
+		"name": "Pet Food/Supplies"
+	},
+	"IAB16-6": {
+		"id": "423",
+		"name": "Pet Food/Supplies"
+	},
+	"IAB16-7": {
+		"id": "423",
+		"name": "Pet Food/Supplies"
+	},
+	"IAB17-1": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-2": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-3": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-4": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-5": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-6": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-7": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-8": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-9": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-10": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-11": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-12": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-13": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-14": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-15": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-16": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-17": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-18": {
+		"id": "412",
+		"name": "Household Products"
+	},
+	"IAB17-19": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-20": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-21": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-22": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-23": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-24": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-25": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-26": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-27": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-28": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-29": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-30": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-31": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-32": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-33": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-34": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-35": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-36": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-37": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-38": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-39": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-40": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-41": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-42": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-43": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB17-44": {
+		"id": "425",
+		"name": "Professional Sports"
+	},
+	"IAB18-1": {
+		"id": "411",
+		"name": "Cosmetics/Toiletries"
+	},
+	"IAB18-2": {
+		"id": "397",
+		"name": "Apparel"
+	},
+	"IAB18-3": {
+		"id": "397",
+		"name": "Apparel"
+	},
+	"IAB18-4": {
+		"id": "418",
+		"name": "Jewelry"
+	},
+	"IAB18-5": {
+		"id": "397",
+		"name": "Apparel"
+	},
+	"IAB18-6": {
+		"id": "397",
+		"name": "Apparel"
+	},
+	"IAB19-2": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB19-3": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB19-4": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB19-5": {
+		"id": "424",
+		"name": "Photographic Equipment"
+	},
+	"IAB19-6": {
+		"id": "417",
+		"name": "Telecommunications"
+	},
+	"IAB19-7": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB19-8": {
+		"id": "432",
+		"name": "Audio and Video Equipment"
+	},
+	"IAB19-9": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB19-10": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB19-11": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB19-12": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB19-13": {
+		"id": "404",
+		"name": "Publishing"
+	},
+	"IAB19-14": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB19-15": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB19-16": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB19-17": {
+		"id": "419",
+		"name": "Filmed Entertainment"
+	},
+	"IAB19-18": {
+		"id": "431",
+		"name": "Computing"
+	},
+	"IAB19-19": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB19-20": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB19-21": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB19-22": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB19-23": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB19-24": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB19-25": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB19-26": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB19-27": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB19-28": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB19-29": {
+		"id": "392",
+		"name": "Entertainment"
+	},
+	"IAB19-30": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB19-31": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB19-32": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB19-33": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB19-34": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB19-35": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB19-36": {
+		"id": "409",
+		"name": "Computing Product"
+	},
+	"IAB20-1": {
+		"id": "395",
+		"name": "Travel/Hotels/Airlines"
+	},
+	"IAB20-2": {
+		"id": "395",
+		"name": "Travel/Hotels/Airlines"
+	},
+	"IAB20-3": {
+		"id": "428",
+		"name": "Aerospace"
+	},
+	"IAB20-4": {
+		"id": "395",
+		"name": "Travel/Hotels/Airlines"
+	},
+	"IAB20-5": {
+		"id": "395",
+		"name": "Travel/Hotels/Airlines"
+	},
+	"IAB20-6": {
+		"id": "395",
+		"name": "Travel/Hotels/Airlines"
+	},
+	"IAB20-7": {
+		"id": "395",
+		"name": "Travel/Hotels/Airlines"
+	},
+	"IAB20-8": {
+		"id": "395",
+		"name": "Travel/Hotels/Airlines"
+	},
+	"IAB20-9": {
+		"id": "395",
+		"name": "Travel/Hotels/Airlines"
+	},
+	"IAB20-10": {
+		"id": "395",
+		"name": "Travel/Hotels/Airlines"
+	},
+	"IAB20-11": {
+		"id": "395",
+		"name": "Travel/Hotels/Airlines"
+	},
+	"IAB20-12": {
+		"id": "395",
+		"name": "Travel/Hotels/Airlines"
+	},
+	"IAB20-13": {
+		"id": "395",
+		"name": "Travel/Hotels/Airlines"
+	},
+	"IAB20-14": {
+		"id": "395",
+		"name": "Travel/Hotels/Airlines"
+	},
+	"IAB20-15": {
+		"id": "395",
+		"name": "Travel/Hotels/Airlines"
+	},
+	"IAB20-16": {
+		"id": "395",
+		"name": "Travel/Hotels/Airlines"
+	},
+	"IAB20-17": {
+		"id": "396",
+		"name": "Amusement and Recreation"
+	},
+	"IAB20-18": {
+		"id": "395",
+		"name": "Travel/Hotels/Airlines"
+	},
+	"IAB20-19": {
+		"id": "395",
+		"name": "Travel/Hotels/Airlines"
+	},
+	"IAB20-20": {
+		"id": "395",
+		"name": "Travel/Hotels/Airlines"
+	},
+	"IAB20-21": {
+		"id": "395",
+		"name": "Travel/Hotels/Airlines"
+	},
+	"IAB20-22": {
+		"id": "395",
+		"name": "Travel/Hotels/Airlines"
+	},
+	"IAB20-23": {
+		"id": "395",
+		"name": "Travel/Hotels/Airlines"
+	},
+	"IAB20-24": {
+		"id": "395",
+		"name": "Travel/Hotels/Airlines"
+	},
+	"IAB20-25": {
+		"id": "395",
+		"name": "Travel/Hotels/Airlines"
+	},
+	"IAB20-26": {
+		"id": "395",
+		"name": "Travel/Hotels/Airlines"
+	},
+	"IAB20-27": {
+		"id": "395",
+		"name": "Travel/Hotels/Airlines"
+	},
+	"IAB21-1": {
+		"id": "416",
+		"name": "Real Estate"
+	},
+	"IAB21-2": {
+		"id": "416",
+		"name": "Real Estate"
+	},
+	"IAB21-3": {
+		"id": "416",
+		"name": "Real Estate"
+	},
+	"IAB22-1": {
+		"id": "403",
+		"name": "Retail Stores/Chains"
+	},
+	"IAB22-2": {
+		"id": "403",
+		"name": "Retail Stores/Chains"
+	},
+	"IAB22-3": {
+		"id": "410",
+		"name": "Product"
+	}
 }
\ No newline at end of file
diff --git a/usersync/usersyncers/syncer.go b/usersync/usersyncers/syncer.go
index 751d2aab..1beb9d58 100755
--- a/usersync/usersyncers/syncer.go
+++ b/usersync/usersyncers/syncer.go
@@ -18,6 +18,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/aja"
 	"github.com/prebid/prebid-server/adapters/appnexus"
 	"github.com/prebid/prebid-server/adapters/audienceNetwork"
+	"github.com/prebid/prebid-server/adapters/avocet"
 	"github.com/prebid/prebid-server/adapters/beachfront"
 	"github.com/prebid/prebid-server/adapters/beintoo"
 	"github.com/prebid/prebid-server/adapters/brightroll"
@@ -90,6 +91,7 @@ func NewSyncerMap(cfg *config.Configuration) map[openrtb_ext.BidderName]usersync
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderAdvangelists, advangelists.NewAdvangelistsSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderAJA, aja.NewAJASyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderAppnexus, appnexus.NewAppnexusSyncer)
+	insertIntoMap(cfg, syncers, openrtb_ext.BidderAvocet, avocet.NewAvocetSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderBeachfront, beachfront.NewBeachfrontSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderBeintoo, beintoo.NewBeintooSyncer)
 	insertIntoMap(cfg, syncers, openrtb_ext.BidderBrightroll, brightroll.NewBrightrollSyncer)


Test patch:
diff --git a/adapters/adocean/adoceantest/exemplary/multi-banner-impression.json b/adapters/adocean/adoceantest/exemplary/multi-banner-impression.json
index 007a5306..9e4ce06e 100644
--- a/adapters/adocean/adoceantest/exemplary/multi-banner-impression.json
+++ b/adapters/adocean/adoceantest/exemplary/multi-banner-impression.json
@@ -18,6 +18,9 @@
         "format": [{
           "w": 300,
           "h": 250
+        }, {
+          "w": 320,
+          "h": 600
         }]
       }
     }, {
@@ -68,7 +71,7 @@
   },
   "httpCalls": [{
     "expectedRequest": {
-      "uri": "https://myao.adocean.pl/_10000000/ad.json?aid=adoceanmyaozpniqismex%3Aao-test&aid=adoceanmyaowafpdwlrks%3Asecod-twelve&gdpr=1&gdpr_consent=COwK6gaOwK6gaFmAAAENAPCAAAAAAAAAAAAAAAAAAAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw&id=tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7&nc=1&nosecure=1&pbsrv_v=1.0.0"
+      "uri": "https://myao.adocean.pl/_10000000/ad.json?aid=adoceanmyaozpniqismex%3Aao-test&aid=adoceanmyaowafpdwlrks%3Asecod-twelve&aosspsizes=myaowafpdwlrks~300x250-myaozpniqismex~300x250_320x600&gdpr=1&gdpr_consent=COwK6gaOwK6gaFmAAAENAPCAAAAAAAAAAAAAAAAAAAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw&id=tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7&nc=1&nosecure=1&pbsrv_v=1.1.0"
     },
     "mockResponse": {
       "status": 200,
diff --git a/adapters/adocean/adoceantest/exemplary/single-banner-impression.json b/adapters/adocean/adoceantest/exemplary/single-banner-impression.json
index b938a042..e6d70f84 100644
--- a/adapters/adocean/adoceantest/exemplary/single-banner-impression.json
+++ b/adapters/adocean/adoceantest/exemplary/single-banner-impression.json
@@ -59,7 +59,7 @@
   "httpCalls": [
     {
       "expectedRequest": {
-        "uri": "https://myao.adocean.pl/_10000000/ad.json?aid=adoceanmyaozpniqismex%3Aao-test&gdpr=1&gdpr_consent=COwK6gaOwK6gaFmAAAENAPCAAAAAAAAAAAAAAAAAAAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw&id=tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7&nc=1&nosecure=1&pbsrv_v=1.0.0"
+        "uri": "https://myao.adocean.pl/_10000000/ad.json?aid=adoceanmyaozpniqismex%3Aao-test&aosspsizes=myaozpniqismex~300x250&gdpr=1&gdpr_consent=COwK6gaOwK6gaFmAAAENAPCAAAAAAAAAAAAAAAAAAAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw&id=tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7&nc=1&nosecure=1&pbsrv_v=1.1.0"
       },
       "mockResponse": {
         "status": 200,
diff --git a/adapters/adocean/adoceantest/supplemental/bad-response.json b/adapters/adocean/adoceantest/supplemental/bad-response.json
index 514262d5..e7b871f9 100644
--- a/adapters/adocean/adoceantest/supplemental/bad-response.json
+++ b/adapters/adocean/adoceantest/supplemental/bad-response.json
@@ -49,7 +49,7 @@
   "httpCalls": [
     {
         "expectedRequest": {
-          "uri": "https://myao.adocean.pl/_10000000/ad.json?aid=adoceanmyaozpniqismex%3Aao-test&id=tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7&nc=1&nosecure=1&pbsrv_v=1.0.0"
+          "uri": "https://myao.adocean.pl/_10000000/ad.json?aid=adoceanmyaozpniqismex%3Aao-test&aosspsizes=myaozpniqismex~300x250&id=tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7&nc=1&nosecure=1&pbsrv_v=1.1.0"
         },
       "mockResponse": {
         "status": 200,
diff --git a/adapters/adocean/adoceantest/supplemental/encode-error.json b/adapters/adocean/adoceantest/supplemental/encode-error.json
index 2f775f98..8dfd0f83 100644
--- a/adapters/adocean/adoceantest/supplemental/encode-error.json
+++ b/adapters/adocean/adoceantest/supplemental/encode-error.json
@@ -49,7 +49,7 @@
   "httpCalls": [
     {
         "expectedRequest": {
-          "uri": "https://myao.adocean.pl/_10000000/ad.json?aid=adoceanmyaozpniqismex%3Aao-test&id=tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7&nc=1&nosecure=1&pbsrv_v=1.0.0"
+          "uri": "https://myao.adocean.pl/_10000000/ad.json?aid=adoceanmyaozpniqismex%3Aao-test&aosspsizes=myaozpniqismex~300x250&id=tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7&nc=1&nosecure=1&pbsrv_v=1.1.0"
         },
       "mockResponse": {
         "status": 200,
diff --git a/adapters/adocean/adoceantest/supplemental/network-error.json b/adapters/adocean/adoceantest/supplemental/network-error.json
index 7a5fa8fd..54e528af 100644
--- a/adapters/adocean/adoceantest/supplemental/network-error.json
+++ b/adapters/adocean/adoceantest/supplemental/network-error.json
@@ -49,7 +49,7 @@
   "httpCalls": [
     {
         "expectedRequest": {
-          "uri": "https://myao.adocean.pl/_10000000/ad.json?aid=adoceanmyaozpniqismex%3Aao-test&id=tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7&nc=1&nosecure=1&pbsrv_v=1.0.0"
+          "uri": "https://myao.adocean.pl/_10000000/ad.json?aid=adoceanmyaozpniqismex%3Aao-test&aosspsizes=myaozpniqismex~300x250&id=tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7&nc=1&nosecure=1&pbsrv_v=1.1.0"
         },
       "mockResponse": {
         "status": 500,
diff --git a/adapters/adocean/adoceantest/supplemental/no-bid.json b/adapters/adocean/adoceantest/supplemental/no-bid.json
index ed81bb35..625fb78f 100644
--- a/adapters/adocean/adoceantest/supplemental/no-bid.json
+++ b/adapters/adocean/adoceantest/supplemental/no-bid.json
@@ -83,7 +83,7 @@
   },
   "httpCalls": [{
     "expectedRequest": {
-      "uri": "https://myao.adocean.pl/_10000000/ad.json?aid=adoceanmyaozpniqismex%3Aao-test&aid=adoceanmyaowafpdwlrks%3Aao-test-two&gdpr=1&gdpr_consent=COwK6gaOwK6gaFmAAAENAPCAAAAAAAAAAAAAAAAAAAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw&id=tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7&nc=1&nosecure=1&pbsrv_v=1.0.0"
+      "uri": "https://myao.adocean.pl/_10000000/ad.json?aid=adoceanmyaozpniqismex%3Aao-test&aid=adoceanmyaowafpdwlrks%3Aao-test-two&aosspsizes=myaowafpdwlrks~300x250-myaozpniqismex~300x250&gdpr=1&gdpr_consent=COwK6gaOwK6gaFmAAAENAPCAAAAAAAAAAAAAAAAAAAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw&id=tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7&nc=1&nosecure=1&pbsrv_v=1.1.0"
     },
     "mockResponse": {
       "status": 200,
@@ -108,7 +108,7 @@
     }
   }, {
     "expectedRequest": {
-      "uri": "https://myao.adocean.pl/_10000000/ad.json?aid=adoceanmyaowafpdwlrks%3Aao-test-three&gdpr=1&gdpr_consent=COwK6gaOwK6gaFmAAAENAPCAAAAAAAAAAAAAAAAAAAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw&id=tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7&nc=1&nosecure=1&pbsrv_v=1.0.0"
+      "uri": "https://myao.adocean.pl/_10000000/ad.json?aid=adoceanmyaowafpdwlrks%3Aao-test-three&aosspsizes=myaowafpdwlrks~300x250&gdpr=1&gdpr_consent=COwK6gaOwK6gaFmAAAENAPCAAAAAAAAAAAAAAAAAAAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw&id=tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7&nc=1&nosecure=1&pbsrv_v=1.1.0"
     },
     "mockResponse": {
       "status": 200,
diff --git a/adapters/adocean/adoceantest/supplemental/no-sizes.json b/adapters/adocean/adoceantest/supplemental/no-sizes.json
new file mode 100644
index 00000000..6286d805
--- /dev/null
+++ b/adapters/adocean/adoceantest/supplemental/no-sizes.json
@@ -0,0 +1,168 @@
+{
+  "mockBidRequest": {
+    "id": "b5300274-a7ec-4cdb-bf5b-d75eeb481a6b",
+    "source": {
+      "tid": "b5300274-a7ec-4cdb-bf5b-d75eeb481a6b"
+    },
+    "tmax": 1000,
+    "imp": [{
+      "id": "ao-test",
+      "ext": {
+        "bidder": {
+          "emiter": "myao.adocean.pl",
+          "masterId": "tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7",
+          "slaveId": "adoceanmyaozpniqismex"
+        }
+      }
+    }, {
+      "id": "ao-test-two",
+      "ext": {
+        "bidder": {
+          "emiter": "myao.adocean.pl",
+          "masterId": "tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7",
+          "slaveId": "adoceanmyaowafpdwlrks"
+        }
+      },
+      "banner": {
+        "format": []
+      }
+    }, {
+      "id": "ao-test-three",
+      "ext": {
+        "bidder": {
+          "emiter": "myao.adocean.pl",
+          "masterId": "tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7",
+          "slaveId": "adoceanmyaowafpdwlrks"
+        }
+      },
+      "banner": {
+        "w": 300,
+        "h": 250
+      }
+    }],
+    "test": 1,
+    "ext": {
+      "prebid": {
+        "targeting": {
+          "includewinners": true,
+          "includebidderkeys": false
+        }
+      }
+    },
+    "site": {
+      "publisher": {
+        "id": "1"
+      },
+      "page": "http://localhost/prebid_server/test.html"
+    },
+    "device": {
+      "w": 418,
+      "h": 961
+    },
+    "regs": {
+      "ext": {
+        "gdpr": 1
+      }
+    },
+    "user": {
+      "ext": {
+        "consent": "COwK6gaOwK6gaFmAAAENAPCAAAAAAAAAAAAAAAAAAAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw"
+      }
+    }
+  },
+  "httpCalls": [{
+    "expectedRequest": {
+      "uri": "https://myao.adocean.pl/_10000000/ad.json?aid=adoceanmyaozpniqismex%3Aao-test&aid=adoceanmyaowafpdwlrks%3Aao-test-two&gdpr=1&gdpr_consent=COwK6gaOwK6gaFmAAAENAPCAAAAAAAAAAAAAAAAAAAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw&id=tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7&nc=1&nosecure=1&pbsrv_v=1.1.0"
+    },
+    "mockResponse": {
+      "status": 200,
+      "body": [{
+          "id": "adoceanmyaozpniqismex",
+          "price": "1",
+          "winurl": "https://win-url.com",
+          "statsUrl": "https://stats-url.com",
+          "code": " <!-- code 1 --> ",
+          "currency": "EUR",
+          "minFloorPrice": "0.01",
+          "width": "300",
+          "height": "250",
+          "crid": "0af345b42983cc4bc0",
+          "ttl": "300"
+        },
+        {
+          "id": "adoceanmyaowafpdwlrks",
+          "price": "1",
+          "winurl": "https://win-url2.com",
+          "statsUrl": "https://stats-url2.com",
+          "code": " <!-- code 2 --> ",
+          "currency": "EUR",
+          "minFloorPrice": "0.01",
+          "width": "300",
+          "height": "250",
+          "crid": "0af345b42983cc4bc0",
+          "ttl": "300"
+        }
+      ]
+    }
+  }, {
+    "expectedRequest": {
+      "uri": "https://myao.adocean.pl/_10000000/ad.json?aid=adoceanmyaowafpdwlrks%3Aao-test-three&aosspsizes=myaowafpdwlrks~300x250&gdpr=1&gdpr_consent=COwK6gaOwK6gaFmAAAENAPCAAAAAAAAAAAAAAAAAAAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw&id=tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7&nc=1&nosecure=1&pbsrv_v=1.1.0"
+    },
+    "mockResponse": {
+      "status": 200,
+      "body": [{
+        "id": "adoceanmyaowafpdwlrks",
+        "price": "1",
+        "winurl": "https://win-url3.com",
+        "statsUrl": "https://stats-url3.com",
+        "code": " <!-- code 3 --> ",
+        "currency": "EUR",
+        "minFloorPrice": "0.01",
+        "width": "300",
+        "height": "250",
+        "crid": "0af345b42983cc4bc0",
+        "ttl": "300"
+      }]
+    }
+  }],
+  "expectedBidResponses": [{
+    "currency": "EUR",
+    "bids": [{
+      "bid": {
+        "id": "adoceanmyaozpniqismex",
+        "impid": "ao-test",
+        "price": 1,
+        "adm": " <script> +function() { var wu = \"https://win-url.com\"; var su = \"https://stats-url.com\".replace(/\\[TIMESTAMP\\]/, Date.now()); if (wu && !(navigator.sendBeacon && navigator.sendBeacon(wu))) { (new Image(1,1)).src = wu } if (su && !(navigator.sendBeacon && navigator.sendBeacon(su))) { (new Image(1,1)).src = su } }(); </script>  <!-- code 1 --> ",
+        "crid": "0af345b42983cc4bc0",
+        "w": 300,
+        "h": 250
+      },
+      "type": "banner"
+    }, {
+      "bid": {
+        "id": "adoceanmyaowafpdwlrks",
+        "impid": "ao-test-two",
+        "price": 1,
+        "adm": " <script> +function() { var wu = \"https://win-url2.com\"; var su = \"https://stats-url2.com\".replace(/\\[TIMESTAMP\\]/, Date.now()); if (wu && !(navigator.sendBeacon && navigator.sendBeacon(wu))) { (new Image(1,1)).src = wu } if (su && !(navigator.sendBeacon && navigator.sendBeacon(su))) { (new Image(1,1)).src = su } }(); </script>  <!-- code 2 --> ",
+        "crid": "0af345b42983cc4bc0",
+        "w": 300,
+        "h": 250
+      },
+      "type": "banner"
+    }]
+  }, {
+    "currency": "EUR",
+    "bids": [{
+      "bid": {
+        "id": "adoceanmyaowafpdwlrks",
+        "impid": "ao-test-three",
+        "price": 1,
+        "adm": " <script> +function() { var wu = \"https://win-url3.com\"; var su = \"https://stats-url3.com\".replace(/\\[TIMESTAMP\\]/, Date.now()); if (wu && !(navigator.sendBeacon && navigator.sendBeacon(wu))) { (new Image(1,1)).src = wu } if (su && !(navigator.sendBeacon && navigator.sendBeacon(su))) { (new Image(1,1)).src = su } }(); </script>  <!-- code 3 --> ",
+        "crid": "0af345b42983cc4bc0",
+        "w": 300,
+        "h": 250
+      },
+      "type": "banner"
+    }]
+  }]
+}
diff --git a/adapters/adocean/adoceantest/supplemental/requests-merge.json b/adapters/adocean/adoceantest/supplemental/requests-merge.json
index 9b5eb39a..e0736ec9 100644
--- a/adapters/adocean/adoceantest/supplemental/requests-merge.json
+++ b/adapters/adocean/adoceantest/supplemental/requests-merge.json
@@ -83,7 +83,7 @@
   },
   "httpCalls": [{
     "expectedRequest": {
-      "uri": "https://myao.adocean.pl/_10000000/ad.json?aid=adoceanmyaozpniqismex%3Aao-test&aid=adoceanmyaowafpdwlrks%3Aao-test-two&gdpr=1&gdpr_consent=COwK6gaOwK6gaFmAAAENAPCAAAAAAAAAAAAAAAAAAAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw&id=tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7&nc=1&nosecure=1&pbsrv_v=1.0.0"
+      "uri": "https://myao.adocean.pl/_10000000/ad.json?aid=adoceanmyaozpniqismex%3Aao-test&aid=adoceanmyaowafpdwlrks%3Aao-test-two&aosspsizes=myaowafpdwlrks~300x250-myaozpniqismex~300x250&gdpr=1&gdpr_consent=COwK6gaOwK6gaFmAAAENAPCAAAAAAAAAAAAAAAAAAAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw&id=tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7&nc=1&nosecure=1&pbsrv_v=1.1.0"
     },
     "mockResponse": {
       "status": 200,
@@ -117,7 +117,7 @@
     }
   }, {
     "expectedRequest": {
-      "uri": "https://myao.adocean.pl/_10000000/ad.json?aid=adoceanmyaowafpdwlrks%3Aao-test-three&gdpr=1&gdpr_consent=COwK6gaOwK6gaFmAAAENAPCAAAAAAAAAAAAAAAAAAAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw&id=tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7&nc=1&nosecure=1&pbsrv_v=1.0.0"
+      "uri": "https://myao.adocean.pl/_10000000/ad.json?aid=adoceanmyaowafpdwlrks%3Aao-test-three&aosspsizes=myaowafpdwlrks~300x250&gdpr=1&gdpr_consent=COwK6gaOwK6gaFmAAAENAPCAAAAAAAAAAAAAAAAAAAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw&id=tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7&nc=1&nosecure=1&pbsrv_v=1.1.0"
     },
     "mockResponse": {
       "status": 200,
diff --git a/adapters/avocet/avocet_test.go b/adapters/avocet/avocet_test.go
new file mode 100644
index 00000000..ff2159bf
--- /dev/null
+++ b/adapters/avocet/avocet_test.go
@@ -0,0 +1,301 @@
+package avocet
+
+import (
+	"encoding/json"
+	"net/http"
+	"reflect"
+	"testing"
+
+	"github.com/mxmCherry/openrtb"
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/adapters/adapterstest"
+	"github.com/prebid/prebid-server/errortypes"
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+func TestJsonSamples(t *testing.T) {
+	adapterstest.RunJSONBidderTest(t, "avocet", NewAvocetAdapter("https://bid.staging.avct.cloud/ortb/bid/5e722ee9bd6df11d063a8013"))
+}
+
+func TestAvocetAdapter_MakeRequests(t *testing.T) {
+	type fields struct {
+		Endpoint string
+	}
+	type args struct {
+		request *openrtb.BidRequest
+		reqInfo *adapters.ExtraRequestInfo
+	}
+	type reqData []*adapters.RequestData
+	tests := []struct {
+		name     string
+		fields   fields
+		args     args
+		want     []*adapters.RequestData
+		wantErrs []error
+	}{
+		{
+			name:   "return nil if zero imps",
+			fields: fields{Endpoint: "https://bid.avct.cloud"},
+			args: args{
+				&openrtb.BidRequest{},
+				nil,
+			},
+			want:     nil,
+			wantErrs: nil,
+		},
+		{
+			name:   "makes POST request with JSON content",
+			fields: fields{Endpoint: "https://bid.avct.cloud"},
+			args: args{
+				&openrtb.BidRequest{Imp: []openrtb.Imp{{}}},
+				nil,
+			},
+			want: reqData{
+				&adapters.RequestData{
+					Method: http.MethodPost,
+					Uri:    "https://bid.avct.cloud",
+					Body:   []byte(`{"id":"","imp":[{"id":""}]}`),
+					Headers: map[string][]string{
+						"Accept":       {"application/json"},
+						"Content-Type": {"application/json;charset=utf-8"},
+					},
+				},
+			},
+			wantErrs: nil,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			a := &AvocetAdapter{
+				Endpoint: tt.fields.Endpoint,
+			}
+			got, got1 := a.MakeRequests(tt.args.request, tt.args.reqInfo)
+			if len(got) != len(tt.want) {
+				t.Errorf("AvocetAdapter.MakeRequests() got %v requests, wanted %v requests", len(got), len(tt.want))
+			}
+			if len(got) == len(tt.want) {
+				for i := range tt.want {
+					if !reflect.DeepEqual(got[i], tt.want[i]) {
+						t.Errorf("AvocetAdapter.MakeRequests() got = %v, want %v", got[i], tt.want[i])
+					}
+				}
+			}
+			if !reflect.DeepEqual(got1, tt.wantErrs) {
+				t.Errorf("AvocetAdapter.MakeRequests() got1 = %v, want %v", got1, tt.wantErrs)
+			}
+		})
+	}
+}
+
+func TestAvocetAdapter_MakeBids(t *testing.T) {
+	type fields struct {
+		Endpoint string
+	}
+	type args struct {
+		internalRequest *openrtb.BidRequest
+		externalRequest *adapters.RequestData
+		response        *adapters.ResponseData
+	}
+	tests := []struct {
+		name   string
+		fields fields
+		args   args
+		want   *adapters.BidderResponse
+		errs   []error
+	}{
+		{
+			name:   "204 No Content indicates no bids",
+			fields: fields{Endpoint: "https://bid.avct.cloud"},
+			args: args{
+				nil,
+				nil,
+				&adapters.ResponseData{StatusCode: http.StatusNoContent},
+			},
+			want: nil,
+			errs: nil,
+		},
+		{
+			name:   "Non-200 return error",
+			fields: fields{Endpoint: "https://bid.avct.cloud"},
+			args: args{
+				nil,
+				nil,
+				&adapters.ResponseData{StatusCode: http.StatusBadRequest, Body: []byte("message")},
+			},
+			want: nil,
+			errs: []error{&errortypes.BadServerResponse{Message: "received status code: 400 error: message"}},
+		},
+		{
+			name:   "200 response containing banner bids",
+			fields: fields{Endpoint: "https://bid.avct.cloud"},
+			args: args{
+				nil,
+				nil,
+				&adapters.ResponseData{StatusCode: http.StatusOK, Body: validBannerBidResponseBody},
+			},
+			want: &adapters.BidderResponse{
+				Currency: "USD",
+				Bids: []*adapters.TypedBid{
+					{
+						Bid:     &validBannerBid,
+						BidType: openrtb_ext.BidTypeBanner,
+					},
+				},
+			},
+			errs: nil,
+		},
+		{
+			name:   "200 response containing video bids",
+			fields: fields{Endpoint: "https://bid.avct.cloud"},
+			args: args{
+				nil,
+				nil,
+				&adapters.ResponseData{StatusCode: http.StatusOK, Body: validVideoBidResponseBody},
+			},
+			want: &adapters.BidderResponse{
+				Currency: "USD",
+				Bids: []*adapters.TypedBid{
+					{
+						Bid:     &validVideoBid,
+						BidType: openrtb_ext.BidTypeVideo,
+						BidVideo: &openrtb_ext.ExtBidPrebidVideo{
+							Duration: 30,
+						},
+					},
+				},
+			},
+			errs: nil,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			a := &AvocetAdapter{
+				Endpoint: tt.fields.Endpoint,
+			}
+			got, got1 := a.MakeBids(tt.args.internalRequest, tt.args.externalRequest, tt.args.response)
+			if !reflect.DeepEqual(got, tt.want) {
+				gotb, _ := json.Marshal(got)
+				wantb, _ := json.Marshal(tt.want)
+				t.Errorf("AvocetAdapter.MakeBids() got = %s, want %s", string(gotb), string(wantb))
+			}
+			if !reflect.DeepEqual(got1, tt.errs) {
+				t.Errorf("AvocetAdapter.MakeBids() got1 = %v, want %v", got1, tt.errs)
+			}
+		})
+	}
+}
+
+func Test_getBidType(t *testing.T) {
+	type args struct {
+		bid openrtb.Bid
+		ext avocetBidExt
+	}
+	tests := []struct {
+		name string
+		args args
+		want openrtb_ext.BidType
+	}{
+		{
+			name: "VPAID 1.0",
+			args: args{openrtb.Bid{API: openrtb.APIFrameworkVPAID10}, avocetBidExt{}},
+			want: openrtb_ext.BidTypeVideo,
+		},
+		{
+			name: "VPAID 2.0",
+			args: args{openrtb.Bid{API: openrtb.APIFrameworkVPAID20}, avocetBidExt{}},
+			want: openrtb_ext.BidTypeVideo,
+		},
+		{
+			name: "other",
+			args: args{openrtb.Bid{}, avocetBidExt{}},
+			want: openrtb_ext.BidTypeBanner,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if got := getBidType(tt.args.bid, tt.args.ext); !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("getBidType() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+var validBannerBid = openrtb.Bid{
+	AdM:      "<iframe src=\"http://ads.staging.avct.cloud/sv?pp=${AUCTION_PRICE}&uuid=0df2c449-6d85-4179-b5d5-37f2f91caa24&ty=h&crid=5b51e49634f2021f127ff7c9&tacid=5b51e4ed89654741306813a8&aid=749d36d7-c993-455f-aefd-ffd8a7e3ccf_0&accid=5b51dd1634f2021f127ff7c0&brid=5b51e20f34f2021f127ff7c4&ioid=5b51e22089654741306813a1&caid=5b51e2d689654741306813a4&it=1&iobsid=496e8cff35b2c0110029534d&ext_aid=749d36d7-c993-455f-aefd-ffd8a7e3ccf_0&bp=15.64434783&bt=1591874537316649768&h=250&w=300&vpr=0&vdp=0&domain=example.com&gco=54510b3b816269000061a0f7&stid=542d2c1615e3c013de53a6e2&glat=0&glong=0&bip4=3232238090&ext_siid=5ea89200c865f911007f1b0e&ext_pid=1&ext_sid=5ea84df8c865f911007f1ade&ext_plid=5ea9601ac865f911007f1b6a&optv=latest:latest&invsrc=5e722ee9bd6df11d063a8013&ug=0d&ca=0&biid=requestd-54644474bf-l7gx4|eu-central-1-staging&reg=eu-central-1&ck=1_5d99a849\" height=\"250\" width=\"300\" marginwidth=0 marginheight=0 hspace=0 vspace=0 frameborder=0 scrolling=\"no\"></iframe>",
+	ADomain:  []string{"avocet.io"},
+	CID:      "5b51e2d689654741306813a4",
+	CrID:     "5b51e49634f2021f127ff7c9",
+	H:        250,
+	ID:       "bc708396-9202-437b-b726-08b9864cb8b8",
+	ImpID:    "test-imp-id",
+	IURL:     "https://cdn.staging.avocet.io/snapshots/5b51dd1634f2021f127ff7c0/5b51e49634f2021f127ff7c9.jpeg",
+	Language: "en",
+	Price:    15.64434783,
+	W:        300,
+}
+
+var validBannerBidResponseBody = []byte(`{
+	"bidid": "dd87f80c-16a0-43c8-a673-b94b3ea4d417",
+	"id": "test-request-id",
+	"seatbid": [
+		{
+			"bid": [
+				{
+					"adm": "<iframe src=\"http://ads.staging.avct.cloud/sv?pp=${AUCTION_PRICE}&uuid=0df2c449-6d85-4179-b5d5-37f2f91caa24&ty=h&crid=5b51e49634f2021f127ff7c9&tacid=5b51e4ed89654741306813a8&aid=749d36d7-c993-455f-aefd-ffd8a7e3ccf_0&accid=5b51dd1634f2021f127ff7c0&brid=5b51e20f34f2021f127ff7c4&ioid=5b51e22089654741306813a1&caid=5b51e2d689654741306813a4&it=1&iobsid=496e8cff35b2c0110029534d&ext_aid=749d36d7-c993-455f-aefd-ffd8a7e3ccf_0&bp=15.64434783&bt=1591874537316649768&h=250&w=300&vpr=0&vdp=0&domain=example.com&gco=54510b3b816269000061a0f7&stid=542d2c1615e3c013de53a6e2&glat=0&glong=0&bip4=3232238090&ext_siid=5ea89200c865f911007f1b0e&ext_pid=1&ext_sid=5ea84df8c865f911007f1ade&ext_plid=5ea9601ac865f911007f1b6a&optv=latest:latest&invsrc=5e722ee9bd6df11d063a8013&ug=0d&ca=0&biid=requestd-54644474bf-l7gx4|eu-central-1-staging&reg=eu-central-1&ck=1_5d99a849\" height=\"250\" width=\"300\" marginwidth=0 marginheight=0 hspace=0 vspace=0 frameborder=0 scrolling=\"no\"></iframe>",
+					"adomain": ["avocet.io"],
+					"cid": "5b51e2d689654741306813a4",
+					"crid": "5b51e49634f2021f127ff7c9",
+					"h": 250,
+					"id": "bc708396-9202-437b-b726-08b9864cb8b8",
+					"impid": "test-imp-id",
+					"iurl": "https://cdn.staging.avocet.io/snapshots/5b51dd1634f2021f127ff7c0/5b51e49634f2021f127ff7c9.jpeg",
+					"language": "en",
+					"price": 15.64434783,
+					"w": 300
+				}
+			],
+			"seat": "TEST_SEAT_ID"
+		}
+	]
+}`)
+
+var validVideoBid = openrtb.Bid{
+	AdM:      "<VAST version=\"3.0\"><Ad id=\"5ec530e32d57fe1100f17d87\"><Wrapper><AdSystem>Avocet</AdSystem><VASTAdTagURI><![CDATA[http://ads.staging.avct.cloud/vast?x=1&uuid=0df2c449-6d85-4179-b5d5-37f2f91caa24&ty=h&crid=5ec530e32d57fe1100f17d87&tacid=5ec531d32d57fe1100f17d89&aid=749d36d7-c993-455f-aefd-ffd8a7e3ccf_0&accid=5b51dd1634f2021f127ff7c0&brid=5b51e20f34f2021f127ff7c4&ioid=5b51e22089654741306813a1&caid=5b51e2d689654741306813a4&it=2&iobsid=496e8cff35b2c0110029534d&ext_aid=749d36d7-c993-455f-aefd-ffd8a7e3ccf_0&bp=15.64434783&bt=1591875033134290518&h=396&w=600&vpr=0&vdp=0&domain=example.com&gco=54510b3b816269000061a0f7&stid=542d2c1615e3c013de53a6e2&glat=0&glong=0&bip4=3232238090&ext_siid=5ea89200c865f911007f1b0e&ext_pid=1&ext_sid=5ea84df8c865f911007f1ade&ext_plid=5ea9601ac865f911007f1b6a&optv=latest:latest&invsrc=5e722ee9bd6df11d063a8013&ug=0d&ca=0&biid=requestd-54644474bf-l7gx4|eu-central-1-staging&reg=eu-central-1&pixel=1&ck=1_c343bf14]]></VASTAdTagURI><Impression><![CDATA[http://ads.staging.avct.cloud/sv?pp=${AUCTION_PRICE}&uuid=0df2c449-6d85-4179-b5d5-37f2f91caa24&ty=h&crid=5ec530e32d57fe1100f17d87&tacid=5ec531d32d57fe1100f17d89&aid=749d36d7-c993-455f-aefd-ffd8a7e3ccf_0&accid=5b51dd1634f2021f127ff7c0&brid=5b51e20f34f2021f127ff7c4&ioid=5b51e22089654741306813a1&caid=5b51e2d689654741306813a4&it=2&iobsid=496e8cff35b2c0110029534d&ext_aid=749d36d7-c993-455f-aefd-ffd8a7e3ccf_0&bp=15.64434783&bt=1591875033134290518&h=396&w=600&vpr=0&vdp=0&domain=example.com&gco=54510b3b816269000061a0f7&stid=542d2c1615e3c013de53a6e2&glat=0&glong=0&bip4=3232238090&ext_siid=5ea89200c865f911007f1b0e&ext_pid=1&ext_sid=5ea84df8c865f911007f1ade&ext_plid=5ea9601ac865f911007f1b6a&optv=latest:latest&invsrc=5e722ee9bd6df11d063a8013&ug=0d&ca=0&biid=requestd-54644474bf-l7gx4|eu-central-1-staging&reg=eu-central-1&pixel=1&ck=1_c343bf14]]></Impression><Creatives><Creative AdId=\"5ec530e32d57fe1100f17d87\"><Linear><TrackingEvents></TrackingEvents><VideoClicks></VideoClicks></Linear></Creative></Creatives></Wrapper></Ad></VAST>",
+	ADomain:  []string{"avocet.io"},
+	CID:      "5b51e2d689654741306813a4",
+	CrID:     "5ec530e32d57fe1100f17d87",
+	H:        396,
+	ID:       "3d4c2d45-5a8c-43b8-9e15-4f48ac45204f",
+	ImpID:    "dfp-ad--top-above-nav",
+	IURL:     "https://cdn.staging.avocet.io/snapshots/5b51dd1634f2021f127ff7c0/5ec530e32d57fe1100f17d87.jpeg",
+	Language: "en",
+	Price:    15.64434783,
+	W:        600,
+	Ext:      []byte(`{"avocet":{"duration":30}}`),
+}
+
+var validVideoBidResponseBody = []byte(`{
+	"bidid": "dd87f80c-16a0-43c8-a673-b94b3ea4d417",
+	"id": "test-request-id",
+	"seatbid": [
+		{
+			"bid": [
+				{
+					"adm": "<VAST version=\"3.0\"><Ad id=\"5ec530e32d57fe1100f17d87\"><Wrapper><AdSystem>Avocet</AdSystem><VASTAdTagURI><![CDATA[http://ads.staging.avct.cloud/vast?x=1&uuid=0df2c449-6d85-4179-b5d5-37f2f91caa24&ty=h&crid=5ec530e32d57fe1100f17d87&tacid=5ec531d32d57fe1100f17d89&aid=749d36d7-c993-455f-aefd-ffd8a7e3ccf_0&accid=5b51dd1634f2021f127ff7c0&brid=5b51e20f34f2021f127ff7c4&ioid=5b51e22089654741306813a1&caid=5b51e2d689654741306813a4&it=2&iobsid=496e8cff35b2c0110029534d&ext_aid=749d36d7-c993-455f-aefd-ffd8a7e3ccf_0&bp=15.64434783&bt=1591875033134290518&h=396&w=600&vpr=0&vdp=0&domain=example.com&gco=54510b3b816269000061a0f7&stid=542d2c1615e3c013de53a6e2&glat=0&glong=0&bip4=3232238090&ext_siid=5ea89200c865f911007f1b0e&ext_pid=1&ext_sid=5ea84df8c865f911007f1ade&ext_plid=5ea9601ac865f911007f1b6a&optv=latest:latest&invsrc=5e722ee9bd6df11d063a8013&ug=0d&ca=0&biid=requestd-54644474bf-l7gx4|eu-central-1-staging&reg=eu-central-1&pixel=1&ck=1_c343bf14]]></VASTAdTagURI><Impression><![CDATA[http://ads.staging.avct.cloud/sv?pp=${AUCTION_PRICE}&uuid=0df2c449-6d85-4179-b5d5-37f2f91caa24&ty=h&crid=5ec530e32d57fe1100f17d87&tacid=5ec531d32d57fe1100f17d89&aid=749d36d7-c993-455f-aefd-ffd8a7e3ccf_0&accid=5b51dd1634f2021f127ff7c0&brid=5b51e20f34f2021f127ff7c4&ioid=5b51e22089654741306813a1&caid=5b51e2d689654741306813a4&it=2&iobsid=496e8cff35b2c0110029534d&ext_aid=749d36d7-c993-455f-aefd-ffd8a7e3ccf_0&bp=15.64434783&bt=1591875033134290518&h=396&w=600&vpr=0&vdp=0&domain=example.com&gco=54510b3b816269000061a0f7&stid=542d2c1615e3c013de53a6e2&glat=0&glong=0&bip4=3232238090&ext_siid=5ea89200c865f911007f1b0e&ext_pid=1&ext_sid=5ea84df8c865f911007f1ade&ext_plid=5ea9601ac865f911007f1b6a&optv=latest:latest&invsrc=5e722ee9bd6df11d063a8013&ug=0d&ca=0&biid=requestd-54644474bf-l7gx4|eu-central-1-staging&reg=eu-central-1&pixel=1&ck=1_c343bf14]]></Impression><Creatives><Creative AdId=\"5ec530e32d57fe1100f17d87\"><Linear><TrackingEvents></TrackingEvents><VideoClicks></VideoClicks></Linear></Creative></Creatives></Wrapper></Ad></VAST>",
+					"adomain": ["avocet.io"],
+					"cid": "5b51e2d689654741306813a4",
+					"crid": "5ec530e32d57fe1100f17d87",
+					"h": 396,
+					"id": "3d4c2d45-5a8c-43b8-9e15-4f48ac45204f",
+					"impid": "dfp-ad--top-above-nav",
+					"iurl": "https://cdn.staging.avocet.io/snapshots/5b51dd1634f2021f127ff7c0/5ec530e32d57fe1100f17d87.jpeg",
+					"language": "en",
+					"price": 15.64434783,
+					"w": 600,
+					"ext": {"avocet":{"duration":30}}
+				}
+			],
+			"seat": "TEST_SEAT_ID"
+		}
+	]
+}`)
diff --git a/adapters/avocet/usersync_test.go b/adapters/avocet/usersync_test.go
new file mode 100644
index 00000000..8fba403f
--- /dev/null
+++ b/adapters/avocet/usersync_test.go
@@ -0,0 +1,35 @@
+package avocet
+
+import (
+	"testing"
+	"text/template"
+
+	"github.com/prebid/prebid-server/privacy"
+	"github.com/prebid/prebid-server/privacy/ccpa"
+	"github.com/prebid/prebid-server/privacy/gdpr"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestAvocetSyncer(t *testing.T) {
+	syncURL := "https://ads.avct.cloud/getuid?&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&url=%2Fsetuid%3Fbidder%3Davocet%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7B%7BUUID%7D%7D"
+	syncURLTemplate := template.Must(
+		template.New("sync-template").Parse(syncURL),
+	)
+
+	syncer := NewAvocetSyncer(syncURLTemplate)
+	syncInfo, err := syncer.GetUsersyncInfo(privacy.Policies{
+		GDPR: gdpr.Policy{
+			Signal:  "1",
+			Consent: "ConsentString",
+		},
+		CCPA: ccpa.Policy{
+			Value: "PrivacyString",
+		},
+	})
+
+	assert.NoError(t, err)
+	assert.Equal(t, "https://ads.avct.cloud/getuid?&gdpr=1&gdpr_consent=ConsentString&us_privacy=PrivacyString&url=%2Fsetuid%3Fbidder%3Davocet%26gdpr%3D1%26gdpr_consent%3DConsentString%26uid%3D%7B%7BUUID%7D%7D", syncInfo.URL)
+	assert.Equal(t, "redirect", syncInfo.Type)
+	assert.EqualValues(t, 63, syncer.GDPRVendorID())
+	assert.Equal(t, false, syncInfo.SupportCORS)
+}
diff --git a/exchange/bidder_test.go b/exchange/bidder_test.go
index fa04e6a4..fff397f0 100644
--- a/exchange/bidder_test.go
+++ b/exchange/bidder_test.go
@@ -1229,6 +1229,64 @@ func TestSetAssetTypes(t *testing.T) {
 	}
 }
 
+func TestTimeoutNotificationOff(t *testing.T) {
+	respBody := "{\"bid\":false}"
+	respStatus := 200
+	server := httptest.NewServer(mockHandler(respStatus, "getBody", respBody))
+	defer server.Close()
+
+	bidderImpl := &notifingBidder{
+		notiRequest: adapters.RequestData{
+			Method:  "GET",
+			Uri:     server.URL + "/notify/me",
+			Body:    nil,
+			Headers: http.Header{},
+		},
+	}
+	bidder := &bidderAdapter{
+		Bidder:      bidderImpl,
+		Client:      server.Client(),
+		DebugConfig: config.Debug{},
+		me:          &metricsConfig.DummyMetricsEngine{},
+	}
+	if tb, ok := bidder.Bidder.(adapters.TimeoutBidder); !ok {
+		t.Error("Failed to cast bidder to a TimeoutBidder")
+	} else {
+		bidder.doTimeoutNotification(tb, &adapters.RequestData{})
+	}
+}
+
+func TestTimeoutNotificationOn(t *testing.T) {
+	respBody := "{\"bid\":false}"
+	respStatus := 200
+	server := httptest.NewServer(mockHandler(respStatus, "getBody", respBody))
+	defer server.Close()
+
+	bidderImpl := &notifingBidder{
+		notiRequest: adapters.RequestData{
+			Method:  "GET",
+			Uri:     server.URL + "/notify/me",
+			Body:    nil,
+			Headers: http.Header{},
+		},
+	}
+	bidder := &bidderAdapter{
+		Bidder: bidderImpl,
+		Client: server.Client(),
+		DebugConfig: config.Debug{
+			TimeoutNotification: config.TimeoutNotification{
+				Log: true,
+			},
+		},
+		me: &metricsConfig.DummyMetricsEngine{},
+	}
+	if tb, ok := bidder.Bidder.(adapters.TimeoutBidder); !ok {
+		t.Error("Failed to cast bidder to a TimeoutBidder")
+	} else {
+		bidder.doTimeoutNotification(tb, &adapters.RequestData{})
+	}
+}
+
 type goodSingleBidder struct {
 	bidRequest   *openrtb.BidRequest
 	httpRequest  *adapters.RequestData
@@ -1302,3 +1360,19 @@ func (bidder *bidRejector) MakeBids(internalRequest *openrtb.BidRequest, externa
 	bidder.httpResponse = response
 	return nil, []error{errors.New("Can't make a response.")}
 }
+
+type notifingBidder struct {
+	notiRequest adapters.RequestData
+}
+
+func (bidder *notifingBidder) MakeRequests(request *openrtb.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
+	return nil, nil
+}
+
+func (bidder *notifingBidder) MakeBids(internalRequest *openrtb.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+	return nil, nil
+}
+
+func (bidder *notifingBidder) MakeTimeoutNotification(req *adapters.RequestData) (*adapters.RequestData, []error) {
+	return &bidder.notiRequest, nil
+}
diff --git a/exchange/exchange_test.go b/exchange/exchange_test.go
index 4f329962..93cb60fb 100644
--- a/exchange/exchange_test.go
+++ b/exchange/exchange_test.go
@@ -582,7 +582,15 @@ func TestPanicRecovery(t *testing.T) {
 	panicker := func(aName openrtb_ext.BidderName, coreBidder openrtb_ext.BidderName, request *openrtb.BidRequest, bidlabels *pbsmetrics.AdapterLabels, conversions currencies.Conversions) {
 		panic("panic!")
 	}
-	recovered := e.recoverSafely(panicker, chBids)
+	cleanReqs := map[openrtb_ext.BidderName]*openrtb.BidRequest{
+		"bidder1": {
+			ID: "b-1",
+		},
+		"bidder2": {
+			ID: "b-2",
+		},
+	}
+	recovered := e.recoverSafely(cleanReqs, panicker, chBids)
 	apnLabels := pbsmetrics.AdapterLabels{
 		Source:      pbsmetrics.DemandWeb,
 		RType:       pbsmetrics.ReqTypeORTB2Web,
diff --git a/usersync/usersyncers/syncer_test.go b/usersync/usersyncers/syncer_test.go
index c9ef382f..69751dd5 100755
--- a/usersync/usersyncers/syncer_test.go
+++ b/usersync/usersyncers/syncer_test.go
@@ -26,6 +26,7 @@ func TestNewSyncerMap(t *testing.T) {
 			string(openrtb_ext.BidderAdvangelists):     syncConfig,
 			string(openrtb_ext.BidderAJA):              syncConfig,
 			string(openrtb_ext.BidderAppnexus):         syncConfig,
+			string(openrtb_ext.BidderAvocet):           syncConfig,
 			string(openrtb_ext.BidderBeachfront):       syncConfig,
 			string(openrtb_ext.BidderBeintoo):          syncConfig,
 			string(openrtb_ext.BidderBrightroll):       syncConfig,