Repository: prebid/prebid-server
Pull request #1873 (2021-06-01 14:11:55)

IX: Update Default Config
Update IX default usersync id.


Patch:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index fb9b6592..a1459626 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -3,7 +3,7 @@ name: Release
 on:
   push:
     tags:
-      - '[0-9]+.[0-9]+.[0-9]+'
+      - 'v[0-9]+.[0-9]+.[0-9]+'
 
 jobs:
   release:
@@ -13,13 +13,15 @@ jobs:
     steps:
       - name: Get Version
         id: get_version
-        run: echo ::set-output name=version::${GITHUB_REF/refs\/tags\//}
+        run: |
+          echo ::set-output name=tag::${GITHUB_REF/refs\/tags\/}
+          echo ::set-output name=version::${GITHUB_REF/refs\/tags\/v}
 
       - name: Create & Publish Release
         uses: release-drafter/release-drafter@v5.12.1
         with:
           name: ${{ steps.get_version.outputs.version }}
-          tag: ${{ steps.get_version.outputs.version }}
+          tag: ${{ steps.get_version.outputs.tag }}
           version: ${{ steps.get_version.outputs.version }}
           publish: true
         env:
diff --git a/README.md b/README.md
index 83ac89a9..f3338ce1 100644
--- a/README.md
+++ b/README.md
@@ -50,6 +50,11 @@ go build .
 Load the landing page in your browser at `http://localhost:8000/`.
 For the full API reference, see [the endpoint documentation](https://docs.prebid.org/prebid-server/endpoints/pbs-endpoint-overview.html)
 
+## Go Modules
+
+The packages within this repository are intended to be used as part of the Prebid Server compiled binary. If you
+choose to import Prebid Server packages in other projects, please understand we make no promises on the stability
+of exported types.
 
 ## Contributing
 
@@ -59,7 +64,7 @@ Report bugs, request features, and suggest improvements [on Github](https://gith
 
 Or better yet, [open a pull request](https://github.com/prebid/prebid-server/compare) with the changes you'd like to see.
 
-## IDE Setup for PBS-Go development
+## IDE Recommendations
 
-The quickest way to start developing PBS-Go in a reproducible environment isolated from your host OS
-is by using this [VScode Remote Container Setup](devcontainer.md)
+The quickest way to start developing Prebid Server in a reproducible environment isolated from your host OS
+is by using Visual Studio Code with [Remote Container Setup](devcontainer.md).
diff --git a/adapters/pubmatic/pubmatic.go b/adapters/pubmatic/pubmatic.go
index 2e361fa5..dc1ee9d0 100644
--- a/adapters/pubmatic/pubmatic.go
+++ b/adapters/pubmatic/pubmatic.go
@@ -66,6 +66,10 @@ const (
 	INVALID_HEIGHT    = "Invalid Height"
 	INVALID_MEDIATYPE = "Invalid MediaType"
 	INVALID_ADSLOT    = "Invalid AdSlot"
+
+	dctrKeyName        = "key_val"
+	pmZoneIDKeyName    = "pmZoneId"
+	pmZoneIDKeyNameOld = "pmZoneID"
 )
 
 func PrepareLogMessage(tID, pubId, adUnitId, bidID, details string, args ...interface{}) string {
@@ -485,30 +489,43 @@ func parseImpressionObject(imp *openrtb2.Imp, wrapExt *string, pubID *string) er
 		imp.Banner = bannerCopy
 	}
 
+	extMap := make(map[string]interface{}, 0)
 	if pubmaticExt.Keywords != nil && len(pubmaticExt.Keywords) != 0 {
-		kvstr := makeKeywordStr(pubmaticExt.Keywords)
-		imp.Ext = json.RawMessage([]byte(kvstr))
-	} else {
-		imp.Ext = nil
+		addKeywordsToExt(pubmaticExt.Keywords, extMap)
+	}
+	//Give preference to direct values of 'dctr' & 'pmZoneId' params in extension
+	if pubmaticExt.Dctr != "" {
+		extMap[dctrKeyName] = pubmaticExt.Dctr
+	}
+	if pubmaticExt.PmZoneID != "" {
+		extMap[pmZoneIDKeyName] = pubmaticExt.PmZoneID
+	}
+
+	imp.Ext = nil
+	if len(extMap) > 0 {
+		ext, err := json.Marshal(extMap)
+		if err == nil {
+			imp.Ext = ext
+		}
 	}
 
 	return nil
 
 }
 
-func makeKeywordStr(keywords []*openrtb_ext.ExtImpPubmaticKeyVal) string {
-	eachKv := make([]string, 0, len(keywords))
+func addKeywordsToExt(keywords []*openrtb_ext.ExtImpPubmaticKeyVal, extMap map[string]interface{}) {
 	for _, keyVal := range keywords {
 		if len(keyVal.Values) == 0 {
 			logf("No values present for key = %s", keyVal.Key)
 			continue
 		} else {
-			eachKv = append(eachKv, fmt.Sprintf("\"%s\":\"%s\"", keyVal.Key, strings.Join(keyVal.Values[:], ",")))
+			key := keyVal.Key
+			if keyVal.Key == pmZoneIDKeyNameOld {
+				key = pmZoneIDKeyName
+			}
+			extMap[key] = strings.Join(keyVal.Values[:], ",")
 		}
 	}
-
-	kvStr := "{" + strings.Join(eachKv, ",") + "}"
-	return kvStr
 }
 
 func prepareImpressionExt(keywords map[string]string) string {
diff --git a/config/config.go b/config/config.go
index afb4ac8d..27e917e4 100644
--- a/config/config.go
+++ b/config/config.go
@@ -612,7 +612,7 @@ func (cfg *Configuration) setDerivedDefaults() {
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderGrid, "https://x.bidswitch.net/check_uuid/"+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dgrid%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BBSW_UUID%7D?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderGumGum, "https://rtb.gumgum.com/usync/prbds2s?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dgumgum%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderImprovedigital, "https://ad.360yield.com/server_match?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dimprovedigital%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%7BPUB_USER_ID%7D")
-	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderIx, "https://ssum.casalemedia.com/usermatchredir?s=184674&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&cb="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dix%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D")
+	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderIx, "https://ssum.casalemedia.com/usermatchredir?s=194962&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&cb="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dix%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D")
 	// openrtb_ext.BidderInvibes doesn't have a good default.
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderJixie, "https://id.jixie.io/api/sync?pid=&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Djixie%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%25%25JXUID%25%25")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderKrushmedia, "https://cs.krushmedia.com/4e4abdd5ecc661643458a730b1aa927d.gif?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dkrushmedia%26uid%3D%5BUID%5D")
diff --git a/openrtb_ext/imp_pubmatic.go b/openrtb_ext/imp_pubmatic.go
index fd97836d..cf5093a2 100644
--- a/openrtb_ext/imp_pubmatic.go
+++ b/openrtb_ext/imp_pubmatic.go
@@ -11,6 +11,8 @@ import "encoding/json"
 type ExtImpPubmatic struct {
 	PublisherId string                  `json:"publisherId"`
 	AdSlot      string                  `json:"adSlot"`
+	Dctr        string                  `json:"dctr"`
+	PmZoneID    string                  `json:"pmzoneid"`
 	WrapExt     json.RawMessage         `json:"wrapper,omitempty"`
 	Keywords    []*ExtImpPubmaticKeyVal `json:"keywords,omitempty"`
 }
diff --git a/static/bidder-params/pubmatic.json b/static/bidder-params/pubmatic.json
index 1b6a2f03..5d41b9fc 100644
--- a/static/bidder-params/pubmatic.json
+++ b/static/bidder-params/pubmatic.json
@@ -12,6 +12,14 @@
 			"type": "string",
 			"description": "An ID which identifies the ad slot"
 		},
+		"pmzoneid": {
+			"type": "string",
+			"description": "Comma separated zone id. Used im deal targeting & site section targeting. e.g drama,sport"
+		},
+		"dctr": {
+			"type": "string",
+			"description": "Deals Custom Targeting, pipe separated key-value pairs e.g key1=V1,V2,V3|key2=v1|key3=v3,v5"
+		},
 		"wrapper": {
 			"type": "object",
 			"description": "Specifies pubmatic openwrap configuration for a publisher",


Test patch:
diff --git a/adapters/pubmatic/pubmatictest/exemplary/banner.json b/adapters/pubmatic/pubmatictest/exemplary/banner.json
index 1eb8a212..f525673c 100644
--- a/adapters/pubmatic/pubmatictest/exemplary/banner.json
+++ b/adapters/pubmatic/pubmatictest/exemplary/banner.json
@@ -61,7 +61,7 @@
                 "w": 300
             },
                 "ext": {
-                    "pmZoneID": "Zone1,Zone2",
+                    "pmZoneId": "Zone1,Zone2",
                     "preference": "sports,movies"
                 }
               }
diff --git a/adapters/pubmatic/pubmatictest/exemplary/video.json b/adapters/pubmatic/pubmatictest/exemplary/video.json
index 4c874535..1715e477 100644
--- a/adapters/pubmatic/pubmatictest/exemplary/video.json
+++ b/adapters/pubmatic/pubmatictest/exemplary/video.json
@@ -73,7 +73,7 @@
                     "maxbitrate": 10
                 },
                 "ext": {
-                    "pmZoneID": "Zone1,Zone2"
+                    "pmZoneId": "Zone1,Zone2"
                 }
               }
             ], 
diff --git a/adapters/pubmatic/pubmatictest/params/race/banner.json b/adapters/pubmatic/pubmatictest/params/race/banner.json
index 86ddc70b..ab88871e 100644
--- a/adapters/pubmatic/pubmatictest/params/race/banner.json
+++ b/adapters/pubmatic/pubmatictest/params/race/banner.json
@@ -1,6 +1,8 @@
 {
 	"publisherId": "156209",
 	"adSlot": "pubmatic_test2@300x250",
+	"pmzoneid": "drama,sport",
+	"dctr": "abBucket=4|adType=page|entity=|paidByCategory=|sku=|userLevel=free|platform=android|majorVersion=3.54|version=3.54.0|mobileApplication=true|showId=20166|show=Kisah Untuk Geri|genre=Drama|contentUrl=https://www.iflix.com/title/show/20166|rating=TV-MA|contentLanguage=id",
 	"keywords": {
 		"pmZoneID": "Zone1,Zone2",
 		"preference": "sports,movies"
diff --git a/adapters/pubmatic/pubmatictest/params/race/video.json b/adapters/pubmatic/pubmatictest/params/race/video.json
index 86ddc70b..ab88871e 100644
--- a/adapters/pubmatic/pubmatictest/params/race/video.json
+++ b/adapters/pubmatic/pubmatictest/params/race/video.json
@@ -1,6 +1,8 @@
 {
 	"publisherId": "156209",
 	"adSlot": "pubmatic_test2@300x250",
+	"pmzoneid": "drama,sport",
+	"dctr": "abBucket=4|adType=page|entity=|paidByCategory=|sku=|userLevel=free|platform=android|majorVersion=3.54|version=3.54.0|mobileApplication=true|showId=20166|show=Kisah Untuk Geri|genre=Drama|contentUrl=https://www.iflix.com/title/show/20166|rating=TV-MA|contentLanguage=id",
 	"keywords": {
 		"pmZoneID": "Zone1,Zone2",
 		"preference": "sports,movies"
diff --git a/adapters/pubmatic/pubmatictest/supplemental/app.json b/adapters/pubmatic/pubmatictest/supplemental/app.json
index 636433ca..e9f1048e 100644
--- a/adapters/pubmatic/pubmatictest/supplemental/app.json
+++ b/adapters/pubmatic/pubmatictest/supplemental/app.json
@@ -61,7 +61,7 @@
                 "w": 300
             },
                 "ext": {
-                    "pmZoneID": "Zone1,Zone2",
+                    "pmZoneId": "Zone1,Zone2",
                     "preference": "sports,movies"
                 }
               }
diff --git a/adapters/pubmatic/pubmatictest/supplemental/dctrAndPmZoneID.json b/adapters/pubmatic/pubmatictest/supplemental/dctrAndPmZoneID.json
new file mode 100644
index 00000000..d68517de
--- /dev/null
+++ b/adapters/pubmatic/pubmatictest/supplemental/dctrAndPmZoneID.json
@@ -0,0 +1,162 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            }
+          ]
+        },
+        "ext": {
+          "bidder": {
+            "adSlot": "AdTag_Div1@300x250",
+            "publisherId": "  999  ",
+            "pmzoneid": "drama,sport",
+            "dctr": "abBucket=4|adType=page|entity=|paidByCategory=|sku=|userLevel=free|platform=android|majorVersion=3.54|version=3.54.0|mobileApplication=true|showId=20166|show=Kisah Untuk Geri|genre=Drama|contentUrl=https://www.iflix.com/title/show/20166|rating=TV-MA|contentLanguage=id",
+            "keywords": [
+              {
+                "key": "pmZoneID",
+                "value": [
+                  "Zone1",
+                  "Zone2"
+                ]
+              },
+              {
+                "key": "preference",
+                "value": [
+                  "sports",
+                  "movies"
+                ]
+              }
+            ],
+            "wrapper": {
+              "version": 1,
+              "profile": 5123
+            }
+          }
+        }
+      }
+    ],
+    "device": {
+      "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
+    },
+    "site": {
+      "id": "siteID",
+      "publisher": {
+        "id": "1234"
+      }
+    }
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "https://hbopenbid.pubmatic.com/translator?source=prebid-server",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "tagid": "AdTag_Div1",
+              "banner": {
+                "format": [
+                  {
+                    "w": 300,
+                    "h": 250
+                  }
+                ],
+                "h": 250,
+                "w": 300
+              },
+              "ext": {
+                "key_val": "abBucket=4|adType=page|entity=|paidByCategory=|sku=|userLevel=free|platform=android|majorVersion=3.54|version=3.54.0|mobileApplication=true|showId=20166|show=Kisah Untuk Geri|genre=Drama|contentUrl=https://www.iflix.com/title/show/20166|rating=TV-MA|contentLanguage=id",
+                "pmZoneId": "drama,sport",
+                "preference": "sports,movies"
+              }
+            }
+          ],
+          "device": {
+            "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
+          },
+          "site": {
+            "id": "siteID",
+            "publisher": {
+              "id": "999"
+            }
+          },
+          "ext": {
+            "wrapper": {
+              "profile": 5123,
+              "version": 1
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-request-id",
+          "seatbid": [
+            {
+              "seat": "958",
+              "bid": [
+                {
+                  "id": "7706636740145184841",
+                  "impid": "test-imp-id",
+                  "price": 0.500000,
+                  "adid": "29681110",
+                  "adm": "some-test-ad",
+                  "adomain": [
+                    "pubmatic.com"
+                  ],
+                  "crid": "29681110",
+                  "h": 250,
+                  "w": 300,
+                  "dealid": "test deal",
+                  "ext": {
+                    "dspid": 6,
+                    "deal_channel": 1
+                  }
+                }
+              ]
+            }
+          ],
+          "bidid": "5778926625248726496",
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "7706636740145184841",
+            "impid": "test-imp-id",
+            "price": 0.5,
+            "adid": "29681110",
+            "adm": "some-test-ad",
+            "adomain": [
+              "pubmatic.com"
+            ],
+            "crid": "29681110",
+            "w": 300,
+            "h": 250,
+            "dealid": "test deal",
+            "ext": {
+              "dspid": 6,
+              "deal_channel": 1
+            }
+          },
+          "type": "banner"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/pubmatic/pubmatictest/supplemental/noAdSlot.json b/adapters/pubmatic/pubmatictest/supplemental/noAdSlot.json
index c66a7189..a277ef53 100644
--- a/adapters/pubmatic/pubmatictest/supplemental/noAdSlot.json
+++ b/adapters/pubmatic/pubmatictest/supplemental/noAdSlot.json
@@ -55,7 +55,7 @@
                         "h": 250
                     },
                     "ext": {
-                        "pmZoneID": "Zone1,Zone2",
+                        "pmZoneId": "Zone1,Zone2",
                         "preference": "sports,movies"
                     }
                 }],
diff --git a/adapters/pubmatic/pubmatictest/supplemental/pmZoneIDInKeywords.json b/adapters/pubmatic/pubmatictest/supplemental/pmZoneIDInKeywords.json
new file mode 100644
index 00000000..c9c335e8
--- /dev/null
+++ b/adapters/pubmatic/pubmatictest/supplemental/pmZoneIDInKeywords.json
@@ -0,0 +1,161 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            }
+          ]
+        },
+        "ext": {
+          "bidder": {
+            "adSlot": "AdTag_Div1@300x250",
+            "publisherId": "  999  ",
+            "dctr": "key1=V1,V2,V3|key2=v1|key3=v3,v5",
+            "keywords": [
+              {
+                "key": "pmZoneID",
+                "value": [
+                  "Zone1",
+                  "Zone2"
+                ]
+              },
+              {
+                "key": "preference",
+                "value": [
+                  "sports",
+                  "movies"
+                ]
+              }
+            ],
+            "wrapper": {
+              "version": 1,
+              "profile": 5123
+            }
+          }
+        }
+      }
+    ],
+    "device": {
+      "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
+    },
+    "site": {
+      "id": "siteID",
+      "publisher": {
+        "id": "1234"
+      }
+    }
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "https://hbopenbid.pubmatic.com/translator?source=prebid-server",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-id",
+              "tagid": "AdTag_Div1",
+              "banner": {
+                "format": [
+                  {
+                    "w": 300,
+                    "h": 250
+                  }
+                ],
+                "h": 250,
+                "w": 300
+              },
+              "ext": {
+                "key_val": "key1=V1,V2,V3|key2=v1|key3=v3,v5",
+                "pmZoneId": "Zone1,Zone2",
+                "preference": "sports,movies"
+              }
+            }
+          ],
+          "device": {
+            "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
+          },
+          "site": {
+            "id": "siteID",
+            "publisher": {
+              "id": "999"
+            }
+          },
+          "ext": {
+            "wrapper": {
+              "profile": 5123,
+              "version": 1
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-request-id",
+          "seatbid": [
+            {
+              "seat": "958",
+              "bid": [
+                {
+                  "id": "7706636740145184841",
+                  "impid": "test-imp-id",
+                  "price": 0.500000,
+                  "adid": "29681110",
+                  "adm": "some-test-ad",
+                  "adomain": [
+                    "pubmatic.com"
+                  ],
+                  "crid": "29681110",
+                  "h": 250,
+                  "w": 300,
+                  "dealid": "test deal",
+                  "ext": {
+                    "dspid": 6,
+                    "deal_channel": 1
+                  }
+                }
+              ]
+            }
+          ],
+          "bidid": "5778926625248726496",
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "7706636740145184841",
+            "impid": "test-imp-id",
+            "price": 0.5,
+            "adid": "29681110",
+            "adm": "some-test-ad",
+            "adomain": [
+              "pubmatic.com"
+            ],
+            "crid": "29681110",
+            "w": 300,
+            "h": 250,
+            "dealid": "test deal",
+            "ext": {
+              "dspid": 6,
+              "deal_channel": 1
+            }
+          },
+          "type": "banner"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/pubmatic/pubmatictest/supplemental/trimPublisherID.json b/adapters/pubmatic/pubmatictest/supplemental/trimPublisherID.json
index 6a344ee0..d207542a 100644
--- a/adapters/pubmatic/pubmatictest/supplemental/trimPublisherID.json
+++ b/adapters/pubmatic/pubmatictest/supplemental/trimPublisherID.json
@@ -71,7 +71,7 @@
                 "w": 300
               },
               "ext": {
-                "pmZoneID": "Zone1,Zone2",
+                "pmZoneId": "Zone1,Zone2",
                 "preference": "sports,movies"
               }
             }