Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support of an array of price buckets and standard granuarlities #104

Closed
wants to merge 12 commits into from
Closed
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ Setting | Description | Type
`DFP_TARGETED_PLACEMENT_NAMES` | The names of GAM placements the line items should target | array of strings
`DFP_PLACEMENT_SIZES` | The creative sizes for the targeted placements | array of objects (e.g., `[{'width': '728', 'height': '90'}]`)
`PREBID_BIDDER_CODE` | The value of [`hb_bidder`](http://prebid.org/dev-docs/publisher-api-reference.html#module_pbjs.bidderSettings) for this partner | string
`PREBID_PRICE_BUCKETS` | The [price granularity](http://prebid.org/dev-docs/publisher-api-reference.html#module_pbjs.setPriceGranularity); used to set `hb_pb` for each line item | object
`PREBID_PRICE_BUCKETS` | The [price granularity](https://docs.prebid.org/dev-docs/publisher-api-reference/setConfig.html#setConfig-Price-Granularity); used to set `hb_pb` for each line item. Can use Prebid standard granularities such as `medium` or `dense`, a single custom CPM bucket object or an array of custom CPM bucket objects | object, arary or string
`DFP_VIDEO_AD_TYPE` | Set to true to create video ad units and creatives | boolean
`DFP_VAST_REDIRECT_URL` | The redirect URL to use for video ad creatives (only used if `DFP_VIDEO_AD_TYPE` is set to True) | string

Expand Down
2 changes: 1 addition & 1 deletion dfp/associate_line_items_and_creatives.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def make_licas(line_item_ids, creative_ids, size_overrides=[]):
"""
dfp_client = get_client()
lica_service = dfp_client.GetService(
'LineItemCreativeAssociationService', version='v202008')
'LineItemCreativeAssociationService', version='v202108')

sizes = []

Expand Down
2 changes: 1 addition & 1 deletion dfp/create_creatives.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def create_creatives(creatives):
"""
dfp_client = get_client()
creative_service = dfp_client.GetService('CreativeService',
version='v202008')
version='v202108')
creatives = creative_service.createCreatives(creatives)

# Return IDs of created line items.
Expand Down
4 changes: 2 additions & 2 deletions dfp/create_custom_targeting.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def create_targeting_key(name, display_name=None, key_type='FREEFORM'):

dfp_client = get_client()
custom_targeting_service = dfp_client.GetService('CustomTargetingService',
version='v202008')
version='v202108')

if display_name is None:
display_name = name
Expand Down Expand Up @@ -60,7 +60,7 @@ def create_targeting_value(name, key_id):

dfp_client = get_client()
custom_targeting_service = dfp_client.GetService('CustomTargetingService',
version='v202008')
version='v202108')

values_config = [
{
Expand Down
2 changes: 1 addition & 1 deletion dfp/create_line_items.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def create_line_items(line_items):
an array: an array of created line item IDs
"""
dfp_client = get_client()
line_item_service = dfp_client.GetService('LineItemService', version='v202008')
line_item_service = dfp_client.GetService('LineItemService', version='v202108')
line_items = line_item_service.createLineItems(line_items)

# Return IDs of created line items.
Expand Down
2 changes: 1 addition & 1 deletion dfp/create_orders.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def create_order(order_name, advertiser_id, trafficker_id):
create_order_config(name=order_name, advertiser_id=advertiser_id,
trafficker_id=trafficker_id)
]
order_service = dfp_client.GetService('OrderService', version='v202008')
order_service = dfp_client.GetService('OrderService', version='v202108')
orders = order_service.createOrders(orders)

order = orders[0]
Expand Down
19 changes: 10 additions & 9 deletions dfp/creative_snippet.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
<script src="https://cdn.jsdelivr.net/npm/prebid-universal-creative@latest/dist/creative.js"></script>
<script>
var ucTagData = {};
ucTagData.adServerDomain = "";
ucTagData.pubUrl = "%%PATTERN:url%%";
ucTagData.targetingMap = %%PATTERN:TARGETINGMAP%%;
var ucTagData = {};
ucTagData.adServerDomain = "";
ucTagData.pubUrl = "%%PATTERN:url%%";
ucTagData.targetingMap = %%PATTERN:TARGETINGMAP%%;
ucTagData.hbPb = "%%PATTERN:hb_pb%%";

try {
ucTag.renderAd(document, ucTagData);
} catch (e) {
console.log(e);
}
try {
ucTag.renderAd(document, ucTagData);
} catch (e) {
console.log(e);
}
</script>
2 changes: 1 addition & 1 deletion dfp/get_ad_units.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def get_ad_unit_by_name(ad_unit_name):

dfp_client = get_client()
ad_unit_service = dfp_client.GetService('InventoryService',
version='v202008')
version='v202108')

query = 'WHERE name = :name'
values = [
Expand Down
4 changes: 2 additions & 2 deletions dfp/get_advertisers.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def create_advertiser(name):
an integer: the advertiser's DFP ID
"""
dfp_client = get_client()
company_service = dfp_client.GetService('CompanyService', version='v202008')
company_service = dfp_client.GetService('CompanyService', version='v202108')

advertisers_config = [
{
Expand Down Expand Up @@ -53,7 +53,7 @@ def get_advertiser_id_by_name(name):
an integer: the advertiser's DFP ID
"""
dfp_client = get_client()
company_service = dfp_client.GetService('CompanyService', version='v202008')
company_service = dfp_client.GetService('CompanyService', version='v202108')

# Filter by name.
query = 'WHERE name = :name'
Expand Down
4 changes: 2 additions & 2 deletions dfp/get_custom_targeting.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def get_key_id_by_name(name):

dfp_client = get_client()
custom_targeting_service = dfp_client.GetService('CustomTargetingService',
version='v202008')
version='v202108')

# Get a key by name.
query = ('WHERE name = :name')
Expand Down Expand Up @@ -57,7 +57,7 @@ def get_targeting_by_key_name(name):

dfp_client = get_client()
custom_targeting_service = dfp_client.GetService('CustomTargetingService',
version='v202008')
version='v202108')

# Get a key by name.
query = ('WHERE name = :name')
Expand Down
4 changes: 2 additions & 2 deletions dfp/get_orders.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def get_order_by_name(order_name):
"""

dfp_client = get_client()
order_service = dfp_client.GetService('OrderService', version='v202008')
order_service = dfp_client.GetService('OrderService', version='v202108')

# Filter by name.
query = 'WHERE name = :name'
Expand Down Expand Up @@ -60,7 +60,7 @@ def get_all_orders(print_orders=False):
dfp_client = get_client()

# Initialize appropriate service.
order_service = dfp_client.GetService('OrderService', version='v202008')
order_service = dfp_client.GetService('OrderService', version='v202108')

# Create a statement to select orders.
statement = ad_manager.FilterStatement()
Expand Down
2 changes: 1 addition & 1 deletion dfp/get_placements.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def get_placement_by_name(placement_name):

dfp_client = get_client()
placement_service = dfp_client.GetService('PlacementService',
version='v202008')
version='v202108')

query = 'WHERE name = :name'
values = [
Expand Down
2 changes: 1 addition & 1 deletion dfp/get_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def get_user_id_by_email(email_address):
an integer: the user's DFP ID
"""
dfp_client = get_client()
user_service = dfp_client.GetService('UserService', version='v202008')
user_service = dfp_client.GetService('UserService', version='v202108')

# Filter by email address.
query = 'WHERE email = :email'
Expand Down
12 changes: 6 additions & 6 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
colorama==0.4.1
future==0.17.1
googleads==25.0.0
mock==3.0.5
pycryptodome==3.9.0
PyYAML==5.1.2
colorama==0.4.4
future==0.18.2
googleads==29.0.0
mock==4.0.3
pycryptodome==3.10.1
PyYAML==5.4.1
8 changes: 4 additions & 4 deletions settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@

PREBID_BIDDER_CODE = None

# Price buckets. This should match your Prebid settings for the partner. See:
# http://prebid.org/dev-docs/publisher-api-reference.html#module_pbjs.setPriceGranularity
# FIXME: this should be an array of buckets. See:
# https://github.com/prebid/Prebid.js/blob/8fed3d7aaa814e67ca3efc103d7d306cab8c692c/src/cpmBucketManager.js
# Price buckets. This should match your Prebid settings for the partner.
# Can be a single bucket, an array of buckets or string for standard Prebid
# price granularities such as 'medium', 'dense' or 'auto'
# See: https://docs.prebid.org/dev-docs/publisher-api-reference/setConfig.html#setConfig-Price-Granularity
PREBID_PRICE_BUCKETS = {
'precision': 2,
'min' : 0,
Expand Down
33 changes: 27 additions & 6 deletions tasks/add_new_prebid_partner.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import sys
from builtins import input
from pprint import pprint
from collections import OrderedDict

from colorama import init

Expand All @@ -29,6 +30,7 @@
get_prices_summary_string,
micro_amount_to_num,
num_to_str,
get_prebid_standard_bucketing
)

# Colorama for cross-platform support for colored logging.
Expand Down Expand Up @@ -317,15 +319,34 @@ def main():
if bidder_code is None:
raise MissingSettingException('PREBID_BIDDER_CODE')

price_buckets = getattr(settings, 'PREBID_PRICE_BUCKETS', None)
if price_buckets is None:
raise MissingSettingException('PREBID_PRICE_BUCKETS')
price_buckets = None
price_buckets_config = getattr(settings, 'PREBID_PRICE_BUCKETS', None)
if price_buckets_config is None:
raise MissingSettingException('PREBID_PRICE_BUCKETS')
elif isinstance(price_buckets_config, dict):
price_buckets = [ price_buckets_config ]
elif isinstance(price_buckets_config, list):
price_buckets = price_buckets_config
elif isinstance(price_buckets_config, str):
price_buckets = get_prebid_standard_bucketing(price_buckets_config)
if price_buckets == None:
raise BadSettingException('Unknown price bucketing scheme \'{0}\' for PREBID_PRICE_BUCKETS'.format(price_buckets_config))
else:
raise BadSettingException('The setting "PREBID_PRICE_BUCKETS" '
'is an invalid type.')

for pb in price_buckets:
check_price_buckets_validity(pb)

prices = []
for pb in price_buckets:
prices.extend(get_prices_array(pb))

check_price_buckets_validity(price_buckets)
# Remove duplicates price buckets
prices = list(OrderedDict.fromkeys(prices))

prices = get_prices_array(price_buckets)
prices_summary = get_prices_summary_string(prices,
price_buckets['precision'])
price_buckets[0]['precision'])

logger.info(
u"""
Expand Down
71 changes: 68 additions & 3 deletions tasks/price_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def num_to_str(num, precision=2):
Returns:
a string
"""
return '%.{0}f'.format(str(precision)) % num
return '%.{0}f'.format(str(precision)) % num

def get_prices_array(price_bucket):
"""
Expand All @@ -48,7 +48,7 @@ def get_prices_array(price_bucket):
price_bucket (object): the price bucket configuration
Returns:
an array of integers: every price bucket cutoff from:
int(round(price_bucket['min'] * 10**6, precision)) to
int(round(price_bucket['min'] * 10**6, precision)) to
int(round(price_bucket['max'] * 10**6, precision))
"""
start_cpm = price_bucket['min'] if price_bucket['min'] >=0 else 0.00
Expand All @@ -65,7 +65,7 @@ def get_prices_array(price_bucket):
while current_cpm_micro_amount <= end_cpm_micro_amount:
prices.append(current_cpm_micro_amount)
current_cpm_micro_amount += increment_micro_amount

return prices

def get_prices_summary_string(prices_array, precision=2):
Expand Down Expand Up @@ -94,3 +94,68 @@ def get_prices_summary_string(prices_array, precision=2):
)

return summary

prebid_bucketing_schemes = {
"low": [{
'precision': 2,
'min' : 0,
'max' : 5,
'increment': 0.50,
}],
"medium": [{
'precision': 2,
'min' : 0,
'max' : 20,
'increment': 0.10,
}],
# High will try to create too many line items at once resulting in an error
#"high": [{
# 'precision': 2,
# 'min' : 0,
# 'max' : 20,
# 'increment': 0.01,
#}],
"auto": [
{
'precision': 2,
'min' : 0,
'max' : 3,
'increment': 0.05,
},
{
'precision': 2,
'min' : 3,
'max' : 8,
'increment': 0.05,
},
{
'precision': 2,
'min' : 8,
'max' : 20,
'increment': 0.50,
}],
"dense": [{
'precision': 2,
'min' : 0,
'max' : 3,
'increment': 0.01
},
{
'precision': 2,
'min' : 3,
'max' : 8,
'increment': 0.05,
},
{
'precision': 2,
'min' : 8,
'max' : 20,
'increment': 0.50,
}]
}

def get_prebid_standard_bucketing(bucketing_scheme):
if bucketing_scheme in prebid_bucketing_schemes:
return prebid_bucketing_schemes[bucketing_scheme]
else:
return None
Loading