Repository: prebid/prebid-server
Pull request #1858 (2021-05-21 14:12:59)

Rename GDPR UserSyncIfAmbiguous to DefaultValue
Addresses the first part of #1783


Patch:
diff --git a/config/config.go b/config/config.go
index 7e24a00d..1260d28a 100644
--- a/config/config.go
+++ b/config/config.go
@@ -193,7 +193,7 @@ type Privacy struct {
 type GDPR struct {
 	Enabled                 bool         `mapstructure:"enabled"`
 	HostVendorID            int          `mapstructure:"host_vendor_id"`
-	UsersyncIfAmbiguous     bool         `mapstructure:"usersync_if_ambiguous"`
+	DefaultValue            string       `mapstructure:"default_value"`
 	Timeouts                GDPRTimeouts `mapstructure:"timeouts_ms"`
 	NonStandardPublishers   []string     `mapstructure:"non_standard_publishers,flow"`
 	NonStandardPublisherMap map[string]struct{}
@@ -202,12 +202,15 @@ type GDPR struct {
 	// EEACountries (EEA = European Economic Area) are a list of countries where we should assume GDPR applies.
 	// If the gdpr flag is unset in a request, but geo.country is set, we will assume GDPR applies if and only
 	// if the country matches one on this list. If both the GDPR flag and country are not set, we default
-	// to UsersyncIfAmbiguous
+	// to DefaultValue
 	EEACountries    []string `mapstructure:"eea_countries"`
 	EEACountriesMap map[string]struct{}
 }
 
 func (cfg *GDPR) validate(errs []error) []error {
+	if cfg.DefaultValue != "0" && cfg.DefaultValue != "1" {
+		errs = append(errs, fmt.Errorf("gdpr.default_value must be 0 or 1"))
+	}
 	if cfg.HostVendorID < 0 || cfg.HostVendorID > 0xffff {
 		errs = append(errs, fmt.Errorf("gdpr.host_vendor_id must be in the range [0, %d]. Got %d", 0xffff, cfg.HostVendorID))
 	}
@@ -937,7 +940,7 @@ func SetupViper(v *viper.Viper, filename string) {
 	v.SetDefault("amp_timeout_adjustment_ms", 0)
 	v.SetDefault("gdpr.enabled", true)
 	v.SetDefault("gdpr.host_vendor_id", 0)
-	v.SetDefault("gdpr.usersync_if_ambiguous", false)
+	v.SetDefault("gdpr.default_value", "1")
 	v.SetDefault("gdpr.timeouts_ms.init_vendorlist_fetches", 0)
 	v.SetDefault("gdpr.timeouts_ms.active_vendorlist_fetch", 0)
 	v.SetDefault("gdpr.non_standard_publishers", []string{""})
diff --git a/endpoints/cookie_sync.go b/endpoints/cookie_sync.go
index bf3935f0..3c1354c8 100644
--- a/endpoints/cookie_sync.go
+++ b/endpoints/cookie_sync.go
@@ -97,7 +97,7 @@ func (deps *cookieSyncDeps) Endpoint(w http.ResponseWriter, r *http.Request, _ h
 	}
 
 	parsedReq := &cookieSyncRequest{}
-	if err := parseRequest(parsedReq, bodyBytes, deps.gDPR.UsersyncIfAmbiguous); err != nil {
+	if err := parseRequest(parsedReq, bodyBytes, deps.gDPR.DefaultValue); err != nil {
 		co.Status = http.StatusBadRequest
 		co.Errors = append(co.Errors, err)
 		http.Error(w, co.Errors[len(co.Errors)-1].Error(), co.Status)
@@ -181,7 +181,7 @@ func (deps *cookieSyncDeps) Endpoint(w http.ResponseWriter, r *http.Request, _ h
 	enc.Encode(csResp)
 }
 
-func parseRequest(parsedReq *cookieSyncRequest, bodyBytes []byte, usersyncIfAmbiguous bool) error {
+func parseRequest(parsedReq *cookieSyncRequest, bodyBytes []byte, gdprDefaultValue string) error {
 	if err := json.Unmarshal(bodyBytes, parsedReq); err != nil {
 		return fmt.Errorf("JSON parsing failed: %s", err.Error())
 	}
@@ -193,7 +193,7 @@ func parseRequest(parsedReq *cookieSyncRequest, bodyBytes []byte, usersyncIfAmbi
 	if parsedReq.GDPR == nil {
 		var gdpr = new(int)
 		*gdpr = 1
-		if usersyncIfAmbiguous {
+		if gdprDefaultValue == "0" {
 			*gdpr = 0
 		}
 		parsedReq.GDPR = gdpr
diff --git a/exchange/exchange.go b/exchange/exchange.go
index 6f0c610a..7b156b5d 100644
--- a/exchange/exchange.go
+++ b/exchange/exchange.go
@@ -51,18 +51,18 @@ type IdFetcher interface {
 }
 
 type exchange struct {
-	adapterMap          map[openrtb_ext.BidderName]adaptedBidder
-	bidderInfo          config.BidderInfos
-	me                  metrics.MetricsEngine
-	cache               prebid_cache_client.Client
-	cacheTime           time.Duration
-	gDPR                gdpr.Permissions
-	currencyConverter   *currency.RateConverter
-	externalURL         string
-	UsersyncIfAmbiguous bool
-	privacyConfig       config.Privacy
-	categoriesFetcher   stored_requests.CategoryFetcher
-	bidIDGenerator      BidIDGenerator
+	adapterMap        map[openrtb_ext.BidderName]adaptedBidder
+	bidderInfo        config.BidderInfos
+	me                metrics.MetricsEngine
+	cache             prebid_cache_client.Client
+	cacheTime         time.Duration
+	gDPR              gdpr.Permissions
+	currencyConverter *currency.RateConverter
+	externalURL       string
+	gdprDefaultValue  string
+	privacyConfig     config.Privacy
+	categoriesFetcher stored_requests.CategoryFetcher
+	bidIDGenerator    BidIDGenerator
 }
 
 // Container to pass out response ext data from the GetAllBids goroutines back into the main thread
@@ -111,16 +111,16 @@ func (randomDeduplicateBidBooleanGenerator) Generate() bool {
 
 func NewExchange(adapters map[openrtb_ext.BidderName]adaptedBidder, cache prebid_cache_client.Client, cfg *config.Configuration, metricsEngine metrics.MetricsEngine, infos config.BidderInfos, gDPR gdpr.Permissions, currencyConverter *currency.RateConverter, categoriesFetcher stored_requests.CategoryFetcher) Exchange {
 	return &exchange{
-		adapterMap:          adapters,
-		bidderInfo:          infos,
-		cache:               cache,
-		cacheTime:           time.Duration(cfg.CacheURL.ExpectedTimeMillis) * time.Millisecond,
-		categoriesFetcher:   categoriesFetcher,
-		currencyConverter:   currencyConverter,
-		externalURL:         cfg.ExternalURL,
-		gDPR:                gDPR,
-		me:                  metricsEngine,
-		UsersyncIfAmbiguous: cfg.GDPR.UsersyncIfAmbiguous,
+		adapterMap:        adapters,
+		bidderInfo:        infos,
+		cache:             cache,
+		cacheTime:         time.Duration(cfg.CacheURL.ExpectedTimeMillis) * time.Millisecond,
+		categoriesFetcher: categoriesFetcher,
+		currencyConverter: currencyConverter,
+		externalURL:       cfg.ExternalURL,
+		gDPR:              gDPR,
+		me:                metricsEngine,
+		gdprDefaultValue:  cfg.GDPR.DefaultValue,
 		privacyConfig: config.Privacy{
 			CCPA: cfg.CCPA,
 			GDPR: cfg.GDPR,
@@ -186,10 +186,10 @@ func (e *exchange) HoldAuction(ctx context.Context, r AuctionRequest, debugLog *
 	recordImpMetrics(r.BidRequest, e.me)
 
 	// Make our best guess if GDPR applies
-	usersyncIfAmbiguous := e.parseUsersyncIfAmbiguous(r.BidRequest)
+	gdprDefaultValue := e.parseGDPRDefaultValue(r.BidRequest)
 
 	// Slice of BidRequests, each a copy of the original cleaned to only contain bidder data for the named bidder
-	bidderRequests, privacyLabels, errs := cleanOpenRTBRequests(ctx, r, requestExt, e.gDPR, e.me, usersyncIfAmbiguous, e.privacyConfig, &r.Account)
+	bidderRequests, privacyLabels, errs := cleanOpenRTBRequests(ctx, r, requestExt, e.gDPR, e.me, gdprDefaultValue, e.privacyConfig, &r.Account)
 
 	e.me.RecordRequestPrivacy(privacyLabels)
 
@@ -301,8 +301,8 @@ func (e *exchange) HoldAuction(ctx context.Context, r AuctionRequest, debugLog *
 	return e.buildBidResponse(ctx, liveAdapters, adapterBids, r.BidRequest, adapterExtra, auc, bidResponseExt, cacheInstructions.returnCreative, errs)
 }
 
-func (e *exchange) parseUsersyncIfAmbiguous(bidRequest *openrtb2.BidRequest) bool {
-	usersyncIfAmbiguous := e.UsersyncIfAmbiguous
+func (e *exchange) parseGDPRDefaultValue(bidRequest *openrtb2.BidRequest) string {
+	gdprDefaultValue := e.gdprDefaultValue
 	var geo *openrtb2.Geo = nil
 
 	if bidRequest.User != nil && bidRequest.User.Geo != nil {
@@ -314,14 +314,14 @@ func (e *exchange) parseUsersyncIfAmbiguous(bidRequest *openrtb2.BidRequest) boo
 		// If we have a country set, and it is on the list, we assume GDPR applies if not set on the request.
 		// Otherwise we assume it does not apply as long as it appears "valid" (is 3 characters long).
 		if _, found := e.privacyConfig.GDPR.EEACountriesMap[strings.ToUpper(geo.Country)]; found {
-			usersyncIfAmbiguous = false
+			gdprDefaultValue = "1"
 		} else if len(geo.Country) == 3 {
 			// The country field is formatted properly as a three character country code
-			usersyncIfAmbiguous = true
+			gdprDefaultValue = "0"
 		}
 	}
 
-	return usersyncIfAmbiguous
+	return gdprDefaultValue
 }
 
 func recordImpMetrics(bidRequest *openrtb2.BidRequest, metricsEngine metrics.MetricsEngine) {
diff --git a/exchange/utils.go b/exchange/utils.go
index 3d5e2374..c5cf6732 100644
--- a/exchange/utils.go
+++ b/exchange/utils.go
@@ -57,7 +57,7 @@ func cleanOpenRTBRequests(ctx context.Context,
 	requestExt *openrtb_ext.ExtRequest,
 	gDPR gdpr.Permissions,
 	metricsEngine metrics.MetricsEngine,
-	usersyncIfAmbiguous bool,
+	gdprDefaultValue string,
 	privacyConfig config.Privacy,
 	account *config.Account) (allowedBidderRequests []BidderRequest, privacyLabels metrics.PrivacyLabels, errs []error) {
 
@@ -87,7 +87,7 @@ func cleanOpenRTBRequests(ctx context.Context,
 	if err != nil {
 		errs = append(errs, err)
 	}
-	gdprEnforced := gdprSignal == gdpr.SignalYes || (gdprSignal == gdpr.SignalAmbiguous && !usersyncIfAmbiguous)
+	gdprEnforced := gdprSignal == gdpr.SignalYes || (gdprSignal == gdpr.SignalAmbiguous && gdprDefaultValue == "1")
 
 	ccpaEnforcer, err := extractCCPA(req.BidRequest, privacyConfig, &req.Account, aliases, integrationTypeMap[req.LegacyLabels.RType])
 	if err != nil {
diff --git a/gdpr/impl.go b/gdpr/impl.go
index aca07fd0..9c09e90b 100644
--- a/gdpr/impl.go
+++ b/gdpr/impl.go
@@ -94,7 +94,7 @@ func (p *permissionsImpl) normalizeGDPR(gdprSignal Signal) Signal {
 		return gdprSignal
 	}
 
-	if p.cfg.UsersyncIfAmbiguous {
+	if p.cfg.DefaultValue == "0" {
 		return SignalNo
 	}
 


Test patch:
diff --git a/config/config_test.go b/config/config_test.go
index f34bd5fa..a2b28d02 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -148,7 +148,7 @@ func TestDefaults(t *testing.T) {
 var fullConfig = []byte(`
 gdpr:
   host_vendor_id: 15
-  usersync_if_ambiguous: true
+  default_value: "0"
   non_standard_publishers: ["siteID","fake-site-id","appID","agltb3B1Yi1pbmNyDAsSA0FwcBiJkfIUDA"]
 ccpa:
   enforce: true
@@ -352,7 +352,7 @@ func TestFullConfig(t *testing.T) {
 	cmpInts(t, "http_client_cache.max_idle_connections_per_host", cfg.CacheClient.MaxIdleConnsPerHost, 2)
 	cmpInts(t, "http_client_cache.idle_connection_timeout_seconds", cfg.CacheClient.IdleConnTimeout, 3)
 	cmpInts(t, "gdpr.host_vendor_id", cfg.GDPR.HostVendorID, 15)
-	cmpBools(t, "gdpr.usersync_if_ambiguous", cfg.GDPR.UsersyncIfAmbiguous, true)
+	cmpStrings(t, "gdpr.default_value", cfg.GDPR.DefaultValue, "0")
 
 	//Assert the NonStandardPublishers was correctly unmarshalled
 	cmpStrings(t, "gdpr.non_standard_publishers", cfg.GDPR.NonStandardPublishers[0], "siteID")
@@ -460,6 +460,9 @@ func TestUnmarshalAdapterExtraInfo(t *testing.T) {
 
 func TestValidConfig(t *testing.T) {
 	cfg := Configuration{
+		GDPR: GDPR{
+			DefaultValue: "1",
+		},
 		StoredRequests: StoredRequests{
 			Files: FileFetcherConfig{Enabled: true},
 			InMemoryCache: InMemoryCache{
@@ -650,6 +653,12 @@ func TestInvalidAMPException(t *testing.T) {
 	assertOneError(t, cfg.validate(), "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)")
 }
 
+func TestInvalidGDPRDefaultValue(t *testing.T) {
+	cfg := newDefaultConfig(t)
+	cfg.GDPR.DefaultValue = "2"
+	assertOneError(t, cfg.validate(), "gdpr.default_value must be 0 or 1")
+}
+
 func TestNegativeCurrencyConverterFetchInterval(t *testing.T) {
 	cfg := Configuration{
 		CurrencyConverter: CurrencyConverter{
diff --git a/endpoints/cookie_sync_test.go b/endpoints/cookie_sync_test.go
index 7632894b..2f56c262 100644
--- a/endpoints/cookie_sync_test.go
+++ b/endpoints/cookie_sync_test.go
@@ -110,7 +110,7 @@ func TestCCPA(t *testing.T) {
 	}
 
 	for _, test := range testCases {
-		gdpr := config.GDPR{UsersyncIfAmbiguous: true}
+		gdpr := config.GDPR{DefaultValue: "0"}
 		ccpa := config.CCPA{Enforce: test.enforceCCPA}
 		rr := doConfigurablePost(test.requestBody, nil, true, syncersForTest(), gdpr, ccpa)
 		assert.Equal(t, http.StatusOK, rr.Code, test.description+":httpResponseCode")
@@ -149,7 +149,7 @@ func TestCookieSyncNoBidders(t *testing.T) {
 }
 
 func TestCookieSyncNoCookiesBrokenGDPR(t *testing.T) {
-	rr := doConfigurablePost(`{"bidders":["appnexus", "audienceNetwork", "random"],"gdpr_consent":"GLKHGKGKKGK"}`, nil, true, map[openrtb_ext.BidderName]usersync.Usersyncer{}, config.GDPR{UsersyncIfAmbiguous: true}, config.CCPA{})
+	rr := doConfigurablePost(`{"bidders":["appnexus", "audienceNetwork", "random"],"gdpr_consent":"GLKHGKGKKGK"}`, nil, true, map[openrtb_ext.BidderName]usersync.Usersyncer{}, config.GDPR{DefaultValue: "0"}, config.CCPA{})
 	assert.Equal(t, rr.Header().Get("Content-Type"), "application/json; charset=utf-8")
 	assert.Equal(t, http.StatusOK, rr.Code)
 	assert.ElementsMatch(t, []string{"appnexus", "audienceNetwork"}, parseSyncs(t, rr.Body.Bytes()))
diff --git a/exchange/exchange_test.go b/exchange/exchange_test.go
index cd36ad94..5a54b5e1 100644
--- a/exchange/exchange_test.go
+++ b/exchange/exchange_test.go
@@ -2004,6 +2004,13 @@ func runSpec(t *testing.T, filename string, spec *exchangeSpec) {
 		eeac[c] = s
 	}
 
+	var gdprDefaultValue string
+	if spec.AssumeGDPRApplies {
+		gdprDefaultValue = "1"
+	} else {
+		gdprDefaultValue = "0"
+	}
+
 	privacyConfig := config.Privacy{
 		CCPA: config.CCPA{
 			Enforce: spec.EnforceCCPA,
@@ -2012,9 +2019,9 @@ func runSpec(t *testing.T, filename string, spec *exchangeSpec) {
 			Enforce: spec.EnforceLMT,
 		},
 		GDPR: config.GDPR{
-			Enabled:             spec.GDPREnabled,
-			UsersyncIfAmbiguous: !spec.AssumeGDPRApplies,
-			EEACountriesMap:     eeac,
+			Enabled:         spec.GDPREnabled,
+			DefaultValue:    gdprDefaultValue,
+			EEACountriesMap: eeac,
 		},
 	}
 	bidIdGenerator := &mockBidIDGenerator{}
@@ -2156,18 +2163,18 @@ func newExchangeForTests(t *testing.T, filename string, expectations map[string]
 	}
 
 	return &exchange{
-		adapterMap:          bidderAdapters,
-		me:                  metricsConf.NewMetricsEngine(&config.Configuration{}, openrtb_ext.CoreBidderNames()),
-		cache:               &wellBehavedCache{},
-		cacheTime:           0,
-		gDPR:                &permissionsMock{allowAllBidders: true},
-		currencyConverter:   currency.NewRateConverter(&http.Client{}, "", time.Duration(0)),
-		UsersyncIfAmbiguous: privacyConfig.GDPR.UsersyncIfAmbiguous,
-		privacyConfig:       privacyConfig,
-		categoriesFetcher:   categoriesFetcher,
-		bidderInfo:          bidderInfos,
-		externalURL:         "http://localhost",
-		bidIDGenerator:      bidIDGenerator,
+		adapterMap:        bidderAdapters,
+		me:                metricsConf.NewMetricsEngine(&config.Configuration{}, openrtb_ext.CoreBidderNames()),
+		cache:             &wellBehavedCache{},
+		cacheTime:         0,
+		gDPR:              &permissionsMock{allowAllBidders: true},
+		currencyConverter: currency.NewRateConverter(&http.Client{}, "", time.Duration(0)),
+		gdprDefaultValue:  privacyConfig.GDPR.DefaultValue,
+		privacyConfig:     privacyConfig,
+		categoriesFetcher: categoriesFetcher,
+		bidderInfo:        bidderInfos,
+		externalURL:       "http://localhost",
+		bidIDGenerator:    bidIDGenerator,
 	}
 }
 
diff --git a/exchange/targeting_test.go b/exchange/targeting_test.go
index aa07ed0c..86646957 100644
--- a/exchange/targeting_test.go
+++ b/exchange/targeting_test.go
@@ -87,15 +87,15 @@ func runTargetingAuction(t *testing.T, mockBids map[openrtb_ext.BidderName][]*op
 	}
 
 	ex := &exchange{
-		adapterMap:          buildAdapterMap(mockBids, server.URL, server.Client()),
-		me:                  &metricsConf.DummyMetricsEngine{},
-		cache:               &wellBehavedCache{},
-		cacheTime:           time.Duration(0),
-		gDPR:                gdpr.AlwaysAllow{},
-		currencyConverter:   currency.NewRateConverter(&http.Client{}, "", time.Duration(0)),
-		UsersyncIfAmbiguous: false,
-		categoriesFetcher:   categoriesFetcher,
-		bidIDGenerator:      &mockBidIDGenerator{false, false},
+		adapterMap:        buildAdapterMap(mockBids, server.URL, server.Client()),
+		me:                &metricsConf.DummyMetricsEngine{},
+		cache:             &wellBehavedCache{},
+		cacheTime:         time.Duration(0),
+		gDPR:              gdpr.AlwaysAllow{},
+		currencyConverter: currency.NewRateConverter(&http.Client{}, "", time.Duration(0)),
+		gdprDefaultValue:  "1",
+		categoriesFetcher: categoriesFetcher,
+		bidIDGenerator:    &mockBidIDGenerator{false, false},
 	}
 
 	imps := buildImps(t, mockBids)
diff --git a/exchange/utils_test.go b/exchange/utils_test.go
index 1788d508..dad0d69d 100644
--- a/exchange/utils_test.go
+++ b/exchange/utils_test.go
@@ -479,7 +479,7 @@ func TestCleanOpenRTBRequests(t *testing.T) {
 	for _, test := range testCases {
 		metricsMock := metrics.MetricsEngineMock{}
 		permissions := permissionsMock{allowAllBidders: true, passGeo: true, passID: true}
-		bidderRequests, _, err := cleanOpenRTBRequests(context.Background(), test.req, nil, &permissions, &metricsMock, true, privacyConfig, nil)
+		bidderRequests, _, err := cleanOpenRTBRequests(context.Background(), test.req, nil, &permissions, &metricsMock, "0", privacyConfig, nil)
 		if test.hasError {
 			assert.NotNil(t, err, "Error shouldn't be nil")
 		} else {
@@ -636,7 +636,7 @@ func TestCleanOpenRTBRequestsCCPA(t *testing.T) {
 			nil,
 			&permissionsMock{allowAllBidders: true, passGeo: true, passID: true},
 			&metrics.MetricsEngineMock{},
-			true,
+			"0",
 			privacyConfig,
 			nil)
 		result := bidderRequests[0]
@@ -698,7 +698,7 @@ func TestCleanOpenRTBRequestsCCPAErrors(t *testing.T) {
 		}
 		permissions := permissionsMock{allowAllBidders: true, passGeo: true, passID: true}
 		metrics := metrics.MetricsEngineMock{}
-		_, _, errs := cleanOpenRTBRequests(context.Background(), auctionReq, &reqExtStruct, &permissions, &metrics, true, privacyConfig, nil)
+		_, _, errs := cleanOpenRTBRequests(context.Background(), auctionReq, &reqExtStruct, &permissions, &metrics, "0", privacyConfig, nil)
 
 		assert.ElementsMatch(t, []error{test.expectError}, errs, test.description)
 	}
@@ -740,7 +740,7 @@ func TestCleanOpenRTBRequestsCOPPA(t *testing.T) {
 
 		permissions := permissionsMock{allowAllBidders: true, passGeo: true, passID: true}
 		metrics := metrics.MetricsEngineMock{}
-		bidderRequests, privacyLabels, errs := cleanOpenRTBRequests(context.Background(), auctionReq, nil, &permissions, &metrics, true, config.Privacy{}, nil)
+		bidderRequests, privacyLabels, errs := cleanOpenRTBRequests(context.Background(), auctionReq, nil, &permissions, &metrics, "0", config.Privacy{}, nil)
 		result := bidderRequests[0]
 
 		assert.Nil(t, errs)
@@ -849,7 +849,7 @@ func TestCleanOpenRTBRequestsSChain(t *testing.T) {
 
 		permissions := permissionsMock{allowAllBidders: true, passGeo: true, passID: true}
 		metrics := metrics.MetricsEngineMock{}
-		bidderRequests, _, errs := cleanOpenRTBRequests(context.Background(), auctionReq, extRequest, &permissions, &metrics, true, config.Privacy{}, nil)
+		bidderRequests, _, errs := cleanOpenRTBRequests(context.Background(), auctionReq, extRequest, &permissions, &metrics, "0", config.Privacy{}, nil)
 		if test.hasError == true {
 			assert.NotNil(t, errs)
 			assert.Len(t, bidderRequests, 0)
@@ -1432,7 +1432,7 @@ func TestCleanOpenRTBRequestsLMT(t *testing.T) {
 
 		permissions := permissionsMock{allowAllBidders: true, passGeo: true, passID: true}
 		metrics := metrics.MetricsEngineMock{}
-		results, privacyLabels, errs := cleanOpenRTBRequests(context.Background(), auctionReq, nil, &permissions, &metrics, true, privacyConfig, nil)
+		results, privacyLabels, errs := cleanOpenRTBRequests(context.Background(), auctionReq, nil, &permissions, &metrics, "0", privacyConfig, nil)
 		result := results[0]
 
 		assert.Nil(t, errs)
@@ -1459,7 +1459,7 @@ func TestCleanOpenRTBRequestsGDPR(t *testing.T) {
 		gdprConsent         string
 		gdprScrub           bool
 		permissionsError    error
-		userSyncIfAmbiguous bool
+		gdprDefaultValue    string
 		expectPrivacyLabels metrics.PrivacyLabels
 		expectError         bool
 	}{
@@ -1470,6 +1470,7 @@ func TestCleanOpenRTBRequestsGDPR(t *testing.T) {
 			gdpr:               "1",
 			gdprConsent:        "malformed",
 			gdprScrub:          false,
+			gdprDefaultValue:   "1",
 			expectPrivacyLabels: metrics.PrivacyLabels{
 				GDPREnforced:   true,
 				GDPRTCFVersion: "",
@@ -1482,6 +1483,7 @@ func TestCleanOpenRTBRequestsGDPR(t *testing.T) {
 			gdpr:               "1",
 			gdprConsent:        tcf2Consent,
 			gdprScrub:          true,
+			gdprDefaultValue:   "1",
 			expectPrivacyLabels: metrics.PrivacyLabels{
 				GDPREnforced:   true,
 				GDPRTCFVersion: metrics.TCFVersionV2,
@@ -1494,6 +1496,7 @@ func TestCleanOpenRTBRequestsGDPR(t *testing.T) {
 			gdpr:               "0",
 			gdprConsent:        tcf2Consent,
 			gdprScrub:          false,
+			gdprDefaultValue:   "1",
 			expectPrivacyLabels: metrics.PrivacyLabels{
 				GDPREnforced:   false,
 				GDPRTCFVersion: "",
@@ -1506,6 +1509,7 @@ func TestCleanOpenRTBRequestsGDPR(t *testing.T) {
 			gdpr:               "0{",
 			gdprConsent:        tcf2Consent,
 			gdprScrub:          true,
+			gdprDefaultValue:   "1",
 			expectPrivacyLabels: metrics.PrivacyLabels{
 				GDPREnforced:   true,
 				GDPRTCFVersion: metrics.TCFVersionV2,
@@ -1519,6 +1523,7 @@ func TestCleanOpenRTBRequestsGDPR(t *testing.T) {
 			gdpr:               "1",
 			gdprConsent:        tcf2Consent,
 			gdprScrub:          true,
+			gdprDefaultValue:   "1",
 			expectPrivacyLabels: metrics.PrivacyLabels{
 				GDPREnforced:   true,
 				GDPRTCFVersion: metrics.TCFVersionV2,
@@ -1531,6 +1536,7 @@ func TestCleanOpenRTBRequestsGDPR(t *testing.T) {
 			gdpr:               "1",
 			gdprConsent:        tcf2Consent,
 			gdprScrub:          false,
+			gdprDefaultValue:   "1",
 			expectPrivacyLabels: metrics.PrivacyLabels{
 				GDPREnforced:   false,
 				GDPRTCFVersion: "",
@@ -1543,6 +1549,7 @@ func TestCleanOpenRTBRequestsGDPR(t *testing.T) {
 			gdpr:               "1",
 			gdprConsent:        tcf2Consent,
 			gdprScrub:          true,
+			gdprDefaultValue:   "1",
 			expectPrivacyLabels: metrics.PrivacyLabels{
 				GDPREnforced:   true,
 				GDPRTCFVersion: metrics.TCFVersionV2,
@@ -1555,32 +1562,33 @@ func TestCleanOpenRTBRequestsGDPR(t *testing.T) {
 			gdpr:               "1",
 			gdprConsent:        tcf2Consent,
 			gdprScrub:          false,
+			gdprDefaultValue:   "1",
 			expectPrivacyLabels: metrics.PrivacyLabels{
 				GDPREnforced:   false,
 				GDPRTCFVersion: "",
 			},
 		},
 		{
-			description:         "Enforce - Ambiguous signal, don't sync user if ambiguous",
-			gdprAccountEnabled:  nil,
-			gdprHostEnabled:     true,
-			gdpr:                "null",
-			gdprConsent:         tcf2Consent,
-			gdprScrub:           true,
-			userSyncIfAmbiguous: false,
+			description:        "Enforce - Ambiguous signal, don't sync user if ambiguous",
+			gdprAccountEnabled: nil,
+			gdprHostEnabled:    true,
+			gdpr:               "null",
+			gdprConsent:        tcf2Consent,
+			gdprScrub:          true,
+			gdprDefaultValue:   "1",
 			expectPrivacyLabels: metrics.PrivacyLabels{
 				GDPREnforced:   true,
 				GDPRTCFVersion: metrics.TCFVersionV2,
 			},
 		},
 		{
-			description:         "Not Enforce - Ambiguous signal, sync user if ambiguous",
-			gdprAccountEnabled:  nil,
-			gdprHostEnabled:     true,
-			gdpr:                "null",
-			gdprConsent:         tcf2Consent,
-			gdprScrub:           false,
-			userSyncIfAmbiguous: true,
+			description:        "Not Enforce - Ambiguous signal, sync user if ambiguous",
+			gdprAccountEnabled: nil,
+			gdprHostEnabled:    true,
+			gdpr:               "null",
+			gdprConsent:        tcf2Consent,
+			gdprScrub:          false,
+			gdprDefaultValue:   "0",
 			expectPrivacyLabels: metrics.PrivacyLabels{
 				GDPREnforced:   false,
 				GDPRTCFVersion: "",
@@ -1594,6 +1602,7 @@ func TestCleanOpenRTBRequestsGDPR(t *testing.T) {
 			gdprConsent:        tcf2Consent,
 			gdprScrub:          true,
 			permissionsError:   errors.New("Some error"),
+			gdprDefaultValue:   "1",
 			expectPrivacyLabels: metrics.PrivacyLabels{
 				GDPREnforced:   true,
 				GDPRTCFVersion: metrics.TCFVersionV2,
@@ -1610,8 +1619,8 @@ func TestCleanOpenRTBRequestsGDPR(t *testing.T) {
 
 		privacyConfig := config.Privacy{
 			GDPR: config.GDPR{
-				Enabled:             test.gdprHostEnabled,
-				UsersyncIfAmbiguous: test.userSyncIfAmbiguous,
+				Enabled:      test.gdprHostEnabled,
+				DefaultValue: test.gdprDefaultValue,
 				TCF2: config.TCF2{
 					Enabled: true,
 				},
@@ -1636,7 +1645,7 @@ func TestCleanOpenRTBRequestsGDPR(t *testing.T) {
 			nil,
 			&permissionsMock{allowAllBidders: true, passGeo: !test.gdprScrub, passID: !test.gdprScrub, activitiesError: test.permissionsError},
 			&metrics.MetricsEngineMock{},
-			test.userSyncIfAmbiguous,
+			test.gdprDefaultValue,
 			privacyConfig,
 			nil)
 		result := results[0]
@@ -1698,8 +1707,8 @@ func TestCleanOpenRTBRequestsGDPRBlockBidRequest(t *testing.T) {
 
 		privacyConfig := config.Privacy{
 			GDPR: config.GDPR{
-				Enabled:             test.gdprEnforced,
-				UsersyncIfAmbiguous: true,
+				Enabled:      test.gdprEnforced,
+				DefaultValue: "0",
 				TCF2: config.TCF2{
 					Enabled: true,
 				},
@@ -1727,7 +1736,7 @@ func TestCleanOpenRTBRequestsGDPRBlockBidRequest(t *testing.T) {
 			nil,
 			&permissionsMock{allowedBidders: test.gdprAllowedBidders, passGeo: true, passID: true, activitiesError: nil},
 			&metricsMock,
-			true,
+			"0",
 			privacyConfig,
 			nil)
 
diff --git a/gdpr/impl_test.go b/gdpr/impl_test.go
index d26c0c57..345dd526 100644
--- a/gdpr/impl_test.go
+++ b/gdpr/impl_test.go
@@ -18,8 +18,8 @@ import (
 func TestDisallowOnEmptyConsent(t *testing.T) {
 	perms := permissionsImpl{
 		cfg: config.GDPR{
-			HostVendorID:        3,
-			UsersyncIfAmbiguous: true,
+			HostVendorID: 3,
+			DefaultValue: "0",
 		},
 		vendorIDs: nil,
 		fetchVendorList: map[uint8]func(ctx context.Context, id uint16) (vendorlist.VendorList, error){
@@ -190,84 +190,84 @@ func TestAllowActivities(t *testing.T) {
 		description           string
 		bidderName            openrtb_ext.BidderName
 		publisherID           string
-		userSyncIfAmbiguous   bool
+		gdprDefaultValue      string
 		gdpr                  Signal
 		consent               string
 		passID                bool
 		weakVendorEnforcement bool
 	}{
 		{
-			description:         "Allow PI - Non standard publisher",
-			bidderName:          bidderBlockedByConsent,
-			publisherID:         "appNexusAppID",
-			userSyncIfAmbiguous: false,
-			gdpr:                SignalYes,
-			consent:             vendor2AndPurpose2Consent,
-			passID:              true,
+			description:      "Allow PI - Non standard publisher",
+			bidderName:       bidderBlockedByConsent,
+			publisherID:      "appNexusAppID",
+			gdprDefaultValue: "1",
+			gdpr:             SignalYes,
+			consent:          vendor2AndPurpose2Consent,
+			passID:           true,
 		},
 		{
-			description:         "Allow PI - known vendor with No GDPR",
-			bidderName:          bidderBlockedByConsent,
-			userSyncIfAmbiguous: false,
-			gdpr:                SignalNo,
-			consent:             vendor2AndPurpose2Consent,
-			passID:              true,
+			description:      "Allow PI - known vendor with No GDPR",
+			bidderName:       bidderBlockedByConsent,
+			gdprDefaultValue: "1",
+			gdpr:             SignalNo,
+			consent:          vendor2AndPurpose2Consent,
+			passID:           true,
 		},
 		{
-			description:         "Allow PI - known vendor with Yes GDPR",
-			bidderName:          bidderAllowedByConsent,
-			userSyncIfAmbiguous: false,
-			gdpr:                SignalYes,
-			consent:             vendor2AndPurpose2Consent,
-			passID:              true,
+			description:      "Allow PI - known vendor with Yes GDPR",
+			bidderName:       bidderAllowedByConsent,
+			gdprDefaultValue: "1",
+			gdpr:             SignalYes,
+			consent:          vendor2AndPurpose2Consent,
+			passID:           true,
 		},
 		{
-			description:         "PI allowed according to host setting UserSyncIfAmbiguous true - known vendor with ambiguous GDPR and empty consent",
-			bidderName:          bidderAllowedByConsent,
-			userSyncIfAmbiguous: true,
-			gdpr:                SignalAmbiguous,
-			consent:             "",
-			passID:              true,
+			description:      "PI allowed according to host setting gdprDefaultValue 0 - known vendor with ambiguous GDPR and empty consent",
+			bidderName:       bidderAllowedByConsent,
+			gdprDefaultValue: "0",
+			gdpr:             SignalAmbiguous,
+			consent:          "",
+			passID:           true,
 		},
 		{
-			description:         "PI allowed according to host setting UserSyncIfAmbiguous true - known vendor with ambiguous GDPR and non-empty consent",
-			bidderName:          bidderAllowedByConsent,
-			userSyncIfAmbiguous: true,
-			gdpr:                SignalAmbiguous,
-			consent:             vendor2AndPurpose2Consent,
-			passID:              true,
+			description:      "PI allowed according to host setting gdprDefaultValue 0 - known vendor with ambiguous GDPR and non-empty consent",
+			bidderName:       bidderAllowedByConsent,
+			gdprDefaultValue: "0",
+			gdpr:             SignalAmbiguous,
+			consent:          vendor2AndPurpose2Consent,
+			passID:           true,
 		},
 		{
-			description:         "PI allowed according to host setting UserSyncIfAmbiguous false - known vendor with ambiguous GDPR and empty consent",
-			bidderName:          bidderAllowedByConsent,
-			userSyncIfAmbiguous: false,
-			gdpr:                SignalAmbiguous,
-			consent:             "",
-			passID:              false,
+			description:      "PI allowed according to host setting gdprDefaultValue 1 - known vendor with ambiguous GDPR and empty consent",
+			bidderName:       bidderAllowedByConsent,
+			gdprDefaultValue: "1",
+			gdpr:             SignalAmbiguous,
+			consent:          "",
+			passID:           false,
 		},
 		{
-			description:         "PI allowed according to host setting UserSyncIfAmbiguous false - known vendor with ambiguous GDPR and non-empty consent",
-			bidderName:          bidderAllowedByConsent,
-			userSyncIfAmbiguous: false,
-			gdpr:                SignalAmbiguous,
-			consent:             vendor2AndPurpose2Consent,
-			passID:              true,
+			description:      "PI allowed according to host setting gdprDefaultValue 1 - known vendor with ambiguous GDPR and non-empty consent",
+			bidderName:       bidderAllowedByConsent,
+			gdprDefaultValue: "1",
+			gdpr:             SignalAmbiguous,
+			consent:          vendor2AndPurpose2Consent,
+			passID:           true,
 		},
 		{
-			description:         "Don't allow PI - known vendor with Yes GDPR and empty consent",
-			bidderName:          bidderAllowedByConsent,
-			userSyncIfAmbiguous: false,
-			gdpr:                SignalYes,
-			consent:             "",
-			passID:              false,
+			description:      "Don't allow PI - known vendor with Yes GDPR and empty consent",
+			bidderName:       bidderAllowedByConsent,
+			gdprDefaultValue: "1",
+			gdpr:             SignalYes,
+			consent:          "",
+			passID:           false,
 		},
 		{
-			description:         "Don't allow PI - default vendor with Yes GDPR and non-empty consent",
-			bidderName:          bidderBlockedByConsent,
-			userSyncIfAmbiguous: false,
-			gdpr:                SignalYes,
-			consent:             vendor2AndPurpose2Consent,
-			passID:              false,
+			description:      "Don't allow PI - default vendor with Yes GDPR and non-empty consent",
+			bidderName:       bidderBlockedByConsent,
+			gdprDefaultValue: "1",
+			gdpr:             SignalYes,
+			consent:          vendor2AndPurpose2Consent,
+			passID:           false,
 		},
 	}
 	vendorListData := MarshalVendorList(vendorList{
@@ -302,7 +302,7 @@ func TestAllowActivities(t *testing.T) {
 	}
 
 	for _, tt := range tests {
-		perms.cfg.UsersyncIfAmbiguous = tt.userSyncIfAmbiguous
+		perms.cfg.DefaultValue = tt.gdprDefaultValue
 
 		_, _, passID, err := perms.AuctionActivitiesAllowed(context.Background(), tt.bidderName, tt.publisherID, tt.gdpr, tt.consent, tt.weakVendorEnforcement)
 
@@ -669,53 +669,53 @@ func assertStringsEqual(t *testing.T, expected string, actual string) {
 
 func TestNormalizeGDPR(t *testing.T) {
 	tests := []struct {
-		description         string
-		userSyncIfAmbiguous bool
-		giveSignal          Signal
-		wantSignal          Signal
+		description      string
+		gdprDefaultValue string
+		giveSignal       Signal
+		wantSignal       Signal
 	}{
 		{
-			description:         "Don't normalize - Signal No and userSyncIfAmbiguous false",
-			userSyncIfAmbiguous: false,
-			giveSignal:          SignalNo,
-			wantSignal:          SignalNo,
+			description:      "Don't normalize - Signal No and gdprDefaultValue 1",
+			gdprDefaultValue: "1",
+			giveSignal:       SignalNo,
+			wantSignal:       SignalNo,
 		},
 		{
-			description:         "Don't normalize - Signal No and userSyncIfAmbiguous true",
-			userSyncIfAmbiguous: true,
-			giveSignal:          SignalNo,
-			wantSignal:          SignalNo,
+			description:      "Don't normalize - Signal No and gdprDefaultValue 0",
+			gdprDefaultValue: "0",
+			giveSignal:       SignalNo,
+			wantSignal:       SignalNo,
 		},
 		{
-			description:         "Don't normalize - Signal Yes and userSyncIfAmbiguous false",
-			userSyncIfAmbiguous: false,
-			giveSignal:          SignalYes,
-			wantSignal:          SignalYes,
+			description:      "Don't normalize - Signal Yes and gdprDefaultValue 1",
+			gdprDefaultValue: "1",
+			giveSignal:       SignalYes,
+			wantSignal:       SignalYes,
 		},
 		{
-			description:         "Don't normalize - Signal Yes and userSyncIfAmbiguous true",
-			userSyncIfAmbiguous: true,
-			giveSignal:          SignalYes,
-			wantSignal:          SignalYes,
+			description:      "Don't normalize - Signal Yes and gdprDefaultValue 0",
+			gdprDefaultValue: "0",
+			giveSignal:       SignalYes,
+			wantSignal:       SignalYes,
 		},
 		{
-			description:         "Normalize - Signal Ambiguous and userSyncIfAmbiguous false",
-			userSyncIfAmbiguous: false,
-			giveSignal:          SignalAmbiguous,
-			wantSignal:          SignalYes,
+			description:      "Normalize - Signal Ambiguous and gdprDefaultValue 1",
+			gdprDefaultValue: "1",
+			giveSignal:       SignalAmbiguous,
+			wantSignal:       SignalYes,
 		},
 		{
-			description:         "Normalize - Signal Ambiguous and userSyncIfAmbiguous true",
-			userSyncIfAmbiguous: true,
-			giveSignal:          SignalAmbiguous,
-			wantSignal:          SignalNo,
+			description:      "Normalize - Signal Ambiguous and gdprDefaultValue 0",
+			gdprDefaultValue: "0",
+			giveSignal:       SignalAmbiguous,
+			wantSignal:       SignalNo,
 		},
 	}
 
 	for _, tt := range tests {
 		perms := permissionsImpl{
 			cfg: config.GDPR{
-				UsersyncIfAmbiguous: tt.userSyncIfAmbiguous,
+				DefaultValue: tt.gdprDefaultValue,
 			},
 		}