Repository: prebid/prebid-server
Pull request #1354 (2020-06-12 13:19:19)

Adds Avocet adapter
This adds an adapter for Avocet. The adapter is disabled by default as each integration requires a specific endpoint.

Thanks in advance for your time.


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/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 56b6a1ba..01de9b1a 100755
--- a/config/config.go
+++ b/config/config.go
@@ -49,6 +49,7 @@ type Configuration struct {
 	AMPTimeoutAdjustment int64              `mapstructure:"amp_timeout_adjustment_ms"`
 	GDPR                 GDPR               `mapstructure:"gdpr"`
 	CCPA                 CCPA               `mapstructure:"ccpa"`
+	LMT                  LMT                `mapstructure:"lmt"`
 	CurrencyConverter    CurrencyConverter  `mapstructure:"currency_converter"`
 	DefReqConfig         DefReqConfig       `mapstructure:"default_request"`
 
@@ -139,6 +140,13 @@ func (cfg *AuctionTimeouts) LimitAuctionTimeout(requested time.Duration) time.Du
 	return requested
 }
 
+// Privacy is a grouping of privacy related configs to assist in dependency injection.
+type Privacy struct {
+	CCPA CCPA
+	GDPR GDPR
+	LMT  LMT
+}
+
 type GDPR struct {
 	HostVendorID            int          `mapstructure:"host_vendor_id"`
 	UsersyncIfAmbiguous     bool         `mapstructure:"usersync_if_ambiguous"`
@@ -193,6 +201,10 @@ type CCPA struct {
 	Enforce bool `mapstructure:"enforce"`
 }
 
+type LMT struct {
+	Enforce bool `mapstructure:"enforce"`
+}
+
 type Analytics struct {
 	File FileLogs `mapstructure:"file"`
 }
@@ -555,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")
@@ -760,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")
@@ -836,6 +850,7 @@ func SetupViper(v *viper.Viper, filename string) {
 	v.SetDefault("gdpr.tcf2.purpose_one_treatement.access_allowed", true)
 	v.SetDefault("gdpr.amp_exception", false)
 	v.SetDefault("ccpa.enforce", false)
+	v.SetDefault("lmt.enforce", true)
 	v.SetDefault("currency_converter.fetch_url", "https://cdn.jsdelivr.net/gh/prebid/currency-file@1/latest.json")
 	v.SetDefault("currency_converter.fetch_interval_seconds", 1800) // fetch currency rates every 30 minutes
 	v.SetDefault("default_request.type", "")
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/endpoints/openrtb2/amp_auction.go b/endpoints/openrtb2/amp_auction.go
index 586481dd..2dcd572c 100644
--- a/endpoints/openrtb2/amp_auction.go
+++ b/endpoints/openrtb2/amp_auction.go
@@ -407,31 +407,34 @@ func (deps *endpointDeps) overrideWithParams(httpRequest *http.Request, req *ope
 }
 
 func makeFormatReplacement(overrideWidth uint64, overrideHeight uint64, width uint64, height uint64, multisize string) []openrtb.Format {
+	var formats []openrtb.Format
 	if overrideWidth != 0 && overrideHeight != 0 {
-		return []openrtb.Format{{
+		formats = []openrtb.Format{{
 			W: overrideWidth,
 			H: overrideHeight,
 		}}
 	} else if overrideWidth != 0 && height != 0 {
-		return []openrtb.Format{{
+		formats = []openrtb.Format{{
 			W: overrideWidth,
 			H: height,
 		}}
 	} else if width != 0 && overrideHeight != 0 {
-		return []openrtb.Format{{
+		formats = []openrtb.Format{{
 			W: width,
 			H: overrideHeight,
 		}}
-	} else if parsedSizes := parseMultisize(multisize); len(parsedSizes) != 0 {
-		return parsedSizes
 	} else if width != 0 && height != 0 {
-		return []openrtb.Format{{
+		formats = []openrtb.Format{{
 			W: width,
 			H: height,
 		}}
 	}
 
-	return nil
+	if parsedSizes := parseMultisize(multisize); len(parsedSizes) != 0 {
+		formats = append(formats, parsedSizes...)
+	}
+
+	return formats
 }
 
 func setWidths(formats []openrtb.Format, width uint64) {
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 660beb64..84ae35d6 100644
--- a/exchange/exchange.go
+++ b/exchange/exchange.go
@@ -48,7 +48,7 @@ type exchange struct {
 	currencyConverter   *currencies.RateConverter
 	UsersyncIfAmbiguous bool
 	defaultTTLs         config.DefaultTTLs
-	enforceCCPA         bool
+	privacyConfig       config.Privacy
 }
 
 // Container to pass out response ext data from the GetAllBids goroutines back into the main thread
@@ -77,7 +77,11 @@ func NewExchange(client *http.Client, cache prebid_cache_client.Client, cfg *con
 	e.currencyConverter = currencyConverter
 	e.UsersyncIfAmbiguous = cfg.GDPR.UsersyncIfAmbiguous
 	e.defaultTTLs = cfg.CacheURL.DefaultTTLs
-	e.enforceCCPA = cfg.CCPA.Enforce
+	e.privacyConfig = config.Privacy{
+		CCPA: cfg.CCPA,
+		GDPR: cfg.GDPR,
+		LMT:  cfg.LMT,
+	}
 	return e
 }
 
@@ -100,7 +104,7 @@ func (e *exchange) HoldAuction(ctx context.Context, bidRequest *openrtb.BidReque
 
 	// Slice of BidRequests, each a copy of the original cleaned to only contain bidder data for the named bidder
 	blabels := make(map[openrtb_ext.BidderName]*pbsmetrics.AdapterLabels)
-	cleanRequests, aliases, errs := cleanOpenRTBRequests(ctx, bidRequest, usersyncs, blabels, labels, e.gDPR, e.UsersyncIfAmbiguous, e.enforceCCPA)
+	cleanRequests, aliases, errs := cleanOpenRTBRequests(ctx, bidRequest, usersyncs, blabels, labels, e.gDPR, e.UsersyncIfAmbiguous, e.privacyConfig)
 
 	// List of bidders we have requests for.
 	liveAdapters := listBiddersWithRequests(cleanRequests)
diff --git a/exchange/utils.go b/exchange/utils.go
index f602d1e8..54122d13 100644
--- a/exchange/utils.go
+++ b/exchange/utils.go
@@ -8,11 +8,13 @@ import (
 
 	"github.com/buger/jsonparser"
 	"github.com/mxmCherry/openrtb"
+	"github.com/prebid/prebid-server/config"
 	"github.com/prebid/prebid-server/gdpr"
 	"github.com/prebid/prebid-server/openrtb_ext"
 	"github.com/prebid/prebid-server/pbsmetrics"
 	"github.com/prebid/prebid-server/privacy"
 	"github.com/prebid/prebid-server/privacy/ccpa"
+	"github.com/prebid/prebid-server/privacy/lmt"
 )
 
 // cleanOpenRTBRequests splits the input request into requests which are sanitized for each bidder. Intended behavior is:
@@ -26,8 +28,8 @@ func cleanOpenRTBRequests(ctx context.Context,
 	blables map[openrtb_ext.BidderName]*pbsmetrics.AdapterLabels,
 	labels pbsmetrics.Labels,
 	gDPR gdpr.Permissions,
-	usersyncIfAmbiguous,
-	enforceCCPA bool) (requestsByBidder map[openrtb_ext.BidderName]*openrtb.BidRequest, aliases map[string]string, errs []error) {
+	usersyncIfAmbiguous bool,
+	privacyConfig config.Privacy) (requestsByBidder map[openrtb_ext.BidderName]*openrtb.BidRequest, aliases map[string]string, errs []error) {
 
 	impsByBidder, errs := splitImps(orig.Imp)
 	if len(errs) > 0 {
@@ -45,15 +47,24 @@ func cleanOpenRTBRequests(ctx context.Context,
 	consent := extractConsent(orig)
 	ampGDPRException := (labels.RType == pbsmetrics.ReqTypeAMP) && gDPR.AMPException()
 
-	privacyEnforcement := privacy.Enforcement{
-		COPPA: orig.Regs != nil && orig.Regs.COPPA == 1,
+	var ccpaPolicy ccpa.Policy
+	if privacyConfig.CCPA.Enforce {
+		ccpaPolicy, _ = ccpa.ReadPolicy(orig)
+	}
+
+	var lmtPolicy lmt.Policy
+	if privacyConfig.LMT.Enforce {
+		lmtPolicy = lmt.ReadPolicy(orig)
 	}
 
-	if enforceCCPA {
-		ccpaPolicy, _ := ccpa.ReadPolicy(orig)
-		privacyEnforcement.CCPA = ccpaPolicy.ShouldEnforce()
+	// request level privacy policies
+	privacyEnforcement := privacy.Enforcement{
+		CCPA:  ccpaPolicy.ShouldEnforce(),
+		COPPA: orig.Regs != nil && orig.Regs.COPPA == 1,
+		LMT:   lmtPolicy.ShouldEnforce(),
 	}
 
+	// bidder level privacy policies
 	for bidder, bidReq := range requestsByBidder {
 
 		if gdpr == 1 {
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/privacy/enforcement.go b/privacy/enforcement.go
index d302192e..8a5d201f 100644
--- a/privacy/enforcement.go
+++ b/privacy/enforcement.go
@@ -10,11 +10,12 @@ type Enforcement struct {
 	COPPA   bool
 	GDPR    bool
 	GDPRGeo bool
+	LMT     bool
 }
 
 // Any returns true if at least one privacy policy requires enforcement.
 func (e Enforcement) Any() bool {
-	return e.CCPA || e.COPPA || e.GDPR || e.GDPRGeo
+	return e.CCPA || e.COPPA || e.GDPR || e.GDPRGeo || e.LMT
 }
 
 // Apply cleans personally identifiable information from an OpenRTB bid request.
@@ -34,7 +35,7 @@ func (e Enforcement) getIPv6ScrubStrategy() ScrubStrategyIPV6 {
 		return ScrubStrategyIPV6Lowest32
 	}
 
-	if e.GDPR || e.CCPA {
+	if e.GDPR || e.CCPA || e.LMT {
 		return ScrubStrategyIPV6Lowest16
 	}
 
@@ -46,7 +47,7 @@ func (e Enforcement) getGeoScrubStrategy() ScrubStrategyGeo {
 		return ScrubStrategyGeoFull
 	}
 
-	if e.GDPRGeo || e.CCPA {
+	if e.GDPRGeo || e.CCPA || e.LMT {
 		return ScrubStrategyGeoReducedPrecision
 	}
 
@@ -63,7 +64,7 @@ func (e Enforcement) getUserScrubStrategy(ampGDPRException bool) ScrubStrategyUs
 	}
 
 	// If no user scrubbing is needed, then return none, else scrub ID (COPPA checked above)
-	if e.CCPA || e.GDPR {
+	if e.CCPA || e.GDPR || e.LMT {
 		return ScrubStrategyUserID
 	}
 
diff --git a/privacy/lmt/policy.go b/privacy/lmt/policy.go
new file mode 100644
index 00000000..79425bf5
--- /dev/null
+++ b/privacy/lmt/policy.go
@@ -0,0 +1,33 @@
+package lmt
+
+import (
+	"github.com/mxmCherry/openrtb"
+)
+
+const (
+	trackingUnrestricted = 0
+	trackingRestricted   = 1
+)
+
+// Policy represents the LMT (Limit Ad Tracking) policy for an OpenRTB bid request.
+type Policy struct {
+	Signal         int
+	SignalProvided bool
+}
+
+// ReadPolicy extracts the LMT (Limit Ad Tracking) policy from an OpenRTB bid request.
+func ReadPolicy(req *openrtb.BidRequest) Policy {
+	policy := Policy{}
+
+	if req != nil && req.Device != nil && req.Device.Lmt != nil {
+		policy.Signal = int(*req.Device.Lmt)
+		policy.SignalProvided = true
+	}
+
+	return policy
+}
+
+// ShouldEnforce returns true when the LMT (Limit Ad Tracking) policy is in effect.
+func (p Policy) ShouldEnforce() bool {
+	return p.SignalProvided && p.Signal == trackingRestricted
+}
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/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/config/config_test.go b/config/config_test.go
index ee8e68e7..2b291fe9 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -43,6 +43,8 @@ gdpr:
   non_standard_publishers: ["siteID","fake-site-id","appID","agltb3B1Yi1pbmNyDAsSA0FwcBiJkfIUDA"]
 ccpa:
   enforce: true
+lmt:
+  enforce: true
 host_cookie:
   cookie_name: userid
   family: prebid
@@ -240,6 +242,7 @@ func TestFullConfig(t *testing.T) {
 	cmpBools(t, "cfg.GDPR.NonStandardPublisherMap", found, false)
 
 	cmpBools(t, "ccpa.enforce", cfg.CCPA.Enforce, true)
+	cmpBools(t, "lmt.enforce", cfg.LMT.Enforce, true)
 
 	//Assert the NonStandardPublishers was correctly unmarshalled
 	cmpStrings(t, "blacklisted_apps", cfg.BlacklistedApps[0], "spamAppID")
diff --git a/endpoints/openrtb2/amp_auction_test.go b/endpoints/openrtb2/amp_auction_test.go
index 289db3f4..731fd55e 100644
--- a/endpoints/openrtb2/amp_auction_test.go
+++ b/endpoints/openrtb2/amp_auction_test.go
@@ -832,6 +832,24 @@ func TestMultisize(t *testing.T) {
 	}.execute(t)
 }
 
+func TestSizeWithMultisize(t *testing.T) {
+	formatOverrideSpec{
+		width:     20,
+		height:    40,
+		multisize: "200x50,100x60",
+		expect: []openrtb.Format{{
+			W: 20,
+			H: 40,
+		}, {
+			W: 200,
+			H: 50,
+		}, {
+			W: 100,
+			H: 60,
+		}},
+	}.execute(t)
+}
+
 func TestHeightOnly(t *testing.T) {
 	formatOverrideSpec{
 		height: 200,
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 e9b2127e..4f329962 100644
--- a/exchange/exchange_test.go
+++ b/exchange/exchange_test.go
@@ -731,7 +731,17 @@ func runSpec(t *testing.T, filename string, spec *exchangeSpec) {
 	if len(errs) != 0 {
 		t.Fatalf("%s: Failed to parse aliases", filename)
 	}
-	ex := newExchangeForTests(t, filename, spec.OutgoingRequests, aliases, spec.EnforceCCPA)
+
+	privacyConfig := config.Privacy{
+		CCPA: config.CCPA{
+			Enforce: spec.EnforceCCPA,
+		},
+		LMT: config.LMT{
+			Enforce: spec.EnforceLMT,
+		},
+	}
+
+	ex := newExchangeForTests(t, filename, spec.OutgoingRequests, aliases, privacyConfig)
 	biddersInAuction := findBiddersInAuction(t, filename, &spec.IncomingRequest.OrtbRequest)
 	categoriesFetcher, error := newCategoryFetcher("./test/category-mapping")
 	if error != nil {
@@ -816,7 +826,7 @@ func extractResponseTimes(t *testing.T, context string, bid *openrtb.BidResponse
 	}
 }
 
-func newExchangeForTests(t *testing.T, filename string, expectations map[string]*bidderSpec, aliases map[string]string, enforceCCPA bool) Exchange {
+func newExchangeForTests(t *testing.T, filename string, expectations map[string]*bidderSpec, aliases map[string]string, privacyConfig config.Privacy) Exchange {
 	adapters := make(map[openrtb_ext.BidderName]adaptedBidder)
 	for _, bidderName := range openrtb_ext.BidderMap {
 		if spec, ok := expectations[string(bidderName)]; ok {
@@ -854,7 +864,7 @@ func newExchangeForTests(t *testing.T, filename string, expectations map[string]
 		gDPR:                gdpr.AlwaysAllow{},
 		currencyConverter:   currencies.NewRateConverterDefault(),
 		UsersyncIfAmbiguous: false,
-		enforceCCPA:         enforceCCPA,
+		privacyConfig:       privacyConfig,
 	}
 }
 
@@ -1620,6 +1630,7 @@ type exchangeSpec struct {
 	OutgoingRequests map[string]*bidderSpec `json:"outgoingRequests"`
 	Response         exchangeResponse       `json:"response,omitempty"`
 	EnforceCCPA      bool                   `json:"enforceCcpa"`
+	EnforceLMT       bool                   `json:"enforceLmt"`
 	DebugLog         *DebugLog              `json:"debuglog,omitempty"`
 }
 
diff --git a/exchange/exchangetest/lmt-featureflag-off.json b/exchange/exchangetest/lmt-featureflag-off.json
new file mode 100644
index 00000000..9a15c879
--- /dev/null
+++ b/exchange/exchangetest/lmt-featureflag-off.json
@@ -0,0 +1,63 @@
+{
+    "enforceLmt": false,
+    "incomingRequest": {
+        "ortbRequest": {
+            "id": "some-request-id",
+            "site": {
+                "page": "test.somepage.com"
+            },
+            "imp": [{
+                "id": "my-imp-id",
+                "video": {
+                    "mimes": ["video/mp4"]
+                },
+                "ext": {
+                    "appnexus": {
+                        "placementId": 1
+                    }
+                }
+            }],
+            "device": {
+                "lmt": 1
+            },
+            "user": {
+                "id": "some-id",
+                "buyeruid": "some-buyer-id"
+            }
+        }
+    },
+    "outgoingRequests": {
+        "appnexus": {
+            "expectRequest": {
+                "ortbRequest": {
+                    "id": "some-request-id",
+                    "site": {
+                        "page": "test.somepage.com"
+                    },
+                    "imp": [{
+                        "id": "my-imp-id",
+                        "video": {
+                            "mimes": ["video/mp4"]
+                        },
+                        "ext": {
+                            "bidder": {
+                                "placementId": 1
+                            }
+                        }
+                    }],
+                    "device": {
+                        "lmt": 1
+                    },
+                    "user": {
+                        "id": "some-id",
+                        "buyeruid": "some-buyer-id"
+                    }
+                },
+                "bidAdjustment": 1.0
+            },
+            "mockResponse": {
+                "errors": ["appnexus-error"]
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/exchange/exchangetest/lmt-featureflag-on.json b/exchange/exchangetest/lmt-featureflag-on.json
new file mode 100644
index 00000000..440f8c76
--- /dev/null
+++ b/exchange/exchangetest/lmt-featureflag-on.json
@@ -0,0 +1,61 @@
+{
+    "enforceLmt": true,
+    "incomingRequest": {
+        "ortbRequest": {
+            "id": "some-request-id",
+            "site": {
+                "page": "test.somepage.com"
+            },
+            "imp": [{
+                "id": "my-imp-id",
+                "video": {
+                    "mimes": ["video/mp4"]
+                },
+                "ext": {
+                    "appnexus": {
+                        "placementId": 1
+                    }
+                }
+            }],
+            "device": {
+                "lmt": 1
+            },
+            "user": {
+                "id": "some-id",
+                "buyeruid": "some-buyer-id"
+            }
+        }
+    },
+    "outgoingRequests": {
+        "appnexus": {
+            "expectRequest": {
+                "ortbRequest": {
+                    "id": "some-request-id",
+                    "site": {
+                        "page": "test.somepage.com"
+                    },
+                    "imp": [{
+                        "id": "my-imp-id",
+                        "video": {
+                            "mimes": ["video/mp4"]
+                        },
+                        "ext": {
+                            "bidder": {
+                                "placementId": 1
+                            }
+                        }
+                    }],
+                    "device": {
+                        "lmt": 1
+                    },
+                    "user": {
+                    }
+                },
+                "bidAdjustment": 1.0
+            },
+            "mockResponse": {
+                "errors": ["appnexus-error"]
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/exchange/utils_test.go b/exchange/utils_test.go
index acbf25ff..4dad3f54 100644
--- a/exchange/utils_test.go
+++ b/exchange/utils_test.go
@@ -6,6 +6,7 @@ import (
 	"testing"
 
 	"github.com/mxmCherry/openrtb"
+	"github.com/prebid/prebid-server/config"
 	"github.com/prebid/prebid-server/openrtb_ext"
 	"github.com/prebid/prebid-server/pbsmetrics"
 	"github.com/stretchr/testify/assert"
@@ -69,8 +70,17 @@ func TestCleanOpenRTBRequests(t *testing.T) {
 			applyCOPPA: false, consentedVendors: map[string]bool{"appnexus": true, "brightroll": true}},
 	}
 
+	privacyConfig := config.Privacy{
+		CCPA: config.CCPA{
+			Enforce: true,
+		},
+		LMT: config.LMT{
+			Enforce: true,
+		},
+	}
+
 	for _, test := range testCases {
-		reqByBidders, _, err := cleanOpenRTBRequests(context.Background(), test.req, &emptyUsersync{}, map[openrtb_ext.BidderName]*pbsmetrics.AdapterLabels{}, pbsmetrics.Labels{}, &permissionsMock{}, true, true)
+		reqByBidders, _, err := cleanOpenRTBRequests(context.Background(), test.req, &emptyUsersync{}, map[openrtb_ext.BidderName]*pbsmetrics.AdapterLabels{}, pbsmetrics.Labels{}, &permissionsMock{}, true, privacyConfig)
 		if test.hasError {
 			assert.NotNil(t, err, "Error shouldn't be nil")
 		} else {
@@ -99,9 +109,80 @@ func TestCleanOpenRTBRequestsCCPA(t *testing.T) {
 	}
 
 	for _, test := range testCases {
-		req := newCCPABidRequest(t)
+		req := newBidRequest(t)
+		req.Regs = &openrtb.Regs{
+			Ext: json.RawMessage(`{"us_privacy":"1-Y-"}`),
+		}
 
-		results, _, errs := cleanOpenRTBRequests(context.Background(), req, &emptyUsersync{}, map[openrtb_ext.BidderName]*pbsmetrics.AdapterLabels{}, pbsmetrics.Labels{}, &permissionsMock{}, true, test.enforceCCPA)
+		privacyConfig := config.Privacy{
+			CCPA: config.CCPA{
+				Enforce: test.enforceCCPA,
+			},
+		}
+
+		results, _, errs := cleanOpenRTBRequests(context.Background(), req, &emptyUsersync{}, map[openrtb_ext.BidderName]*pbsmetrics.AdapterLabels{}, pbsmetrics.Labels{}, &permissionsMock{}, true, privacyConfig)
+		result := results["appnexus"]
+
+		assert.Nil(t, errs)
+
+		if test.expectDataScrub {
+			assert.Equal(t, result.User.BuyerUID, "", test.description+":User.BuyerUID")
+			assert.Equal(t, result.Device.DIDMD5, "", test.description+":Device.DIDMD5")
+		} else {
+			assert.NotEqual(t, result.User.BuyerUID, "", test.description+":User.BuyerUID")
+			assert.NotEqual(t, result.Device.DIDMD5, "", test.description+":Device.DIDMD5")
+		}
+	}
+}
+
+func TestCleanOpenRTBRequestsLMT(t *testing.T) {
+	var (
+		enabled  int8 = 1
+		disabled int8 = 0
+	)
+	testCases := []struct {
+		description     string
+		lmt             *int8
+		enforceLMT      bool
+		expectDataScrub bool
+	}{
+		{
+			description:     "Feature Flag Enabled - OpenTRB Enabled",
+			lmt:             &enabled,
+			enforceLMT:      true,
+			expectDataScrub: true,
+		},
+		{
+			description:     "Feature Flag Disabled - OpenTRB Enabled",
+			lmt:             &enabled,
+			enforceLMT:      false,
+			expectDataScrub: false,
+		},
+		{
+			description:     "Feature Flag Enabled - OpenTRB Disabled",
+			lmt:             &disabled,
+			enforceLMT:      true,
+			expectDataScrub: false,
+		},
+		{
+			description:     "Feature Flag Disabled - OpenTRB Disabled",
+			lmt:             &disabled,
+			enforceLMT:      false,
+			expectDataScrub: false,
+		},
+	}
+
+	for _, test := range testCases {
+		req := newBidRequest(t)
+		req.Device.Lmt = test.lmt
+
+		privacyConfig := config.Privacy{
+			LMT: config.LMT{
+				Enforce: test.enforceLMT,
+			},
+		}
+
+		results, _, errs := cleanOpenRTBRequests(context.Background(), req, &emptyUsersync{}, map[openrtb_ext.BidderName]*pbsmetrics.AdapterLabels{}, pbsmetrics.Labels{}, &permissionsMock{}, true, privacyConfig)
 		result := results["appnexus"]
 
 		assert.Nil(t, errs)
@@ -163,8 +244,7 @@ func newAdapterAliasBidRequest(t *testing.T) *openrtb.BidRequest {
 	}
 }
 
-func newCCPABidRequest(t *testing.T) *openrtb.BidRequest {
-	dnt := int8(1)
+func newBidRequest(t *testing.T) *openrtb.BidRequest {
 	return &openrtb.BidRequest{
 		Site: &openrtb.Site{
 			Page:   "www.some.domain.com",
@@ -178,7 +258,6 @@ func newCCPABidRequest(t *testing.T) *openrtb.BidRequest {
 			UA:       "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36",
 			IFA:      "ifa",
 			IP:       "132.173.230.74",
-			DNT:      &dnt,
 			Language: "EN",
 		},
 		Source: &openrtb.Source{
@@ -189,9 +268,6 @@ func newCCPABidRequest(t *testing.T) *openrtb.BidRequest {
 			BuyerUID: "their-id",
 			Ext:      json.RawMessage(`{"digitrust":{"id":"digi-id","keyv":1,"pref":1}}`),
 		},
-		Regs: &openrtb.Regs{
-			Ext: json.RawMessage(`{"us_privacy":"1-Y-"}`),
-		},
 		Imp: []openrtb.Imp{{
 			ID: "some-imp-id",
 			Banner: &openrtb.Banner{
diff --git a/privacy/enforcement_test.go b/privacy/enforcement_test.go
index 0e82648d..968c6354 100644
--- a/privacy/enforcement_test.go
+++ b/privacy/enforcement_test.go
@@ -21,6 +21,7 @@ func TestAny(t *testing.T) {
 				COPPA:   false,
 				GDPR:    false,
 				GDPRGeo: false,
+				LMT:     false,
 			},
 			expected: false,
 		},
@@ -31,6 +32,7 @@ func TestAny(t *testing.T) {
 				COPPA:   true,
 				GDPR:    true,
 				GDPRGeo: true,
+				LMT:     true,
 			},
 			expected: true,
 		},
@@ -41,16 +43,7 @@ func TestAny(t *testing.T) {
 				COPPA:   true,
 				GDPR:    false,
 				GDPRGeo: false,
-			},
-			expected: true,
-		},
-		{
-			description: "GDPRGeo only",
-			enforcement: Enforcement{
-				CCPA:    false,
-				COPPA:   false,
-				GDPR:    false,
-				GDPRGeo: true,
+				LMT:     true,
 			},
 			expected: true,
 		},
@@ -79,6 +72,7 @@ func TestApply(t *testing.T) {
 				COPPA:   true,
 				GDPR:    true,
 				GDPRGeo: true,
+				LMT:     true,
 			},
 			ampGDPRException:   false,
 			expectedDeviceIPv6: ScrubStrategyIPV6Lowest32,
@@ -93,6 +87,7 @@ func TestApply(t *testing.T) {
 				COPPA:   false,
 				GDPR:    false,
 				GDPRGeo: false,
+				LMT:     false,
 			},
 			ampGDPRException:   false,
 			expectedDeviceIPv6: ScrubStrategyIPV6Lowest16,
@@ -107,6 +102,7 @@ func TestApply(t *testing.T) {
 				COPPA:   true,
 				GDPR:    false,
 				GDPRGeo: false,
+				LMT:     false,
 			},
 			ampGDPRException:   false,
 			expectedDeviceIPv6: ScrubStrategyIPV6Lowest32,
@@ -121,6 +117,7 @@ func TestApply(t *testing.T) {
 				COPPA:   false,
 				GDPR:    true,
 				GDPRGeo: true,
+				LMT:     false,
 			},
 			ampGDPRException:   false,
 			expectedDeviceIPv6: ScrubStrategyIPV6Lowest16,
@@ -135,6 +132,7 @@ func TestApply(t *testing.T) {
 				COPPA:   false,
 				GDPR:    true,
 				GDPRGeo: true,
+				LMT:     false,
 			},
 			ampGDPRException:   true,
 			expectedDeviceIPv6: ScrubStrategyIPV6Lowest16,
@@ -149,6 +147,7 @@ func TestApply(t *testing.T) {
 				COPPA:   false,
 				GDPR:    false,
 				GDPRGeo: false,
+				LMT:     false,
 			},
 			ampGDPRException:   true,
 			expectedDeviceIPv6: ScrubStrategyIPV6Lowest16,
@@ -163,6 +162,7 @@ func TestApply(t *testing.T) {
 				COPPA:   true,
 				GDPR:    true,
 				GDPRGeo: true,
+				LMT:     false,
 			},
 			ampGDPRException:   true,
 			expectedDeviceIPv6: ScrubStrategyIPV6Lowest32,
@@ -177,6 +177,7 @@ func TestApply(t *testing.T) {
 				COPPA:   false,
 				GDPR:    true,
 				GDPRGeo: false,
+				LMT:     false,
 			},
 			ampGDPRException:   false,
 			expectedDeviceIPv6: ScrubStrategyIPV6Lowest16,
@@ -191,6 +192,7 @@ func TestApply(t *testing.T) {
 				COPPA:   false,
 				GDPR:    false,
 				GDPRGeo: true,
+				LMT:     false,
 			},
 			ampGDPRException:   false,
 			expectedDeviceIPv6: ScrubStrategyIPV6None,
@@ -198,6 +200,36 @@ func TestApply(t *testing.T) {
 			expectedUser:       ScrubStrategyUserNone,
 			expectedUserGeo:    ScrubStrategyGeoReducedPrecision,
 		},
+		{
+			description: "LMT Only",
+			enforcement: Enforcement{
+				CCPA:    false,
+				COPPA:   false,
+				GDPR:    false,
+				GDPRGeo: false,
+				LMT:     true,
+			},
+			ampGDPRException:   false,
+			expectedDeviceIPv6: ScrubStrategyIPV6Lowest16,
+			expectedDeviceGeo:  ScrubStrategyGeoReducedPrecision,
+			expectedUser:       ScrubStrategyUserID,
+			expectedUserGeo:    ScrubStrategyGeoReducedPrecision,
+		},
+		{
+			description: "LMT Only, ampGDPRException",
+			enforcement: Enforcement{
+				CCPA:    false,
+				COPPA:   false,
+				GDPR:    false,
+				GDPRGeo: false,
+				LMT:     true,
+			},
+			ampGDPRException:   true,
+			expectedDeviceIPv6: ScrubStrategyIPV6Lowest16,
+			expectedDeviceGeo:  ScrubStrategyGeoReducedPrecision,
+			expectedUser:       ScrubStrategyUserID,
+			expectedUserGeo:    ScrubStrategyGeoReducedPrecision,
+		},
 	}
 
 	for _, test := range testCases {
@@ -229,6 +261,7 @@ func TestApplyNoneApplicable(t *testing.T) {
 		CCPA:  false,
 		COPPA: false,
 		GDPR:  false,
+		LMT:   false,
 	}
 	enforcement.apply(req, false, m)
 
diff --git a/privacy/lmt/policy_test.go b/privacy/lmt/policy_test.go
new file mode 100644
index 00000000..45de219a
--- /dev/null
+++ b/privacy/lmt/policy_test.go
@@ -0,0 +1,128 @@
+package lmt
+
+import (
+	"testing"
+
+	"github.com/mxmCherry/openrtb"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestRead(t *testing.T) {
+	var one int8 = 1
+
+	testCases := []struct {
+		description    string
+		request        *openrtb.BidRequest
+		expectedPolicy Policy
+	}{
+		{
+			description: "Nil Request",
+			request:     nil,
+			expectedPolicy: Policy{
+				Signal:         0,
+				SignalProvided: false,
+			},
+		},
+		{
+			description: "Nil Device",
+			request: &openrtb.BidRequest{
+				Device: nil,
+			},
+			expectedPolicy: Policy{
+				Signal:         0,
+				SignalProvided: false,
+			},
+		},
+		{
+			description: "Nil Device.Lmt",
+			request: &openrtb.BidRequest{
+				Device: &openrtb.Device{
+					Lmt: nil,
+				},
+			},
+			expectedPolicy: Policy{
+				Signal:         0,
+				SignalProvided: false,
+			},
+		},
+		{
+			description: "Enabled",
+			request: &openrtb.BidRequest{
+				Device: &openrtb.Device{
+					Lmt: &one,
+				},
+			},
+			expectedPolicy: Policy{
+				Signal:         1,
+				SignalProvided: true,
+			},
+		},
+	}
+
+	for _, test := range testCases {
+		p := ReadPolicy(test.request)
+		assert.Equal(t, test.expectedPolicy, p, test.description)
+	}
+}
+
+func TestShouldEnforce(t *testing.T) {
+	testCases := []struct {
+		description string
+		policy      Policy
+		expected    bool
+	}{
+		{
+			description: "Signal Not Provided - Zero",
+			policy: Policy{
+				Signal:         0,
+				SignalProvided: false,
+			},
+			expected: false,
+		},
+		{
+			description: "Signal Not Provided - One",
+			policy: Policy{
+				Signal:         1,
+				SignalProvided: false,
+			},
+			expected: false,
+		},
+		{
+			description: "Signal Not Provided - Other",
+			policy: Policy{
+				Signal:         42,
+				SignalProvided: false,
+			},
+			expected: false,
+		},
+		{
+			description: "Signal Provided - Zero",
+			policy: Policy{
+				Signal:         0,
+				SignalProvided: true,
+			},
+			expected: false,
+		},
+		{
+			description: "Signal Provided - One",
+			policy: Policy{
+				Signal:         1,
+				SignalProvided: true,
+			},
+			expected: true,
+		},
+		{
+			description: "Signal Provided - Other",
+			policy: Policy{
+				Signal:         42,
+				SignalProvided: true,
+			},
+			expected: false,
+		},
+	}
+
+	for _, test := range testCases {
+		result := test.policy.ShouldEnforce()
+		assert.Equal(t, test.expected, result, test.description)
+	}
+}
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,