Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions endpoints/openrtb2/amp_auction.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/prebid/prebid-server/v4/metrics"
"github.com/prebid/prebid-server/v4/openrtb_ext"
"github.com/prebid/prebid-server/v4/privacy"
"github.com/prebid/prebid-server/v4/privacy/ccpa"
"github.com/prebid/prebid-server/v4/stored_requests"
"github.com/prebid/prebid-server/v4/stored_requests/backends/empty_fetcher"
"github.com/prebid/prebid-server/v4/stored_responses"
Expand Down Expand Up @@ -652,8 +653,12 @@ func (deps *endpointDeps) overrideWithParams(ampParams amp.Params, req *openrtb2
}

policyWriter, policyWriterErr := amp.ReadPolicy(ampParams, deps.cfg.GDPR.Enabled)
var errors []error
if policyWriterErr != nil {
return []error{policyWriterErr}
errors = append(errors, policyWriterErr)
if !shouldApplyAmpPolicyDespiteWarning(ampParams, policyWriterErr) {
return errors
}
}
if err := policyWriter.Write(req); err != nil {
return []error{err}
Expand All @@ -663,7 +668,6 @@ func (deps *endpointDeps) overrideWithParams(ampParams amp.Params, req *openrtb2
req.TMax = int64(*ampParams.Timeout) - deps.cfg.AMPTimeoutAdjustment
}

var errors []error
if warn := setTargeting(req, ampParams.Targeting); warn != nil {
errors = append(errors, warn)
}
Expand All @@ -675,6 +679,15 @@ func (deps *endpointDeps) overrideWithParams(ampParams amp.Params, req *openrtb2
return errors
}

func shouldApplyAmpPolicyDespiteWarning(ampParams amp.Params, policyWriterErr error) bool {
return errortypes.IsWarning(policyWriterErr) &&
ampParams.GdprApplies != nil &&
*ampParams.GdprApplies &&
ccpa.ValidateConsent(ampParams.Consent) &&
ampParams.ConsentType != amp.ConsentTCF1 &&
ampParams.ConsentType != amp.ConsentTCF2
}

// setConsentedProviders sets the addtl_consent value to user.ext.ConsentedProvidersSettings.consented_providers
// in its orginal Google Additional Consent string format and user.ext.consented_providers_settings.consented_providers
// that is an array of ints that contains the elements found in addtl_consent
Expand Down
82 changes: 82 additions & 0 deletions endpoints/openrtb2/amp_auction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,8 @@ func TestOverrideWithParams(t *testing.T) {
errorMsgs []string
expectFatalErrors bool
}
gdprApplies := true
timeout := uint64(500)
testCases := []struct {
desc string
given testInput
Expand Down Expand Up @@ -544,6 +546,86 @@ func TestOverrideWithParams(t *testing.T) {
errorMsgs: []string{"unable to merge imp.ext with targeting data, check targeting data is correct: Invalid JSON Patch"},
},
},
{
desc: "amp.Params with valid CCPA consent and gdpr_applies true - expect consent warning and remaining overrides applied",
given: testInput{
ampParams: amp.Params{
Consent: "1YNN",
ConsentType: amp.ConsentUSPrivacy,
GdprApplies: &gdprApplies,
Targeting: `{"foo":"bar"}`,
Timeout: &timeout,
Trace: "verbose",
},
bidRequest: &openrtb2.BidRequest{
Imp: []openrtb2.Imp{{Banner: &openrtb2.Banner{Format: []openrtb2.Format{}}}},
},
},
expected: testOutput{
bidRequest: &openrtb2.BidRequest{
Imp: []openrtb2.Imp{{
Banner: &openrtb2.Banner{Format: []openrtb2.Format{}},
Ext: json.RawMessage(`{"data":{"foo":"bar"}}`),
}},
Regs: &openrtb2.Regs{USPrivacy: "1YNN"},
Site: &openrtb2.Site{Ext: json.RawMessage(`{"amp":1}`)},
TMax: 500,
Ext: json.RawMessage(`{"prebid":{"trace":"verbose"}}`),
},
errorMsgs: []string{"AMP request gdpr_applies value was ignored because provided consent string is a CCPA consent string"},
},
},
{
desc: "amp.Params default consent_type with valid CCPA consent and gdpr_applies true - expect consent warning and remaining overrides applied",
given: testInput{
ampParams: amp.Params{
Consent: "1YNN",
GdprApplies: &gdprApplies,
Targeting: `{"foo":"bar"}`,
Timeout: &timeout,
Trace: "verbose",
},
bidRequest: &openrtb2.BidRequest{
Imp: []openrtb2.Imp{{Banner: &openrtb2.Banner{Format: []openrtb2.Format{}}}},
},
},
expected: testOutput{
bidRequest: &openrtb2.BidRequest{
Imp: []openrtb2.Imp{{
Banner: &openrtb2.Banner{Format: []openrtb2.Format{}},
Ext: json.RawMessage(`{"data":{"foo":"bar"}}`),
}},
Regs: &openrtb2.Regs{USPrivacy: "1YNN"},
Site: &openrtb2.Site{Ext: json.RawMessage(`{"amp":1}`)},
TMax: 500,
Ext: json.RawMessage(`{"prebid":{"trace":"verbose"}}`),
},
errorMsgs: []string{"AMP request gdpr_applies value was ignored because provided consent string is a CCPA consent string"},
},
},
{
desc: "amp.Params with invalid CCPA consent and gdpr_applies true - expect consent warning and remaining overrides skipped",
given: testInput{
ampParams: amp.Params{
Consent: "XXXX",
ConsentType: amp.ConsentUSPrivacy,
GdprApplies: &gdprApplies,
Targeting: `{"foo":"bar"}`,
Timeout: &timeout,
Trace: "verbose",
},
bidRequest: &openrtb2.BidRequest{
Imp: []openrtb2.Imp{{Banner: &openrtb2.Banner{Format: []openrtb2.Format{}}}},
},
},
expected: testOutput{
bidRequest: &openrtb2.BidRequest{
Imp: []openrtb2.Imp{{Banner: &openrtb2.Banner{Format: []openrtb2.Format{}}}},
Site: &openrtb2.Site{Ext: json.RawMessage(`{"amp":1}`)},
},
errorMsgs: []string{"Consent string 'XXXX' is not a valid CCPA consent string."},
},
},
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both of these test cases in amp_auction_test.go set ConsentType: amp.ConsentUSPrivacy. The default: branch of ReadPolicy (unset consent_type, i.e. ConsentType == 0) is also affected by the fix but untested. Add a case that omits ConsentType (defaults to 0 → default branch):


        {
            desc: "amp.Params default consent_type with valid CCPA consent and gdpr_applies true - expect consent warning and remaining overrides applied",
            given: testInput{
                ampParams: amp.Params{
                    Consent:     "1YNN",
                    // ConsentType intentionally unset -> auto-detect (default branch)
                    GdprApplies: &gdprApplies,
                    Targeting:   `{"foo":"bar"}`,
                    Timeout:     &timeout,
                    Trace:       "verbose",
                },
                bidRequest: &openrtb2.BidRequest{
                    Imp: []openrtb2.Imp{{Banner: &openrtb2.Banner{Format: []openrtb2.Format{}}}},
                },
            },
            expected: testOutput{
                bidRequest: &openrtb2.BidRequest{
                    Imp: []openrtb2.Imp{{
                        Banner: &openrtb2.Banner{Format: []openrtb2.Format{}},
                        Ext:    json.RawMessage(`{"data":{"foo":"bar"}}`),
                    }},
                    Regs: &openrtb2.Regs{USPrivacy: "1YNN"},
                    Site: &openrtb2.Site{Ext: json.RawMessage(`{"amp":1}`)},
                    TMax: 500,
                    Ext:  json.RawMessage(`{"prebid":{"trace":"verbose"}}`),
                },
                errorMsgs: []string{"AMP request gdpr_applies value was ignored because provided consent string is a CCPA consent string"},
            },
        },

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added


for _, test := range testCases {
Expand Down
Loading