Repository: prebid/prebid-server
Pull request #1585 (2020-11-14 08:46:20)

New Adapter: Mobfox
https://github.com/prebid/prebid.github.io/pull/2501

mobfxoHB: @guscarreon  The Adprime adapter was not created by us and it is not related to our company. I have reviewed multiple adapters and realised that their implementation is pretty similar to what is required, so I would like to create new one that might look related to already existing ones. Please let me know how we should proceed.
guscarreon: @mobfxoHB. Your adapter looks pretty good, but: Starting our next release on December 3rd, adapter source code will need to be written in a slightly different way. Pull request #1532 describes this changes. Therefore, before we merge your adapter please take a look to PR #1532 and modify your adapter accordingly. If you have any questions, we're glad to help.

SyntaxNode: We also just published a [new adapter doc](https://docs.prebid.org/prebid-server/developers/add-new-bidder-go.html) today which will guide you through the new approach.
mobfxoHB: @guscarreon About docs - i think now it's more clear what should be done, but one thing would be helpful - minimal structure of files, which should be added or edited at the beginning of the docs as the reffernce to prevent scrolling back and forth.  About this comment https://github.com/prebid/prebid-server/pull/1585/#discussion_r534364812 , which docs do you mean?  github.io dev-docs ? maybe there is some formal parameter for multi impression support
SyntaxNode: > About this comment #1585 , which docs do you mean? github.io dev-docs ? maybe there is some formal parameter for multi impression support

We were referring to the github.io dev-docs. Please include a mention there that your adapter will only forward the first impression to your bidding server and ignore the rest.

I think you already mentioned this, but please consider supporting multiple impressions in the future. Each impression can be broken down to individual requests.
mobfxoHB: > > About this comment #1585 , which docs do you mean? github.io dev-docs ? maybe there is some formal parameter for multi impression support
> 
> We were referring to the github.io dev-docs. Please include a mention there that your adapter will only forward the first impression to your bidding server and ignore the rest.
> 
> I think you already mentioned this, but please consider supporting multiple impressions in the future. Each impression can be broken down to individual requests.

I've mentioned this in the docs
mobfxoHB: @guscarreon Thank you for your patience, I think we would live adapter without any changes for now and add more precise status codes handling and multi bidding in next iteration
mobfxoHB: @mansinahar @SyntaxNode Good day, i've made last changes to resolve merge conflict, so, can we please finish with this PR ?

Patch:
diff --git a/adapters/mobfoxpb/mobfoxpb.go b/adapters/mobfoxpb/mobfoxpb.go
new file mode 100644
index 00000000..5369c082
--- /dev/null
+++ b/adapters/mobfoxpb/mobfoxpb.go
@@ -0,0 +1,131 @@
+package mobfoxpb
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+
+	"github.com/buger/jsonparser"
+	"github.com/mxmCherry/openrtb"
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/config"
+	"github.com/prebid/prebid-server/errortypes"
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+type adapter struct {
+	URI string
+}
+
+// Builder builds a new instance of the Mobfox adapter for the given bidder with the given config.
+func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) {
+	bidder := &adapter{
+		URI: config.Endpoint,
+	}
+	return bidder, nil
+}
+
+// MakeRequests create bid request for mobfoxpb demand
+func (a *adapter) MakeRequests(request *openrtb.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
+	var errs []error
+	var err error
+	var tagID string
+
+	var adapterRequests []*adapters.RequestData
+
+	reqCopy := *request
+	imp := request.Imp[0]
+	tagID, err = jsonparser.GetString(imp.Ext, "bidder", "TagID")
+	if err != nil {
+		errs = append(errs, err)
+		return nil, errs
+	}
+	imp.TagID = tagID
+	reqCopy.Imp = []openrtb.Imp{imp}
+	adapterReq, err := a.makeRequest(&reqCopy)
+	if err != nil {
+		errs = append(errs, err)
+	}
+	if adapterReq != nil {
+		adapterRequests = append(adapterRequests, adapterReq)
+	}
+	return adapterRequests, errs
+}
+
+func (a *adapter) makeRequest(request *openrtb.BidRequest) (*adapters.RequestData, error) {
+	reqJSON, err := json.Marshal(request)
+
+	if err != nil {
+		return nil, err
+	}
+
+	headers := http.Header{}
+	headers.Add("Content-Type", "application/json;charset=utf-8")
+	headers.Add("Accept", "application/json")
+	return &adapters.RequestData{
+		Method:  "POST",
+		Uri:     a.URI,
+		Body:    reqJSON,
+		Headers: headers,
+	}, nil
+}
+
+// MakeBids makes the bids
+func (a *adapter) MakeBids(internalRequest *openrtb.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+	var errs []error
+
+	if response.StatusCode == http.StatusNoContent {
+		return nil, nil
+	}
+
+	if response.StatusCode != http.StatusOK {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode),
+		}}
+	}
+
+	var bidResp openrtb.BidResponse
+
+	if err := json.Unmarshal(response.Body, &bidResp); err != nil {
+		return nil, []error{err}
+	}
+
+	bidResponse := adapters.NewBidderResponseWithBidsCapacity(1)
+
+	for _, sb := range bidResp.SeatBid {
+		for _, bid := range sb.Bid {
+			bidType, err := getMediaTypeForImp(bid.ImpID, internalRequest.Imp)
+			if err != nil {
+				errs = append(errs, err)
+			} else {
+				b := &adapters.TypedBid{
+					Bid:     &bid,
+					BidType: bidType,
+				}
+				bidResponse.Bids = append(bidResponse.Bids, b)
+			}
+		}
+	}
+	return bidResponse, errs
+}
+
+func getMediaTypeForImp(impID string, imps []openrtb.Imp) (openrtb_ext.BidType, error) {
+	mediaType := openrtb_ext.BidTypeBanner
+	for _, imp := range imps {
+		if imp.ID == impID {
+			if imp.Banner != nil {
+				mediaType = openrtb_ext.BidTypeBanner
+			} else if imp.Video != nil {
+				mediaType = openrtb_ext.BidTypeVideo
+			} else if imp.Native != nil {
+				mediaType = openrtb_ext.BidTypeNative
+			}
+			return mediaType, nil
+		}
+	}
+
+	// This shouldnt happen. Lets handle it just incase by returning an error.
+	return "", &errortypes.BadServerResponse{
+		Message: fmt.Sprintf("Failed to find impression \"%s\" ", impID),
+	}
+}
diff --git a/config/config.go b/config/config.go
index db9adf4f..f48ce9da 100755
--- a/config/config.go
+++ b/config/config.go
@@ -214,7 +214,7 @@ func (cfg *GDPR) validate(errs []error) []error {
 		glog.Warning("gdpr.host_vendor_id was not specified. Host company GDPR checks will be skipped.")
 	}
 	if cfg.AMPException == true {
-		glog.Warning("gdpr.amp_exception is deprecated and will be removed in a future version. If you need to disable GDPR for AMP, you may do so per-account (gdpr.integration_enabled.amp) or at the host level for the default account (account_defaults.gdpr.integration_enabled.amp).")
+		errs = append(errs, fmt.Errorf("gdpr.amp_exception has been discontinued and must be removed from your config. If you need to disable GDPR for AMP, you may do so per-account (gdpr.integration_enabled.amp) or at the host level for the default account (account_defaults.gdpr.integration_enabled.amp)"))
 	}
 	return errs
 }
@@ -846,6 +846,7 @@ func SetupViper(v *viper.Viper, filename string) {
 	v.SetDefault("adapters.marsmedia.endpoint", "https://bid306.rtbsrv.com/bidder/?bid=f3xtet")
 	v.SetDefault("adapters.mgid.endpoint", "https://prebid.mgid.com/prebid/")
 	v.SetDefault("adapters.mobilefuse.endpoint", "http://mfx.mobilefuse.com/openrtb?pub_id={{.PublisherID}}")
+	v.SetDefault("adapters.mobfoxpb.endpoint", "http://bes.mobfox.com/?c=o&m=ortb")
 	v.SetDefault("adapters.nanointeractive.endpoint", "https://ad.audiencemanager.de/hbs")
 	v.SetDefault("adapters.ninthdecimal.endpoint", "http://rtb.ninthdecimal.com/xp/get?pubid={{.PublisherID}}")
 	v.SetDefault("adapters.nobid.endpoint", "https://ads.servenobid.com/ortb_adreq?tek=pbs&ver=1")
@@ -873,7 +874,7 @@ func SetupViper(v *viper.Viper, filename string) {
 	v.SetDefault("adapters.triplelift_native.disabled", true)
 	v.SetDefault("adapters.triplelift_native.extra_info", "{\"publisher_whitelist\":[]}")
 	v.SetDefault("adapters.triplelift.endpoint", "https://tlx.3lift.com/s2s/auction?sra=1&supplier_id=20")
-	v.SetDefault("adapters.ucfunnel.endpoint", "http://pbs.aralego.com/prebid")
+	v.SetDefault("adapters.ucfunnel.endpoint", "https://pbs.aralego.com/prebid")
 	v.SetDefault("adapters.unruly.endpoint", "http://targeting.unrulymedia.com/openrtb/2.2")
 	v.SetDefault("adapters.valueimpression.endpoint", "https://rtb.valueimpression.com/endpoint")
 	v.SetDefault("adapters.verizonmedia.disabled", true)
diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go
index 2d73b823..32311ef6 100755
--- a/exchange/adapter_builders.go
+++ b/exchange/adapter_builders.go
@@ -54,6 +54,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/lunamedia"
 	"github.com/prebid/prebid-server/adapters/marsmedia"
 	"github.com/prebid/prebid-server/adapters/mgid"
+	"github.com/prebid/prebid-server/adapters/mobfoxpb"
 	"github.com/prebid/prebid-server/adapters/mobilefuse"
 	"github.com/prebid/prebid-server/adapters/nanointeractive"
 	"github.com/prebid/prebid-server/adapters/ninthdecimal"
@@ -150,6 +151,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder {
 		openrtb_ext.BidderLunaMedia:        lunamedia.Builder,
 		openrtb_ext.BidderMarsmedia:        marsmedia.Builder,
 		openrtb_ext.BidderMgid:             mgid.Builder,
+		openrtb_ext.BidderMobfoxpb:         mobfoxpb.Builder,
 		openrtb_ext.BidderMobileFuse:       mobilefuse.Builder,
 		openrtb_ext.BidderNanoInteractive:  nanointeractive.Builder,
 		openrtb_ext.BidderNinthDecimal:     ninthdecimal.Builder,
diff --git a/exchange/utils.go b/exchange/utils.go
index d70829ff..a803e4e2 100644
--- a/exchange/utils.go
+++ b/exchange/utils.go
@@ -77,7 +77,6 @@ func cleanOpenRTBRequests(ctx context.Context,
 
 	gdpr := extractGDPR(req.BidRequest, usersyncIfAmbiguous)
 	consent := extractConsent(req.BidRequest)
-	ampGDPRException := (req.LegacyLabels.RType == metrics.ReqTypeAMP) && gDPR.AMPException()
 
 	ccpaEnforcer, err := extractCCPA(req.BidRequest, privacyConfig, &req.Account, aliases, integrationTypeMap[req.LegacyLabels.RType])
 	if err != nil {
@@ -125,7 +124,7 @@ func cleanOpenRTBRequests(ctx context.Context,
 			privacyEnforcement.GDPRID = false
 		}
 
-		privacyEnforcement.Apply(bidderRequest.BidRequest, ampGDPRException)
+		privacyEnforcement.Apply(bidderRequest.BidRequest)
 	}
 
 	return
diff --git a/gdpr/gdpr.go b/gdpr/gdpr.go
index 6d447beb..60a7cc1e 100644
--- a/gdpr/gdpr.go
+++ b/gdpr/gdpr.go
@@ -24,9 +24,6 @@ type Permissions interface {
 	//
 	// If the consent string was nonsensical, the returned error will be an ErrorMalformedConsent.
 	PersonalInfoAllowed(ctx context.Context, bidder openrtb_ext.BidderName, PublisherID string, consent string) (bool, bool, bool, error)
-
-	// Exposes the AMP execption flag
-	AMPException() bool
 }
 
 // Versions of the GDPR TCF technical specification.
diff --git a/gdpr/impl.go b/gdpr/impl.go
index 2fbd9c5a..5b3b86fe 100644
--- a/gdpr/impl.go
+++ b/gdpr/impl.go
@@ -60,10 +60,6 @@ func (p *permissionsImpl) PersonalInfoAllowed(ctx context.Context, bidder openrt
 	return false, false, false, nil
 }
 
-func (p *permissionsImpl) AMPException() bool {
-	return p.cfg.AMPException
-}
-
 func (p *permissionsImpl) allowSync(ctx context.Context, vendorID uint16, consent string) (bool, error) {
 	// If we're not given a consent string, respect the preferences in the app config.
 	if consent == "" {
@@ -225,10 +221,6 @@ func (a AlwaysAllow) PersonalInfoAllowed(ctx context.Context, bidder openrtb_ext
 	return true, true, true, nil
 }
 
-func (a AlwaysAllow) AMPException() bool {
-	return false
-}
-
 // Exporting to allow for easy test setups
 type AlwaysFail struct{}
 
@@ -243,7 +235,3 @@ func (a AlwaysFail) BidderSyncAllowed(ctx context.Context, bidder openrtb_ext.Bi
 func (a AlwaysFail) PersonalInfoAllowed(ctx context.Context, bidder openrtb_ext.BidderName, PublisherID string, consent string) (bool, bool, bool, error) {
 	return false, false, false, nil
 }
-
-func (a AlwaysFail) AMPException() bool {
-	return false
-}
diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go
index 6f426c52..f7f83125 100755
--- a/openrtb_ext/bidders.go
+++ b/openrtb_ext/bidders.go
@@ -94,6 +94,7 @@ const (
 	BidderLunaMedia        BidderName = "lunamedia"
 	BidderMarsmedia        BidderName = "marsmedia"
 	BidderMgid             BidderName = "mgid"
+	BidderMobfoxpb         BidderName = "mobfoxpb"
 	BidderMobileFuse       BidderName = "mobilefuse"
 	BidderNanoInteractive  BidderName = "nanointeractive"
 	BidderNinthDecimal     BidderName = "ninthdecimal"
@@ -190,6 +191,7 @@ func CoreBidderNames() []BidderName {
 		BidderLunaMedia,
 		BidderMarsmedia,
 		BidderMgid,
+		BidderMobfoxpb,
 		BidderMobileFuse,
 		BidderNanoInteractive,
 		BidderNinthDecimal,
diff --git a/privacy/enforcement.go b/privacy/enforcement.go
index 3f157329..64070ae3 100644
--- a/privacy/enforcement.go
+++ b/privacy/enforcement.go
@@ -19,14 +19,14 @@ func (e Enforcement) Any() bool {
 }
 
 // Apply cleans personally identifiable information from an OpenRTB bid request.
-func (e Enforcement) Apply(bidRequest *openrtb.BidRequest, ampGDPRException bool) {
-	e.apply(bidRequest, ampGDPRException, NewScrubber())
+func (e Enforcement) Apply(bidRequest *openrtb.BidRequest) {
+	e.apply(bidRequest, NewScrubber())
 }
 
-func (e Enforcement) apply(bidRequest *openrtb.BidRequest, ampGDPRException bool, scrubber Scrubber) {
+func (e Enforcement) apply(bidRequest *openrtb.BidRequest, scrubber Scrubber) {
 	if bidRequest != nil && e.Any() {
 		bidRequest.Device = scrubber.ScrubDevice(bidRequest.Device, e.getDeviceIDScrubStrategy(), e.getIPv4ScrubStrategy(), e.getIPv6ScrubStrategy(), e.getGeoScrubStrategy())
-		bidRequest.User = scrubber.ScrubUser(bidRequest.User, e.getUserScrubStrategy(ampGDPRException), e.getGeoScrubStrategy())
+		bidRequest.User = scrubber.ScrubUser(bidRequest.User, e.getUserScrubStrategy(), e.getGeoScrubStrategy())
 	}
 }
 
@@ -70,7 +70,7 @@ func (e Enforcement) getGeoScrubStrategy() ScrubStrategyGeo {
 	return ScrubStrategyGeoNone
 }
 
-func (e Enforcement) getUserScrubStrategy(ampGDPRException bool) ScrubStrategyUser {
+func (e Enforcement) getUserScrubStrategy() ScrubStrategyUser {
 	if e.COPPA {
 		return ScrubStrategyUserIDAndDemographic
 	}
@@ -79,7 +79,7 @@ func (e Enforcement) getUserScrubStrategy(ampGDPRException bool) ScrubStrategyUs
 		return ScrubStrategyUserID
 	}
 
-	if e.GDPRID && !ampGDPRException {
+	if e.GDPRID {
 		return ScrubStrategyUserID
 	}
 
diff --git a/static/bidder-info/adprime.yaml b/static/bidder-info/adprime.yaml
index 9759ed63..d702521e 100644
--- a/static/bidder-info/adprime.yaml
+++ b/static/bidder-info/adprime.yaml
@@ -1,5 +1,5 @@
 maintainer:
-  email: "rafal@adprime.com"
+  email: "prebid@adprime.com"
 capabilities:
   app:
     mediaTypes:
@@ -8,4 +8,4 @@ capabilities:
   site:
     mediaTypes:
       - banner
-      - video 
\ No newline at end of file
+      - video 
diff --git a/static/bidder-info/mobfoxpb.yaml b/static/bidder-info/mobfoxpb.yaml
new file mode 100644
index 00000000..ba3bb60d
--- /dev/null
+++ b/static/bidder-info/mobfoxpb.yaml
@@ -0,0 +1,11 @@
+maintainer:
+  email: "platform@mobfox.com"
+capabilities:
+  app:
+    mediaTypes:
+      - banner
+      - video
+  site:
+    mediaTypes:
+      - banner
+      - video
diff --git a/static/bidder-params/mobfoxpb.json b/static/bidder-params/mobfoxpb.json
new file mode 100644
index 00000000..0cc7a16c
--- /dev/null
+++ b/static/bidder-params/mobfoxpb.json
@@ -0,0 +1,14 @@
+{
+  "$schema": "http://json-schema.org/draft-04/schema#",
+  "title": "Mobfox Adapter Params",
+  "description": "A schema which validates params accepted by the Mobfox adapter",
+  "type": "object",
+  "properties": {
+    "TagID": {
+      "type": "string",
+      "minLength": 1,
+      "description": "An ID which identifies the mobfox ad tag"
+    }
+  },
+  "required" : [ "TagID" ]
+}


Test patch:
diff --git a/adapters/mobfoxpb/mobfoxpb_test.go b/adapters/mobfoxpb/mobfoxpb_test.go
new file mode 100644
index 00000000..271d30a9
--- /dev/null
+++ b/adapters/mobfoxpb/mobfoxpb_test.go
@@ -0,0 +1,18 @@
+package mobfoxpb
+
+import (
+	"testing"
+
+	"github.com/prebid/prebid-server/adapters/adapterstest"
+	"github.com/prebid/prebid-server/config"
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+func TestJsonSamples(t *testing.T) {
+	bidder, buildErr := Builder(openrtb_ext.BidderMobfoxpb, config.Adapter{
+		Endpoint: "http://example.com/?c=o&m=ortb"})
+	if buildErr != nil {
+		t.Fatalf("Builder returned unexpected error %v", buildErr)
+	}
+	adapterstest.RunJSONBidderTest(t, "mobfoxpbtest", bidder)
+}
diff --git a/adapters/mobfoxpb/mobfoxpbtest/exemplary/simple-banner.json b/adapters/mobfoxpb/mobfoxpbtest/exemplary/simple-banner.json
new file mode 100644
index 00000000..b1936661
--- /dev/null
+++ b/adapters/mobfoxpb/mobfoxpbtest/exemplary/simple-banner.json
@@ -0,0 +1,132 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+        {
+            "id": "test-imp-id",
+            "banner": {
+                "format": [
+                    {
+                      "w": 300,
+                      "h": 250
+                    },
+                    {
+                      "w": 300,
+                      "h": 600
+                    }
+                ]
+            },
+            "tagid": "6",
+            "ext": {
+                "bidder": {
+                  "TagID": "6"
+                }
+            }
+        }
+    ],
+    "app": {
+      "id": "1",
+      "bundle": "com.wls.testwlsapplication"
+    },
+    "device": {
+      "ip": "123.123.123.123",
+      "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx"
+    }
+},
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://example.com/?c=o&m=ortb",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+              {
+                "id": "test-imp-id",
+                "banner": {
+                  "format": [
+                  {
+                    "w": 300,
+                    "h": 250
+                  },
+                  {
+                    "w": 300,
+                    "h": 600
+                  }
+                ]
+              },
+                "tagid": "6",
+                "ext": {
+                  "bidder": {
+                  "TagID": "6"
+                }
+              }
+            }
+          ],
+          "app": {
+            "id": "1",
+            "bundle": "com.wls.testwlsapplication"
+          },
+          "device": {
+            "ip": "123.123.123.123",
+            "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx"
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-request-id",
+          "seatbid": [
+              {
+                "bid": [
+                  {
+                    "id": "test_bid_id",
+                    "impid": "test-imp-id",
+                    "price": 0.27543,
+                    "adm": "<iframe id=\"adm-banner-16\" width=\"300\" height=\"250\" frameborder=\"0\" marginheight=\"0\" marginwidth=\"0\" style=\"{overflow:hidden}\" src=\"https://bes.mobfox.com/?c=o&m=adm&k=882b2510ed6d6c94fa69c99aa522a708\"></iframe>",
+                    "cid": "test_cid",
+                    "crid": "test_crid",
+                    "dealid": "test_dealid",
+                    "w": 300,
+                    "h": 250,
+                    "ext": {
+                      "prebid": {
+                        "type": "banner"
+                      }
+                    }
+                  }
+                ]
+              }
+          ]
+        }
+      }
+    }
+  ],
+
+  "expectedBidResponses": [
+    {
+      "bids":[
+        {
+          "bid":  {
+            "id": "test_bid_id",
+            "impid": "test-imp-id",
+            "price": 0.27543,
+            "adm": "<iframe id=\"adm-banner-16\" width=\"300\" height=\"250\" frameborder=\"0\" marginheight=\"0\" marginwidth=\"0\" style=\"{overflow:hidden}\" src=\"https://bes.mobfox.com/?c=o&m=adm&k=882b2510ed6d6c94fa69c99aa522a708\"></iframe>",
+            "cid": "test_cid",
+            "crid": "test_crid",
+            "dealid": "test_dealid",
+            "w": 300,
+            "h": 250,
+            "ext": {
+              "prebid": {
+                "type": "banner"
+              }
+            }
+          },
+          "type": "banner"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/mobfoxpb/mobfoxpbtest/exemplary/simple-video.json b/adapters/mobfoxpb/mobfoxpbtest/exemplary/simple-video.json
new file mode 100644
index 00000000..6cdcdc5a
--- /dev/null
+++ b/adapters/mobfoxpb/mobfoxpbtest/exemplary/simple-video.json
@@ -0,0 +1,119 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "device": {
+      "ip": "123.123.123.123",
+      "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx"
+    },
+    "app": {
+      "id": "1",
+      "bundle": "com.wls.testwlsapplication"
+    },
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "video": {
+          "mimes": ["video/mp4"],
+          "protocols": [2, 5],
+          "w": 1024,
+          "h": 576
+        },
+        "ext": {
+          "bidder": {
+            "TagID": "7"
+          }
+        }
+      }
+    ]
+  },
+
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://example.com/?c=o&m=ortb",
+        "body": {
+          "id": "test-request-id",
+          "device": {
+            "ip": "123.123.123.123",
+            "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx"
+          },
+          "app": {
+            "id": "1",
+            "bundle": "com.wls.testwlsapplication"
+          },
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "video": {
+                "mimes": ["video/mp4"],
+                "protocols": [2, 5],
+                "w": 1024,
+                "h": 576
+              },
+              "tagid": "7",
+              "ext": {
+                "bidder": {
+                  "TagID": "7"
+                }
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-request-id",
+          "seatbid": [
+          {
+            "bid": [
+              {
+                "id": "test_bid_id",
+                "impid": "test-imp-id",
+                "price": 0.27543,
+                "adm": "<VAST version=\"3.0\"><Ad id=\"20001\" sequence=\"1\"><InLine><AdSystem version=\"4.0\"><![CDATA[iabtechlab]]></AdSystem><AdTitle><![CDATA[Inline Simple Ad]]></AdTitle><Impression><![CDATA[]]></Impression><Creatives><Creative id=\"5480\" sequence=\"1\"><Linear><Duration>00:01:00</Duration><MediaFiles><MediaFile id=\"5246\" delivery=\"progressive\" type=\"video/mp4\" bitrate=\"600\" width=\"640\" height=\"360\" minBitrate=\"500\" maxBitrate=\"700\" scalable=\"1\" maintainAspectRatio=\"1\" codec=\"0\"><![CDATA[https://s0.2mdn.net/4253510/google_ddm_animation_480P.mp4]]></MediaFile></MediaFiles><VideoClicks><ClickThrough id=\"blog\"><![CDATA[https://example.com]]></ClickThrough></VideoClicks></Linear></Creative></Creatives></InLine></Ad></VAST>",
+                "cid": "test_cid",
+                "crid": "test_crid",
+                "dealid": "test_dealid",
+                "ext": {
+                  "prebid": {
+                    "type": "video"
+                  }
+                }
+              }
+            ],
+            "seat": "mobfoxpb"
+          }
+          ],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+
+
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "test_bid_id",
+            "impid": "test-imp-id",
+            "price": 0.27543,
+            "adm": "<VAST version=\"3.0\"><Ad id=\"20001\" sequence=\"1\"><InLine><AdSystem version=\"4.0\"><![CDATA[iabtechlab]]></AdSystem><AdTitle><![CDATA[Inline Simple Ad]]></AdTitle><Impression><![CDATA[]]></Impression><Creatives><Creative id=\"5480\" sequence=\"1\"><Linear><Duration>00:01:00</Duration><MediaFiles><MediaFile id=\"5246\" delivery=\"progressive\" type=\"video/mp4\" bitrate=\"600\" width=\"640\" height=\"360\" minBitrate=\"500\" maxBitrate=\"700\" scalable=\"1\" maintainAspectRatio=\"1\" codec=\"0\"><![CDATA[https://s0.2mdn.net/4253510/google_ddm_animation_480P.mp4]]></MediaFile></MediaFiles><VideoClicks><ClickThrough id=\"blog\"><![CDATA[https://example.com]]></ClickThrough></VideoClicks></Linear></Creative></Creatives></InLine></Ad></VAST>",
+            "cid": "test_cid",
+            "crid": "test_crid",
+            "dealid": "test_dealid",
+            "ext": {
+              "prebid": {
+                "type": "video"
+              }
+            }
+          },
+          "type": "video"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/mobfoxpb/mobfoxpbtest/exemplary/simple-web-banner.json b/adapters/mobfoxpb/mobfoxpbtest/exemplary/simple-web-banner.json
new file mode 100644
index 00000000..bba728ac
--- /dev/null
+++ b/adapters/mobfoxpb/mobfoxpbtest/exemplary/simple-web-banner.json
@@ -0,0 +1,130 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            },
+            {
+              "w": 300,
+              "h": 600
+            }
+          ]
+        },
+        "tagid": "8",
+        "ext": {
+          "bidder": {
+            "TagID": "8"
+          }
+        }
+      }
+    ],
+    "site": {
+      "id": "1",
+      "domain": "test.com"
+    },
+    "device": {
+      "ip": "123.123.123.123"
+    }
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://example.com/?c=o&m=ortb",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "banner": {
+                "format": [
+                  {
+                    "w": 300,
+                    "h": 250
+                  },
+                  {
+                    "w": 300,
+                    "h": 600
+                  }
+                ]
+              },
+              "tagid": "8",
+              "ext": {
+                "bidder": {
+                  "TagID": "8"
+                }
+              }
+            }
+          ],
+          "site": {
+            "id": "1",
+            "domain": "test.com"
+          },
+          "device": {
+            "ip": "123.123.123.123"
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-request-id",
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "id": "test_bid_id",
+                  "impid": "test-imp-id",
+                  "price": 0.27543,
+                  "adm": "<iframe id=\"adm-banner-1\" width=\"468\" height=\"60\" frameborder=\"0\" marginheight=\"0\" marginwidth=\"0\" style=\"{overflow:hidden}\" src=\"https://bes.mobfox.com/?c=o&m=adm&k=bc2d316f39931a07d9a8dd249bf85fc0\"></iframe>",
+                  "cid": "test_cid",
+                  "crid": "test_crid",
+                  "dealid": "test_dealid",
+                  "w": 468,
+                  "h": 60,
+                  "ext": {
+                    "prebid": {
+                      "type": "banner"
+                    }
+                  }
+                }
+              ],
+              "seat": "mobfoxpb"
+            }
+          ],
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "bids": [
+        {
+          "bid": {
+            "id": "test_bid_id",
+            "impid": "test-imp-id",
+            "price": 0.27543,
+            "adm": "<iframe id=\"adm-banner-1\" width=\"468\" height=\"60\" frameborder=\"0\" marginheight=\"0\" marginwidth=\"0\" style=\"{overflow:hidden}\" src=\"https://bes.mobfox.com/?c=o&m=adm&k=bc2d316f39931a07d9a8dd249bf85fc0\"></iframe>",
+            "cid": "test_cid",
+            "crid": "test_crid",
+            "dealid": "test_dealid",
+            "w": 468,
+            "h": 60,
+            "ext": {
+              "prebid": {
+                "type": "banner"
+              }
+            }
+          },
+          "type": "banner"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/mobfoxpb/mobfoxpbtest/params/race/banner.json b/adapters/mobfoxpb/mobfoxpbtest/params/race/banner.json
new file mode 100644
index 00000000..dbdac1ad
--- /dev/null
+++ b/adapters/mobfoxpb/mobfoxpbtest/params/race/banner.json
@@ -0,0 +1,3 @@
+{
+  "TagID": "6"
+}
\ No newline at end of file
diff --git a/adapters/mobfoxpb/mobfoxpbtest/params/race/video.json b/adapters/mobfoxpb/mobfoxpbtest/params/race/video.json
new file mode 100644
index 00000000..6e2e0b38
--- /dev/null
+++ b/adapters/mobfoxpb/mobfoxpbtest/params/race/video.json
@@ -0,0 +1,3 @@
+{
+  "TagID": "7"
+}
\ No newline at end of file
diff --git a/adapters/mobfoxpb/mobfoxpbtest/supplemental/bad-imp-ext.json b/adapters/mobfoxpb/mobfoxpbtest/supplemental/bad-imp-ext.json
new file mode 100644
index 00000000..ac3dce59
--- /dev/null
+++ b/adapters/mobfoxpb/mobfoxpbtest/supplemental/bad-imp-ext.json
@@ -0,0 +1,42 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            },
+            {
+              "w": 300,
+              "h": 600
+            }
+          ]
+        },
+        "tagid": "6",
+        "ext": {
+          "mobfoxpb": {
+            "TagID": "6"
+          }
+        }
+      }
+    ],
+    "app": {
+      "id": "1",
+      "bundle": "com.wls.testwlsapplication"
+    },
+    "device": {
+      "ip": "123.123.123.123",
+      "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx"
+    }
+  },
+  "expectedMakeRequestsErrors": [
+    {
+      "value": "Key path not found",
+      "comparison": "literal"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/mobfoxpb/mobfoxpbtest/supplemental/bad_response.json b/adapters/mobfoxpb/mobfoxpbtest/supplemental/bad_response.json
new file mode 100644
index 00000000..2f834c92
--- /dev/null
+++ b/adapters/mobfoxpb/mobfoxpbtest/supplemental/bad_response.json
@@ -0,0 +1,87 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            },
+            {
+              "w": 300,
+              "h": 600
+            }
+          ]
+        },
+        "tagid": "17",
+        "ext": {
+          "bidder": {
+            "TagID": "17"
+          }
+        }
+      }
+    ],
+    "app": {
+      "id": "1",
+      "bundle": "com.wls.testwlsapplication"
+    },
+    "device": {
+      "ip": "123.123.123.123",
+      "ifa": "sdjfksdf-dfsds-dsdg-dsgg"
+    }
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://example.com/?c=o&m=ortb",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "banner": {
+                "format": [
+                  {
+                    "w": 300,
+                    "h": 250
+                  },
+                  {
+                    "w": 300,
+                    "h": 600
+                  }
+                ]
+              },
+              "tagid": "17",
+              "ext": {
+                "bidder": {
+                  "TagID": "17"
+                }
+              }
+            }
+          ],
+          "app": {
+            "id": "1",
+            "bundle": "com.wls.testwlsapplication"
+          },
+          "device": {
+            "ip": "123.123.123.123",
+            "ifa": "sdjfksdf-dfsds-dsdg-dsgg"
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": ""
+      }
+    }
+  ],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "json: cannot unmarshal string into Go value of type openrtb.BidResponse",
+      "comparison": "literal"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/mobfoxpb/mobfoxpbtest/supplemental/bad_status_code.json b/adapters/mobfoxpb/mobfoxpbtest/supplemental/bad_status_code.json
new file mode 100644
index 00000000..96d3a649
--- /dev/null
+++ b/adapters/mobfoxpb/mobfoxpbtest/supplemental/bad_status_code.json
@@ -0,0 +1,81 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            },
+            {
+              "w": 300,
+              "h": 600
+            }
+          ]
+        },
+        "tagid": "100000000",
+        "ext": {
+          "bidder": {
+            "TagID": "100000000"
+          }
+        }
+      }
+    ],
+    "app": {
+      "id": "1",
+      "bundle": "com.wls.testwlsapplication"
+    },
+    "device": {}
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://example.com/?c=o&m=ortb",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "banner": {
+                "format": [
+                  {
+                    "w": 300,
+                    "h": 250
+                  },
+                  {
+                    "w": 300,
+                    "h": 600
+                  }
+                ]
+              },
+              "tagid": "100000000",
+              "ext": {
+                "bidder": {
+                  "TagID": "100000000"
+                }
+              }
+            }
+          ],
+          "app": {
+            "id": "1",
+            "bundle": "com.wls.testwlsapplication"
+          },
+          "device": {}
+        }
+      },
+      "mockResponse": {
+        "status": 400,
+        "body": {}
+      }
+    }
+  ],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Unexpected status code: 400. Run with request.debug = 1 for more info",
+      "comparison": "literal"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/mobfoxpb/mobfoxpbtest/supplemental/imp_ext_empty_object.json b/adapters/mobfoxpb/mobfoxpbtest/supplemental/imp_ext_empty_object.json
new file mode 100644
index 00000000..cc56fa25
--- /dev/null
+++ b/adapters/mobfoxpb/mobfoxpbtest/supplemental/imp_ext_empty_object.json
@@ -0,0 +1,38 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            },
+            {
+              "w": 300,
+              "h": 600
+            }
+          ]
+        },
+        "tagid": "6",
+        "ext": {}
+      }
+    ],
+    "app": {
+      "id": "1",
+      "bundle": "com.wls.testwlsapplication"
+    },
+    "device": {
+      "ip": "123.123.123.123",
+      "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx"
+    }
+  },
+  "expectedMakeRequestsErrors": [
+    {
+      "value": "Key path not found",
+      "comparison": "literal"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/mobfoxpb/mobfoxpbtest/supplemental/imp_ext_string.json b/adapters/mobfoxpb/mobfoxpbtest/supplemental/imp_ext_string.json
new file mode 100644
index 00000000..464c9e31
--- /dev/null
+++ b/adapters/mobfoxpb/mobfoxpbtest/supplemental/imp_ext_string.json
@@ -0,0 +1,38 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            },
+            {
+              "w": 300,
+              "h": 600
+            }
+          ]
+        },
+        "tagid": "6",
+        "ext": ""
+      }
+    ],
+    "app": {
+      "id": "1",
+      "bundle": "com.wls.testwlsapplication"
+    },
+    "device": {
+      "ip": "123.123.123.123",
+      "ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx"
+    }
+  },
+  "expectedMakeRequestsErrors": [
+    {
+      "value": "Key path not found",
+      "comparison": "literal"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/mobfoxpb/mobfoxpbtest/supplemental/status-204.json b/adapters/mobfoxpb/mobfoxpbtest/supplemental/status-204.json
new file mode 100644
index 00000000..c1091969
--- /dev/null
+++ b/adapters/mobfoxpb/mobfoxpbtest/supplemental/status-204.json
@@ -0,0 +1,82 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            },
+            {
+              "w": 300,
+              "h": 600
+            }
+          ]
+        },
+        "tagid": "17",
+        "ext": {
+          "bidder": {
+            "TagID": "17"
+          }
+        }
+      }
+    ],
+    "app": {
+      "id": "1",
+      "bundle": "com.wls.testwlsapplication"
+    },
+    "device": {
+      "ip": "123.123.123.123",
+      "ifa": "sdjfksdf-dfsds-dsdg-dsgg"
+    }
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://example.com/?c=o&m=ortb",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "banner": {
+                "format": [
+                  {
+                    "w": 300,
+                    "h": 250
+                  },
+                  {
+                    "w": 300,
+                    "h": 600
+                  }
+                ]
+              },
+              "tagid": "17",
+              "ext": {
+                "bidder": {
+                  "TagID": "17"
+                }
+              }
+            }
+          ],
+          "app": {
+            "id": "1",
+            "bundle": "com.wls.testwlsapplication"
+          },
+          "device": {
+            "ip": "123.123.123.123",
+            "ifa": "sdjfksdf-dfsds-dsdg-dsgg"
+          }
+        }
+      },
+      "expectedBidResponses": [],
+      "mockResponse": {
+        "status": 204,
+        "body": {}
+      }
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/mobfoxpb/mobfoxpbtest/supplemental/status-404.json b/adapters/mobfoxpb/mobfoxpbtest/supplemental/status-404.json
new file mode 100644
index 00000000..d9ef7108
--- /dev/null
+++ b/adapters/mobfoxpb/mobfoxpbtest/supplemental/status-404.json
@@ -0,0 +1,87 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            },
+            {
+              "w": 300,
+              "h": 600
+            }
+          ]
+        },
+        "tagid": "100000000",
+        "ext": {
+          "bidder": {
+            "TagID": "100000000"
+          }
+        }
+      }
+    ],
+    "app": {
+      "id": "1",
+      "bundle": "com.wls.testwlsapplication"
+    },
+    "device": {
+      "ip": "123.123.123.123",
+      "ifa": "sdjfksdf-dfsds-dsdg-dsgg"
+    }
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://example.com/?c=o&m=ortb",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "banner": {
+                "format": [
+                  {
+                    "w": 300,
+                    "h": 250
+                  },
+                  {
+                    "w": 300,
+                    "h": 600
+                  }
+                ]
+              },
+              "tagid": "100000000",
+              "ext": {
+                "bidder": {
+                  "TagID": "100000000"
+                }
+              }
+            }
+          ],
+          "app": {
+            "id": "1",
+            "bundle": "com.wls.testwlsapplication"
+          },
+          "device": {
+            "ip": "123.123.123.123",
+            "ifa": "sdjfksdf-dfsds-dsdg-dsgg"
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 404,
+        "body": {}
+      }
+    }
+  ],
+  "expectedMakeBidsErrors": [
+    {
+      "value": "Unexpected status code: 404. Run with request.debug = 1 for more info",
+      "comparison": "literal"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/mobfoxpb/params_test.go b/adapters/mobfoxpb/params_test.go
new file mode 100644
index 00000000..59b9ec38
--- /dev/null
+++ b/adapters/mobfoxpb/params_test.go
@@ -0,0 +1,47 @@
+package mobfoxpb
+
+import (
+	"encoding/json"
+	"testing"
+
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+// TestValidParams makes sure that the mobfoxpb schema accepts all imp.ext fields which we intend to support.
+func TestValidParams(t *testing.T) {
+	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
+	if err != nil {
+		t.Fatalf("Failed to fetch the json-schemas. %v", err)
+	}
+
+	for _, validParam := range validParams {
+		if err := validator.Validate(openrtb_ext.BidderMobfoxpb, json.RawMessage(validParam)); err != nil {
+			t.Errorf("Schema rejected mobfoxpb params: %s", validParam)
+		}
+	}
+}
+
+// TestInvalidParams makes sure that the mobfoxpb schema rejects all the imp.ext fields we don't support.
+func TestInvalidParams(t *testing.T) {
+	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
+	if err != nil {
+		t.Fatalf("Failed to fetch the json-schemas. %v", err)
+	}
+
+	for _, invalidParam := range invalidParams {
+		if err := validator.Validate(openrtb_ext.BidderMobfoxpb, json.RawMessage(invalidParam)); err == nil {
+			t.Errorf("Schema allowed unexpected params: %s", invalidParam)
+		}
+	}
+}
+
+var validParams = []string{
+	`{"TagID": "6"}`,
+}
+
+var invalidParams = []string{
+	`{"id": "123"}`,
+	`{"tagid": "123"}`,
+	`{"TagID": 16}`,
+	`{"TagID": ""}`,
+}
diff --git a/endpoints/auction_test.go b/endpoints/auction_test.go
index f7f915cb..b5f0989e 100644
--- a/endpoints/auction_test.go
+++ b/endpoints/auction_test.go
@@ -424,10 +424,6 @@ func (m *auctionMockPermissions) PersonalInfoAllowed(ctx context.Context, bidder
 	return m.allowPI, m.allowGeo, m.allowID, nil
 }
 
-func (m *auctionMockPermissions) AMPException() bool {
-	return false
-}
-
 func TestBidSizeValidate(t *testing.T) {
 	bids := make(pbs.PBSBidSlice, 0)
 	// bid1 will be rejected due to undefined size when adunit has multiple sizes
diff --git a/endpoints/cookie_sync_test.go b/endpoints/cookie_sync_test.go
index 77be2590..ee29125b 100644
--- a/endpoints/cookie_sync_test.go
+++ b/endpoints/cookie_sync_test.go
@@ -257,7 +257,3 @@ func (g *gdprPerms) BidderSyncAllowed(ctx context.Context, bidder openrtb_ext.Bi
 func (g *gdprPerms) PersonalInfoAllowed(ctx context.Context, bidder openrtb_ext.BidderName, PublisherID string, consent string) (bool, bool, bool, error) {
 	return true, true, true, nil
 }
-
-func (g *gdprPerms) AMPException() bool {
-	return false
-}
diff --git a/endpoints/setuid_test.go b/endpoints/setuid_test.go
index ae063677..1f2c4040 100644
--- a/endpoints/setuid_test.go
+++ b/endpoints/setuid_test.go
@@ -441,10 +441,6 @@ func (g *mockPermsSetUID) PersonalInfoAllowed(ctx context.Context, bidder openrt
 	return g.allowPI, g.allowPI, g.allowPI, nil
 }
 
-func (g *mockPermsSetUID) AMPException() bool {
-	return false
-}
-
 func newFakeSyncer(familyName string) usersync.Usersyncer {
 	return fakeSyncer{
 		familyName: familyName,
diff --git a/exchange/utils_test.go b/exchange/utils_test.go
index 5fb5707c..757eb658 100644
--- a/exchange/utils_test.go
+++ b/exchange/utils_test.go
@@ -34,10 +34,6 @@ func (p *permissionsMock) PersonalInfoAllowed(ctx context.Context, bidder openrt
 	return p.personalInfoAllowed, p.personalInfoAllowed, p.personalInfoAllowed, nil
 }
 
-func (p *permissionsMock) AMPException() bool {
-	return false
-}
-
 func assertReq(t *testing.T, bidderRequests []BidderRequest,
 	applyCOPPA bool, consentedVendors map[string]bool) {
 	// assert individual bidder requests
diff --git a/privacy/enforcement_test.go b/privacy/enforcement_test.go
index 0cf36a61..9240aafc 100644
--- a/privacy/enforcement_test.go
+++ b/privacy/enforcement_test.go
@@ -59,7 +59,6 @@ func TestApply(t *testing.T) {
 	testCases := []struct {
 		description        string
 		enforcement        Enforcement
-		ampGDPRException   bool
 		expectedDeviceID   ScrubStrategyDeviceID
 		expectedDeviceIPv4 ScrubStrategyIPV4
 		expectedDeviceIPv6 ScrubStrategyIPV6
@@ -124,7 +123,6 @@ func TestApply(t *testing.T) {
 				GDPRID:  true,
 				LMT:     false,
 			},
-			ampGDPRException:   false,
 			expectedDeviceID:   ScrubStrategyDeviceIDAll,
 			expectedDeviceIPv4: ScrubStrategyIPV4Lowest8,
 			expectedDeviceIPv6: ScrubStrategyIPV6Lowest16,
@@ -132,23 +130,6 @@ func TestApply(t *testing.T) {
 			expectedUser:       ScrubStrategyUserID,
 			expectedUserGeo:    ScrubStrategyGeoReducedPrecision,
 		},
-		{
-			description: "GDPR Only - Full - AMP Exception",
-			enforcement: Enforcement{
-				CCPA:    false,
-				COPPA:   false,
-				GDPRGeo: true,
-				GDPRID:  true,
-				LMT:     false,
-			},
-			ampGDPRException:   true,
-			expectedDeviceID:   ScrubStrategyDeviceIDAll,
-			expectedDeviceIPv4: ScrubStrategyIPV4Lowest8,
-			expectedDeviceIPv6: ScrubStrategyIPV6Lowest16,
-			expectedDeviceGeo:  ScrubStrategyGeoReducedPrecision,
-			expectedUser:       ScrubStrategyUserNone,
-			expectedUserGeo:    ScrubStrategyGeoReducedPrecision,
-		},
 		{
 			description: "GDPR Only - ID Only",
 			enforcement: Enforcement{
@@ -158,7 +139,6 @@ func TestApply(t *testing.T) {
 				GDPRID:  true,
 				LMT:     false,
 			},
-			ampGDPRException:   false,
 			expectedDeviceID:   ScrubStrategyDeviceIDAll,
 			expectedDeviceIPv4: ScrubStrategyIPV4None,
 			expectedDeviceIPv6: ScrubStrategyIPV6None,
@@ -166,23 +146,6 @@ func TestApply(t *testing.T) {
 			expectedUser:       ScrubStrategyUserID,
 			expectedUserGeo:    ScrubStrategyGeoNone,
 		},
-		{
-			description: "GDPR Only - ID Only - AMP Exception",
-			enforcement: Enforcement{
-				CCPA:    false,
-				COPPA:   false,
-				GDPRGeo: false,
-				GDPRID:  true,
-				LMT:     false,
-			},
-			ampGDPRException:   true,
-			expectedDeviceID:   ScrubStrategyDeviceIDAll,
-			expectedDeviceIPv4: ScrubStrategyIPV4None,
-			expectedDeviceIPv6: ScrubStrategyIPV6None,
-			expectedDeviceGeo:  ScrubStrategyGeoNone,
-			expectedUser:       ScrubStrategyUserNone,
-			expectedUserGeo:    ScrubStrategyGeoNone,
-		},
 		{
 			description: "GDPR Only - Geo Only",
 			enforcement: Enforcement{
@@ -192,7 +155,6 @@ func TestApply(t *testing.T) {
 				GDPRID:  false,
 				LMT:     false,
 			},
-			ampGDPRException:   false,
 			expectedDeviceID:   ScrubStrategyDeviceIDNone,
 			expectedDeviceIPv4: ScrubStrategyIPV4Lowest8,
 			expectedDeviceIPv6: ScrubStrategyIPV6Lowest16,
@@ -217,24 +179,7 @@ func TestApply(t *testing.T) {
 			expectedUserGeo:    ScrubStrategyGeoReducedPrecision,
 		},
 		{
-			description: "Interactions: COPPA Only + AMP Exception",
-			enforcement: Enforcement{
-				CCPA:    false,
-				COPPA:   true,
-				GDPRGeo: false,
-				GDPRID:  false,
-				LMT:     false,
-			},
-			ampGDPRException:   true,
-			expectedDeviceID:   ScrubStrategyDeviceIDAll,
-			expectedDeviceIPv4: ScrubStrategyIPV4Lowest8,
-			expectedDeviceIPv6: ScrubStrategyIPV6Lowest32,
-			expectedDeviceGeo:  ScrubStrategyGeoFull,
-			expectedUser:       ScrubStrategyUserIDAndDemographic,
-			expectedUserGeo:    ScrubStrategyGeoFull,
-		},
-		{
-			description: "Interactions: COPPA + GDPR Full + AMP Exception",
+			description: "Interactions: COPPA + GDPR Full",
 			enforcement: Enforcement{
 				CCPA:    false,
 				COPPA:   true,
@@ -242,7 +187,6 @@ func TestApply(t *testing.T) {
 				GDPRID:  true,
 				LMT:     false,
 			},
-			ampGDPRException:   true,
 			expectedDeviceID:   ScrubStrategyDeviceIDAll,
 			expectedDeviceIPv4: ScrubStrategyIPV4Lowest8,
 			expectedDeviceIPv6: ScrubStrategyIPV6Lowest32,
@@ -264,7 +208,7 @@ func TestApply(t *testing.T) {
 		m.On("ScrubDevice", req.Device, test.expectedDeviceID, test.expectedDeviceIPv4, test.expectedDeviceIPv6, test.expectedDeviceGeo).Return(replacedDevice).Once()
 		m.On("ScrubUser", req.User, test.expectedUser, test.expectedUserGeo).Return(replacedUser).Once()
 
-		test.enforcement.apply(req, test.ampGDPRException, m)
+		test.enforcement.apply(req, m)
 
 		m.AssertExpectations(t)
 		assert.Same(t, replacedDevice, req.Device, "Device")
@@ -284,7 +228,7 @@ func TestApplyNoneApplicable(t *testing.T) {
 		GDPRID:  false,
 		LMT:     false,
 	}
-	enforcement.apply(req, false, m)
+	enforcement.apply(req, m)
 
 	m.AssertNotCalled(t, "ScrubDevice")
 	m.AssertNotCalled(t, "ScrubUser")
@@ -294,7 +238,7 @@ func TestApplyNil(t *testing.T) {
 	m := &mockScrubber{}
 
 	enforcement := Enforcement{}
-	enforcement.apply(nil, false, m)
+	enforcement.apply(nil, m)
 
 	m.AssertNotCalled(t, "ScrubDevice")
 	m.AssertNotCalled(t, "ScrubUser")
diff --git a/usersync/usersyncers/syncer_test.go b/usersync/usersyncers/syncer_test.go
index dc4ca0a6..60ab2478 100755
--- a/usersync/usersyncers/syncer_test.go
+++ b/usersync/usersyncers/syncer_test.go
@@ -101,6 +101,7 @@ func TestNewSyncerMap(t *testing.T) {
 		openrtb_ext.BidderInMobi:       true,
 		openrtb_ext.BidderKidoz:        true,
 		openrtb_ext.BidderKubient:      true,
+		openrtb_ext.BidderMobfoxpb:     true,
 		openrtb_ext.BidderMobileFuse:   true,
 		openrtb_ext.BidderOrbidder:     true,
 		openrtb_ext.BidderPubnative:    true,