예제 #1
0
def check_price_buckets_validity(price_buckets):
  """
  Validate that the price_buckets object contains all required keys and the
  values are the expected types.

  Args:
    price_buckets (object)
  Returns:
    None
  """

  try:
    pb_precision = price_buckets['precision']
    pb_min = price_buckets['min']
    pb_max = price_buckets['max']
    pb_increment = price_buckets['increment']
  except KeyError:
    raise BadSettingException('The setting "PREBID_PRICE_BUCKETS" '
      'must contain keys "precision", "min", "max", and "increment".')

  if not (isinstance(pb_precision, int) or isinstance(pb_precision, float)):
    raise BadSettingException('The "precision" key in "PREBID_PRICE_BUCKETS" '
      'must be a number.')

  if not (isinstance(pb_min, int) or isinstance(pb_min, float)):
    raise BadSettingException('The "min" key in "PREBID_PRICE_BUCKETS" '
      'must be a number.')

  if not (isinstance(pb_max, int) or isinstance(pb_max, float)):
    raise BadSettingException('The "max" key in "PREBID_PRICE_BUCKETS" '
      'must be a number.')

  if not (isinstance(pb_increment, int) or isinstance(pb_increment, float)):
    raise BadSettingException('The "increment" key in "PREBID_PRICE_BUCKETS" '
      'must be a number.')
예제 #2
0
def get_advertiser_id_by_name(name):
    """
  Returns a DFP company ID from company name.

  Args:
    name (str): the name of the DFP advertiser
  Returns:
    an integer: the advertiser's DFP ID
  """
    dfp_client = get_client()
    company_service = dfp_client.GetService('CompanyService',
                                            version='v201802')

    # Filter by name.
    query = 'WHERE name = :name'
    values = [
        {
            'key': 'name',
            'value': {
                'xsi_type': 'TextValue',
                'value': name
            }
        },
    ]
    statement = dfp.FilterStatement(query, values)

    response = company_service.getCompaniesByStatement(statement.ToStatement())

    # A company is required.
    no_company_found = False
    try:
        no_company_found = True if len(response['results']) < 1 else False
    except (AttributeError, KeyError):
        no_company_found = True

    if no_company_found:
        if getattr(settings, 'DFP_CREATE_ADVERTISER_IF_DOES_NOT_EXIST', False):
            advertiser = create_advertiser(name)
        else:
            raise DFPObjectNotFound(
                'No advertiser found  with name {0}'.format(name))
    elif len(response['results']) > 1:
        raise BadSettingException(
            'Multiple advertisers found with name {0}'.format(name))
    else:
        advertiser = response['results'][0]

    logger.info(
        u'Using existing advertiser with ID "{id}", name "{name}", and '
        'type "{type}".'.format(id=advertiser['id'],
                                name=advertiser['name'],
                                type=advertiser['type']))

    return advertiser['id']
예제 #3
0
def create_order(order_name, advertiser_id, trafficker_id):
    """
  Creates an order in DFP.

  Args:
    order_name (str): the name of the order
    advertiser_id (int): the ID of the advertiser in DFP
    trafficker_id (int): the ID of the DFP user owning the order
  Returns:
    an integer: the ID of the created order
  """

    dfp_client = get_client()
    company_service = dfp_client.GetService('CompanyService',
                                            version='v201702')

    # Check to make sure an order does not exist with this name.
    # Otherwise, DFP will throw an exception.
    existing_order = dfp.get_orders.get_order_by_name(order_name)
    if existing_order is not None:

        # If the settings allow modifying an existing order, do so. Otherwise,
        # throw an exception.
        can_use_existing_order = getattr(settings,
                                         'DFP_USE_EXISTING_ORDER_IF_EXISTS',
                                         None)
        if can_use_existing_order:
            order = existing_order
            logger.info(
                'Using existing order with id "{id}" and name "{name}".'.
                format(id=order['id'], name=order['name']))
        else:
            raise BadSettingException(
                ('An order already exists with name {0}. '
                 'Please choose a new order name.').format(order_name))

    # No order with the name exists, so create it.
    else:
        orders = [
            create_order_config(name=order_name,
                                advertiser_id=advertiser_id,
                                trafficker_id=trafficker_id)
        ]
        order_service = dfp_client.GetService('OrderService',
                                              version='v201702')
        orders = order_service.createOrders(orders)

        order = orders[0]
        logger.info(
            u'Created an order with id "{id}" and name "{name}".'.format(
                id=order['id'], name=order['name']))

    return order['id']
def validateCSVValues(start_range, end_range, granularity, rate_id):
    if start_range < 0 or end_range < 0:
        raise BadSettingException(
            'Start range and end range can not be negative. Please correct the csv and try again.'
        )

    if start_range > end_range:
        raise BadSettingException(
            'Start range can not be more than end range. Please correct the csv and try again.'
        )

    if rate_id not in (1, 2):
        raise BadSettingException(
            'Rate id can only be 1 or 2. Please correct the csv and try again')

    if start_range < 0.01 and granularity == 0.01:
        raise BadSettingException(
            'Start range can not be less than 0.01 for granularity 0.01, either increase granularity or start range in csv.'
        )

    if end_range > 999:
        raise BadSettingException(
            'End range can not be more then 999. Please correct the csv and try again.'
        )

    if granularity == 0:
        raise BadSettingException(
            'Zero is not accepted as granularity. Please correct the csv and try again'
        )
예제 #5
0
def main():
    """
  Loads placements from settings and fetches them from DFP.

  Returns:
    None
  """

    placements = getattr(settings, 'DFP_TARGETED_PLACEMENT_NAMES', None)
    if placements is None:
        raise MissingSettingException('DFP_TARGETED_PLACEMENT_NAMES')
    elif len(placements) < 1:
        raise BadSettingException('The setting "DFP_TARGETED_PLACEMENT_NAMES" '
                                  'must contain at least one placement ID.')

    get_placement_ids_by_name(placements)
예제 #6
0
def main():
    """
  Loads ad units from settings and fetches them from DFP.

  Returns:
    None
  """

    ad_units = getattr(settings, 'DFP_TARGETED_AD_UNIT_NAMES', None)
    if ad_units is None:
        raise MissingSettingException('DFP_TARGETED_AD_UNIT_NAMES')
    elif len(ad_units) < 1:
        raise BadSettingException('The setting "DFP_TARGETED_AD_UNIT_NAMES" '
                                  'must contain at least one ad unit ID.')

    get_ad_unit_ids_by_name(ad_units)
예제 #7
0
def main():
    """
  Validate the settings and ask for confirmation from the user. Then,
  start all necessary DFP tasks.
  """

    user_email = getattr(settings, 'DFP_USER_EMAIL_ADDRESS', None)
    if user_email is None:
        raise MissingSettingException('DFP_USER_EMAIL_ADDRESS')

    advertiser_name = getattr(settings, 'DFP_ADVERTISER_NAME', None)
    if advertiser_name is None:
        raise MissingSettingException('DFP_ADVERTISER_NAME')

    order_name = getattr(settings, 'DFP_ORDER_NAME', None)
    if order_name is None:
        raise MissingSettingException('DFP_ORDER_NAME')

    placements = getattr(settings, 'DFP_TARGETED_PLACEMENT_NAMES', None)
    ad_units = getattr(settings, 'DFP_TARGETED_AD_UNIT_NAMES', None)

    video_ad_type = getattr(settings, 'DFP_VIDEO_AD_TYPE', False)
    vast_redirect_url = getattr(settings, 'DFP_VAST_REDIRECT_URL', '')

    if video_ad_type is True and len(vast_redirect_url) < 1:
        raise BadSettingException(
            'When setting "DFP_VIDEO_AD_TYPE" to "True", please also set "DFP_VAST_REDIRECT_URL".'
        )

    if ad_units is None and placements is None:
        raise MissingSettingException(
            'DFP_TARGETED_PLACEMENT_NAMES or DFP_TARGETED_AD_UNIT_NAMES')
    elif (placements is None
          or len(placements) < 1) and (ad_units is None or len(ad_units) < 1):
        raise BadSettingException(
            'The setting "DFP_TARGETED_PLACEMENT_NAMES" or "DFP_TARGETED_AD_UNIT_NAMES" '
            'must contain at least one DFP placement or ad unit.')

    sizes = getattr(settings, 'DFP_PLACEMENT_SIZES', None)
    if sizes is None:
        raise MissingSettingException('DFP_PLACEMENT_SIZES')
    elif len(sizes) < 1:
        raise BadSettingException('The setting "DFP_PLACEMENT_SIZES" '
                                  'must contain at least one size object.')

    currency_code = getattr(settings, 'DFP_CURRENCY_CODE', 'USD')

    line_item_format = getattr(settings, 'DFP_LINE_ITEM_FORMAT',
                               u'{bidder_code}: HB ${price}')

    # How many creatives to attach to each line item. We need at least one
    # creative per ad unit on a page. See:
    # https://github.com/kmjennison/dfp-prebid-setup/issues/13
    num_creatives = (getattr(settings, 'DFP_NUM_CREATIVES_PER_LINE_ITEM', None)
                     or len(placements) + len(ad_units))

    bidder_code = getattr(settings, 'PREBID_BIDDER_CODE', None)
    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')

    check_price_buckets_validity(price_buckets)

    prices = get_prices_array(price_buckets)
    prices_summary = get_prices_summary_string(prices)

    logger.info(u"""

    Going to create {name_start_format}{num_line_items}{format_end} new line items.
      {name_start_format}Order{format_end}: {value_start_format}{order_name}{format_end}
      {name_start_format}Advertiser{format_end}: {value_start_format}{advertiser}{format_end}

    Line items will have targeting:
      {name_start_format}hb_pb{format_end} = {value_start_format}{prices_summary}{format_end}
      {name_start_format}hb_bidder{format_end} = {value_start_format}{bidder_code}{format_end}
      {name_start_format}placements{format_end} = {value_start_format}{placements}{format_end}
      {name_start_format}ad units{format_end} = {value_start_format}{ad_units}{format_end}
    """.format(
        num_line_items=len(prices),
        order_name=order_name,
        advertiser=advertiser_name,
        user_email=user_email,
        prices_summary=prices_summary,
        bidder_code=bidder_code,
        placements=placements,
        ad_units=ad_units,
        sizes=sizes,
        name_start_format=color.BOLD,
        format_end=color.END,
        value_start_format=color.BLUE,
    ))

    if video_ad_type:
        logger.info(
            u"""    Line items will have VAST redirect creatives with redirect URL:
      {value_start_format}{redirect_url}{format_end}

    """.format(
                redirect_url=vast_redirect_url,
                value_start_format=color.BLUE,
                format_end=color.END,
            ))
    else:
        logger.info(
            u"""    Line items will have third party creatives based on snippet.html content.

    """)

    ok = input('Is this correct? (y/n)\n')

    if ok != 'y':
        logger.info('Exiting.')
        return

    setup_partner(user_email, advertiser_name, order_name, placements,
                  ad_units, sizes, bidder_code, prices, num_creatives,
                  currency_code, line_item_format, video_ad_type,
                  vast_redirect_url)
def main():
    """
  Validate the settings and ask for confirmation from the user. Then,
  start all necessary DFP tasks.
  """

    user_email = getattr(settings, 'DFP_USER_EMAIL_ADDRESS', None)
    if user_email is None:
        raise MissingSettingException('DFP_USER_EMAIL_ADDRESS')

    advertiser_name = getattr(settings, 'DFP_ADVERTISER_NAME', None)
    if advertiser_name is None:
        raise MissingSettingException('DFP_ADVERTISER_NAME')

    advertiser_type = getattr(settings, 'DFP_ADVERTISER_TYPE', "ADVERTISER")
    if advertiser_type != "ADVERTISER" and advertiser_type != "AD_NETWORK":
        raise BadSettingException('DFP_ADVERTISER_TYPE')

    order_name = getattr(settings, 'DFP_ORDER_NAME', None)
    if order_name is None:
        raise MissingSettingException('DFP_ORDER_NAME')

    lineitem_type = getattr(settings, 'DFP_LINEITEM_TYPE', None)
    if lineitem_type is None:
        raise MissingSettingException('DFP_LINEITEM_TYPE')

    num_placements = 0
    placements = getattr(settings, 'DFP_TARGETED_PLACEMENT_NAMES', None)
    placements_print = str(placements)
    if placements is None:
        placements = []
        placements_print = "RON"

    # if no placements are specified, we wil do run of network which is
    #   effectively one placement
    num_placements = len(placements)
    if num_placements == 0:
        num_placements = 1
        placements_print = "RON"
    creative_type = getattr(settings, 'OPENWRAP_CREATIVE_TYPE', None)
    if creative_type is None:
        creative_type = constant.WEB
    elif creative_type not in [
            constant.WEB, constant.WEB_SAFEFRAME, constant.AMP,
            constant.IN_APP, constant.NATIVE, constant.VIDEO,
            constant.JW_PLAYER
    ]:
        raise BadSettingException(
            'Unknown OPENWRAP_CREATIVE_TYPE: {0}'.format(creative_type))

    sizes = getattr(settings, 'DFP_PLACEMENT_SIZES', None)
    if creative_type != constant.NATIVE:
        if sizes is None:
            raise MissingSettingException('DFP_PLACEMENT_SIZES')
        elif len(sizes) < 1:
            raise BadSettingException('The setting "DFP_PLACEMENT_SIZES" '
                                      'must contain at least one size object.')

    currency_code = getattr(settings, 'DFP_CURRENCY_CODE', 'USD')

    # How many creatives to attach to each line item. We need at least one
    # creative per ad unit on a page. See:
    # https://github.com/kmjennison/dfp-prebid-setup/issues/13
    num_creatives = (getattr(settings, 'DFP_NUM_CREATIVES_PER_LINE_ITEM', None)
                     or num_placements)

    # read creative template for native Line-items
    creative_template = None
    if creative_type == constant.NATIVE:
        creative_template = getattr(settings, 'OPENWRAP_CREATIVE_TEMPLATE',
                                    None)
        if creative_template is None:
            raise MissingSettingException('OPENWRAP_CREATIVE_TEMPLATE')
        elif not isinstance(creative_template, (list, str)):
            raise BadSettingException('OPENWRAP_CREATIVE_TEMPLATE')
        if isinstance(creative_template, str):
            creative_template = [creative_template]

    bidder_code = getattr(settings, 'PREBID_BIDDER_CODE', None)
    if bidder_code is not None and not isinstance(bidder_code,
                                                  (list, tuple, str)):
        raise BadSettingException('PREBID_BIDDER_CODE')

    same_adv_exception = getattr(settings, 'DFP_SAME_ADV_EXCEPTION', False)
    if not isinstance(same_adv_exception, bool):
        raise BadSettingException('DFP_SAME_ADV_EXCEPTION')

    device_categories = getattr(settings, 'DFP_DEVICE_CATEGORIES', None)
    if device_categories is not None and not isinstance(
            device_categories, (list, tuple, str)):
        raise BadSettingException('DFP_DEVICE_CATEGORIES')

    device_capabilities = None
    #   We do not want to restrict line item based on device capabilties
    #   Disabling after a discussion with Lloyd
    #   if creative_type is constant.IN_APP:
    #       device_capabilities = ('Mobile Apps', 'MRAID v1', 'MRAID v2')

    roadblock_type = getattr(settings, 'DFP_ROADBLOCK_TYPE', 'ONE_OR_MORE')
    if roadblock_type not in ('ONE_OR_MORE', 'AS_MANY_AS_POSSIBLE'):
        raise BadSettingException('DFP_ROADBLOCK_TYPE')

    lineitem_prefix = getattr(settings, 'LINE_ITEM_PREFIX', None)
    if lineitem_prefix != None:
        if not isinstance(lineitem_prefix, (str)):
            raise BadSettingException('LINE_ITEM_PREFIX')

    use_1x1 = getattr(settings, 'OPENWRAP_USE_1x1_CREATIVE', False)
    if not isinstance(use_1x1, bool):
        raise BadSettingException('OPENWRAP_USE_1x1_CREATIVE')

    custom_targeting = getattr(settings, 'OPENWRAP_CUSTOM_TARGETING', None)
    if custom_targeting != None:
        if not isinstance(custom_targeting, (list, tuple)):
            raise BadSettingException('OPENWRAP_CUSTOM_TARGETING')

        for ct in custom_targeting:
            if len(ct) != 3:
                raise BadSettingException('OPENWRAP_CUSTOM_TARGETING')

            if ct[1] != "IS" and ct[1] != "IS_NOT":
                raise BadSettingException('OPENWRAP_CUSTOM_TARGETING')

            if not isinstance(ct[2], (list, tuple, str, bool)):
                raise BadSettingException(
                    'OPENWRAP_CUSTOM_TARGETING - {0}'.format(type(ct[2])))

    price_buckets_csv = getattr(settings, 'OPENWRAP_BUCKET_CSV', None)
    if price_buckets_csv is None:
        raise MissingSettingException('OPENWRAP_BUCKET_CSV')

    prices = load_price_csv(price_buckets_csv, creative_type)

    prices_summary = []
    for p in prices:
        prices_summary.append(p['rate'])

    if len(prices) > constant.LINE_ITEMS_LIMIT:
        print(
            '\n Error: {} Lineitems will be created. This is exceeding Line items count per order of {}!\n'
            .format(len(prices), constant.LINE_ITEMS_LIMIT))
        return

    # set bidder_code, custom_targetting, device categories to None when creative_type is IN-APP, JW_PLAYER
    # default roadblock_type to ONE_OR_MORE when creative_type is VIDEO, JW_PLAYER
    # default roadblock type to 'AS_MANY_AS_POSSIBLE' when creative_type is in-app

    if creative_type == constant.IN_APP:
        roadblock_type = 'AS_MANY_AS_POSSIBLE'
        #bidder_code = None
        custom_targeting = None
        device_categories = None
    elif creative_type == constant.JW_PLAYER:
        roadblock_type = 'ONE_OR_MORE'
        bidder_code = ['pubmatic']
        custom_targeting = None
        device_categories = None
    elif creative_type == constant.VIDEO:
        roadblock_type = 'ONE_OR_MORE'

    logger.info(u"""

    Going to create {name_start_format}{num_line_items}{format_end} new line items.
      {name_start_format}Order{format_end}: {value_start_format}{order_name}{format_end}
      {name_start_format}Advertiser{format_end}: {value_start_format}{advertiser}{format_end}
      {name_start_format}Advertiser Type{format_end}: {value_start_format}{advertiser_type}{format_end}
      {name_start_format}LineItem Type{format_end}: {value_start_format}{lineitem_type}{format_end}
      {name_start_format}LineItem Prefix{format_end}: {value_start_format}{lineitem_prefix}{format_end}
      {name_start_format}Creative Type{format_end} = {value_start_format}{creative_type}{format_end}
      {name_start_format}Use 1x1 Creative{format_end} = {value_start_format}{use_1x1}{format_end}

    Line items will have targeting:
      {name_start_format}rates{format_end} = {value_start_format}{prices_summary}{format_end}
      {name_start_format}bidders{format_end} = {value_start_format}{bidder_code}{format_end}
      {name_start_format}placements{format_end} = {value_start_format}{placements}{format_end}
      {name_start_format}custom targeting{format_end} = {value_start_format}{custom_targeting}{format_end}
      {name_start_format}same advertiser exception{format_end} = {value_start_format}{same_adv_exception}{format_end}
      {name_start_format}device categories{format_end} = {value_start_format}{device_categories}{format_end}
      {name_start_format}device capabilities{format_end} = {value_start_format}{device_capabilities}{format_end}
      {name_start_format}roadblock type{format_end} = {value_start_format}{roadblock_type}{format_end}
    """.format(
        num_line_items=len(prices),
        order_name=order_name,
        advertiser=advertiser_name,
        advertiser_type=advertiser_type,
        lineitem_type=lineitem_type,
        lineitem_prefix=lineitem_prefix,
        creative_type=creative_type,
        user_email=user_email,
        prices_summary=prices_summary,
        bidder_code=bidder_code,
        placements=placements_print,
        sizes=sizes,
        custom_targeting=custom_targeting,
        same_adv_exception=same_adv_exception,
        device_categories=device_categories,
        device_capabilities=device_capabilities,
        roadblock_type=roadblock_type,
        use_1x1=use_1x1,
        name_start_format=color.BOLD,
        format_end=color.END,
        value_start_format=color.BLUE,
    ))

    ok = input('Is this correct? (y/n)\n')

    if ok != 'y':
        logger.info('Exiting.')
        return

    try:
        setup_partner(user_email, advertiser_name, advertiser_type, order_name,
                      placements, sizes, lineitem_type, lineitem_prefix,
                      bidder_code, prices, creative_type, creative_template,
                      num_creatives, use_1x1, currency_code, custom_targeting,
                      same_adv_exception, device_categories,
                      device_capabilities, roadblock_type)
    except ConnectionError as e:
        logger.error(
            '\nConnection Error. Please try again after some time! Err: \n{}'.
            format(e))
    except GoogleAdsServerFault as e:
        if "ServerError.SERVER_ERROR" in str(e):
            logger.error(
                '\n\nDFP Server Error. Please try again after some time! Err: \n{}'
                .format(e))
        else:
            raise DFPException(
                "\n\nError occured while creating Lineitems in DFP: \n {}".
                format(e))
def load_price_csv(filename, creative_type):
    buckets = []
    exchange_rate = 1

    #read currency conversion flag
    currency_exchange = True

    # Currency module/CURRENCY_EXCHANGE is applicable for web and native platform
    if creative_type in (constant.WEB, constant.WEB_SAFEFRAME,
                         constant.NATIVE):
        currency_exchange = getattr(settings, 'CURRENCY_EXCHANGE', True)

    if currency_exchange:
        network = get_dfp_network()
        logger.info("Network currency : %s", network.currencyCode)
        exchange_rate = get_exchange_rate(network.currencyCode)

    logger.info("Currency exchange rate: {}".format(exchange_rate))
    #currency rate handling till here
    with open(filename, 'r') as csvfile:
        preader = csv.reader(csvfile)
        next(preader)  # skip header row
        for row in preader:
            # ignore extra lines or spaces
            if row == [] or row[0].strip() == "":
                continue
            print(row)

            try:
                start_range = float(row[2])
                end_range = float(row[3])
                granularity = float(row[4])
                rate_id = int(row[5])
            except ValueError:
                raise BadSettingException(
                    'Start range, end range, granularity and rate id should be number. Please correct the csv and try again.'
                )

            validateCSVValues(start_range, end_range, granularity, rate_id)

            if granularity != -1:
                i = start_range
                while i < end_range:
                    a = round(i + granularity, 2)
                    if a > end_range:
                        a = end_range

                    if round(i, 2) != (a, 2):
                        buckets.append({
                            'start':
                            i,
                            'end':
                            a,
                            'granularity':
                            granularity,
                            'rate':
                            get_calculated_rate(i, a, rate_id, exchange_rate)
                        })
                    i = a
            else:
                buckets.append({
                    'start':
                    start_range,
                    'end':
                    end_range,
                    'granularity':
                    1.0,
                    'rate':
                    get_calculated_rate(start_range, end_range, rate_id,
                                        exchange_rate)
                })

    return buckets
def setup_partner(user_email, advertiser_name, advertiser_type, order_name,
                  placements, sizes, lineitem_type, lineitem_prefix,
                  bidder_code, prices, creative_type, creative_template,
                  num_creatives, use_1x1, currency_code, custom_targeting,
                  same_adv_exception, device_categories, device_capabilities,
                  roadblock_type):
    """
  Call all necessary DFP tasks for a new Prebid partner setup.
  """

    # Get the user.
    user_id = dfp.get_users.get_user_id_by_email(user_email)

    # Get the placement IDs.
    placement_ids = None
    ad_unit_ids = None
    if len(placements) > 0:
        placement_ids = dfp.get_placements.get_placement_ids_by_name(
            placements)
    else:
        # Run of network
        root_id = dfp.get_root_ad_unit_id.get_root_ad_unit_id()
        ad_unit_ids = [root_id]

    # Get the device category IDs
    # Dont get device categories for in-app and jwplayer platform
    device_category_ids = None
    if device_categories != None and creative_type not in (constant.IN_APP,
                                                           constant.JW_PLAYER):
        device_category_ids = []
        if isinstance(device_categories, str):
            device_categories = (device_categories)

        dc_map = dfp.get_device_categories.get_device_categories()

        for dc in device_categories:
            if dc in dc_map:
                device_category_ids.append(dc_map[dc])
            else:
                raise BadSettingException(
                    "Invalid Device Cagetory: {} ".format(dc))

    #get device capabilty ids for in-APP platform
    device_capability_ids = None
    if device_capabilities != None and creative_type is constant.IN_APP:
        device_capability_ids = []
        if isinstance(device_capabilities, str):
            device_capabilities = (device_capabilities)

        dc_map = dfp.get_device_capabilities.get_device_capabilities()

        for dc in device_capabilities:
            if dc in dc_map:
                device_capability_ids.append(dc_map[dc])
            else:
                raise BadSettingException(
                    "Invalid Device Capability: {} ".format(dc))

    # Get (or potentially create) the advertiser.
    advertiser_id = dfp.get_advertisers.get_advertiser_id_by_name(
        advertiser_name, advertiser_type)

    # Create the order.
    order_id = dfp.create_orders.create_order(order_name, advertiser_id,
                                              user_id)

    # Create creatives.
    #Get creative template for native platform
    creative_template_ids = None
    if creative_type == constant.NATIVE:
        creative_template_ids = dfp.get_creative_template.get_creative_template_ids_by_name(
            creative_template)

    #if bidder is None, then bidder will be 'All'
    bidder_str = bidder_code
    if bidder_str == None:
        bidder_str = "All"
    elif isinstance(bidder_str, (list, tuple)):
        bidder_str = "_".join(bidder_str)

    #generate unique id that will be used for creative and line item naming
    unique_id = get_unique_id(creative_type)

    #create creatives
    logger.info("creating creatives...")
    size_arg = sizes
    if use_1x1:
        size_arg = None

    creative_configs = get_creative_config(creative_type,
                                           bidder_str,
                                           order_name,
                                           advertiser_id,
                                           size_arg,
                                           num_creatives,
                                           creative_template_ids,
                                           prefix=unique_id)
    creative_ids = dfp.create_creatives.create_creatives(creative_configs)

    # if platform is video, create creative sets
    if creative_type in (constant.VIDEO, constant.JW_PLAYER):
        creative_set_configs = dfp.create_creative_sets.create_creative_set_config(
            creative_ids, sizes, unique_id)
        creative_ids = dfp.create_creative_sets.create_creative_sets(
            creative_set_configs)

    # Create line items.
    # if line item prefix is not passed, set unique id as lineitem prefix
    if lineitem_prefix is None:
        lineitem_prefix = unique_id

    logger.info("creating line_items_config...")
    line_items_config = create_line_item_configs(
        prices,
        order_id,
        placement_ids,
        bidder_code,
        sizes,
        OpenWrapTargetingKeyGen(),
        lineitem_type,
        lineitem_prefix,
        currency_code,
        custom_targeting,
        creative_type,
        creative_template_ids,
        same_adv_exception=same_adv_exception,
        ad_unit_ids=ad_unit_ids,
        device_category_ids=device_category_ids,
        device_capability_ids=device_capability_ids,
        roadblock_type=roadblock_type)

    logger.info("Creating line items...")
    line_item_ids = dfp.create_line_items.create_line_items(line_items_config)

    # Associate creatives with line items.
    size_overrides = []
    if use_1x1 and creative_type is not constant.NATIVE:
        size_overrides = sizes
    logger.info("Creating lineitem creative associations...")
    dfp.associate_line_items_and_creatives.make_licas(
        line_item_ids,
        creative_ids,
        size_overrides=size_overrides,
        creative_type=creative_type)

    logger.info("""

    Done! Please review your order, line items, and creatives to
    make sure they are correct. Then, approve the order in DFP.

    Happy bidding!

  """)
예제 #11
0
def main():
    """
  Validate the settings and ask for confirmation from the user. Then,
  start all necessary DFP tasks.
  """

    user_email = getattr(settings, 'DFP_USER_EMAIL_ADDRESS', None)
    if user_email is None:
        raise MissingSettingException('DFP_USER_EMAIL_ADDRESS')

    advertiser_name = getattr(settings, 'DFP_ADVERTISER_NAME', None)
    if advertiser_name is None:
        raise MissingSettingException('DFP_ADVERTISER_NAME')

    order_name = getattr(settings, 'DFP_ORDER_NAME', None)
    if order_name is None:
        raise MissingSettingException('DFP_ORDER_NAME')

    placements = getattr(settings, 'DFP_TARGETED_PLACEMENT_NAMES', None)
    if placements is None:
        raise MissingSettingException('DFP_TARGETED_PLACEMENT_NAMES')
    elif len(placements) < 1:
        raise BadSettingException(
            'The setting "DFP_TARGETED_PLACEMENT_NAMES" '
            'must contain at least one DFP placement ID.')

    sizes = getattr(settings, 'DFP_PLACEMENT_SIZES', None)
    if sizes is None:
        raise MissingSettingException('DFP_PLACEMENT_SIZES')
    elif len(sizes) < 1:
        raise BadSettingException('The setting "DFP_PLACEMENT_SIZES" '
                                  'must contain at least one size object.')

    currency_code = getattr(settings, 'DFP_CURRENCY_CODE', 'USD')

    # How many creatives to attach to each line item. We need at least one
    # creative per ad unit on a page. See:
    # https://github.com/kmjennison/dfp-prebid-setup/issues/13
    num_creatives = (getattr(settings, 'DFP_NUM_CREATIVES_PER_LINE_ITEM', None)
                     or len(placements))

    bidder_code = getattr(settings, 'PREBID_BIDDER_CODE', None)
    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')

    check_price_buckets_validity(price_buckets)

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

    logger.info(u"""

    Going to create {name_start_format}{num_line_items}{format_end} new line items.
      {name_start_format}Order{format_end}: {value_start_format}{order_name}{format_end}
      {name_start_format}Advertiser{format_end}: {value_start_format}{advertiser}{format_end}

    Line items will have targeting:
      {name_start_format}hb_pb{format_end} = {value_start_format}{prices_summary}{format_end}
      {name_start_format}hb_bidder{format_end} = {value_start_format}{bidder_code}{format_end}
      {name_start_format}placements{format_end} = {value_start_format}{placements}{format_end}

    """.format(
        num_line_items=len(prices),
        order_name=order_name,
        advertiser=advertiser_name,
        user_email=user_email,
        prices_summary=prices_summary,
        bidder_code=bidder_code,
        placements=placements,
        sizes=sizes,
        name_start_format=color.BOLD,
        format_end=color.END,
        value_start_format=color.BLUE,
    ))

    ok = input('Is this correct? (y/n)\n')

    if ok != 'y':
        logger.info('Exiting.')
        return

    setup_partner(
        user_email,
        advertiser_name,
        order_name,
        placements,
        sizes,
        bidder_code,
        prices,
        num_creatives,
        currency_code,
    )
예제 #12
0
def main():
    """
  Validate the settings and ask for confirmation from the user. Then,
  start all necessary DFP tasks.
  """

    user_email = getattr(settings, 'DFP_USER_EMAIL_ADDRESS', None)
    if user_email is None:
        raise MissingSettingException('DFP_USER_EMAIL_ADDRESS')

    advertiser_name = getattr(settings, 'DFP_ADVERTISER_NAME', None)
    if advertiser_name is None:
        raise MissingSettingException('DFP_ADVERTISER_NAME')

    order_name = getattr(settings, 'DFP_ORDER_NAME', None)
    if order_name is None:
        raise MissingSettingException('DFP_ORDER_NAME')

    placements = getattr(settings, 'DFP_TARGETED_PLACEMENT_NAMES', None)
    no_inventory = getattr(settings, 'DFP_ALLOW_NO_INVENTORY_TARGETING', None)
    if placements is None:
        raise MissingSettingException('DFP_TARGETED_PLACEMENT_NAMES')
    elif len(placements) < 1 and no_inventory is not True:
        raise BadSettingException(
            'The setting "DFP_TARGETED_PLACEMENT_NAMES" '
            'must contain at least one DFP placement ID.')

    sizes = getattr(settings, 'DFP_PLACEMENT_SIZES', None)
    if sizes is None:
        raise MissingSettingException('DFP_PLACEMENT_SIZES')
    elif len(sizes) < 1:
        raise BadSettingException('The setting "DFP_PLACEMENT_SIZES" '
                                  'must contain at least one size object.')

    currency_code = getattr(settings, 'DFP_CURRENCY_CODE', 'USD')

    # How many creatives to attach to each line item. We need at least one
    # creative per ad unit on a page. See:
    # https://github.com/kmjennison/dfp-prebid-setup/issues/13
    num_creatives = (getattr(settings, 'DFP_NUM_CREATIVES_PER_LINE_ITEM', None)
                     or len(placements))

    # In the case where no inventory is being used, make sure at least one
    # creative is created
    if not num_creatives > 0:
        num_creatives = 1

    bidder_code = getattr(settings, 'PREBID_BIDDER_CODE', None)
    if bidder_code is None:
        raise MissingSettingException('PREBID_BIDDER_CODE')

    bidder_params = getattr(settings, 'PREBID_BIDDER_PARAMS', None)
    hb_pb_key = 'hb_pb'
    additional_keys = ''

    if bidder_params is True:
        hb_pb_key += '_' + bidder_code
        hb_adid_key = 'hb_adid_' + bidder_code
        hb_size_key = 'hb_size_' + bidder_code

        if len(hb_pb_key) > 20:
            hb_pb_key = hb_pb_key[:20]

        if len(hb_adid_key) > 20:
            hb_adid_key = hb_adid_key[:20]

        if len(hb_size_key) > 20:
            hb_size_key = hb_size_key[:20]

        additional_keys = u"""

    Additionally, keys {name_start_format}{hb_adid_key}{format_end} and {name_start_format}{hb_size_key}{format_end} will be created.""".format(
            hb_adid_key=hb_adid_key,
            hb_size_key=hb_size_key,
            name_start_format=color.BOLD,
            format_end=color.END,
        )

    price_buckets = getattr(settings, 'PREBID_PRICE_BUCKETS', None)
    if price_buckets is None:
        raise MissingSettingException('PREBID_PRICE_BUCKETS')

    check_price_buckets_validity(price_buckets)

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

    logger.info(u"""

    Going to create {name_start_format}{num_line_items}{format_end} new line items.
      {name_start_format}Order{format_end}: {value_start_format}{order_name}{format_end}
      {name_start_format}Advertiser{format_end}: {value_start_format}{advertiser}{format_end}
      {name_start_format}Owner{format_end}: {value_start_format}{user_email}{format_end}

    Line items will have targeting:
      {name_start_format}{hb_pb_key}{format_end} = {value_start_format}{prices_summary}{format_end}
      {name_start_format}hb_bidder{format_end} = {value_start_format}{bidder_code}{format_end}
      {name_start_format}placements{format_end} = {value_start_format}{placements}{format_end}{additional_keys}

    """.format(num_line_items=len(prices),
               order_name=order_name,
               advertiser=advertiser_name,
               user_email=user_email,
               hb_pb_key=hb_pb_key,
               prices_summary=prices_summary,
               bidder_code=bidder_code,
               placements=placements,
               sizes=sizes,
               name_start_format=color.BOLD,
               format_end=color.END,
               value_start_format=color.BLUE,
               additional_keys=additional_keys))

    ok = input('Is this correct? (y/n)\n')

    if ok != 'y':
        logger.info('Exiting.')
        return

    setup_partner(
        user_email,
        advertiser_name,
        order_name,
        placements,
        sizes,
        bidder_code,
        prices,
        num_creatives,
        currency_code,
    )
def main():
    """
  Validate the settings and ask for confirmation from the user. Then,
  start all necessary DFP tasks.
  """

    user_email = getattr(settings, 'DFP_USER_EMAIL_ADDRESS', None)
    if user_email is None:
        raise MissingSettingException('DFP_USER_EMAIL_ADDRESS')

    advertiser_name = getattr(settings, 'DFP_ADVERTISER_NAME', None)
    if advertiser_name is None:
        raise MissingSettingException('DFP_ADVERTISER_NAME')

    order_name = getattr(settings, 'DFP_ORDER_NAME', None)
    if order_name is None:
        raise MissingSettingException('DFP_ORDER_NAME')

    placements = getattr(settings, 'DFP_TARGETED_PLACEMENT_NAMES', [])
    ad_units = getattr(settings, 'DFP_TARGETED_AD_UNIT_NAMES', [])

    if not ad_units and not placements:
        raise MissingSettingException(
            'DFP_TARGETED_PLACEMENT_NAMES or DFP_TARGETED_AD_UNIT_NAMES')
    elif (not placements or len(placements) < 1) and (not ad_units
                                                      or len(ad_units) < 1):
        raise BadSettingException(
            'The setting "DFP_TARGETED_PLACEMENT_NAMES" or "DFP_TARGETED_AD_UNIT_NAMES" '
            'must contain at least one DFP placement or ad unit.')

    sizes = getattr(settings, 'DFP_PLACEMENT_SIZES', None)
    if sizes is None:
        raise MissingSettingException('DFP_PLACEMENT_SIZES')
    elif len(sizes) < 1:
        raise BadSettingException('The setting "DFP_PLACEMENT_SIZES" '
                                  'must contain at least one size object.')

    currency_code = getattr(settings, 'DFP_CURRENCY_CODE', 'USD')

    # How many creatives to attach to each line item. We need at least one
    # creative per ad unit on a page. See:
    # https://github.com/kmjennison/dfp-prebid-setup/issues/13
    num_creatives = (getattr(settings, 'DFP_NUM_CREATIVES_PER_LINE_ITEM', None)
                     or len(placements))

    bidder_code = getattr(settings, 'PREBID_BIDDER_CODE', None)
    if bidder_code is None:
        logger.warning(
            'PREBID_BIDDER_CODE is not specified. Create one set of line items for all bidders.'
        )

    price_bucket_list = getattr(settings, 'PREBID_PRICE_BUCKETS', None)
    if price_bucket_list is None:
        raise MissingSettingException('PREBID_PRICE_BUCKETS')

    price_multipliers = getattr(settings, 'PRICE_MULTIPLIERS', {})
    price_multiplier = price_multipliers.get(currency_code, 1)

    # Validate price buckets and adjust by price_multiplier
    adjusted_price_buckets = []
    for price_bucket in price_bucket_list:
        check_price_buckets_validity(price_bucket)
        adjusted_price_buckets.append(
            adjust_price_bucket_by_price_multiplier(price_bucket,
                                                    price_multiplier))

    prices = get_prices_array_from_price_bucket_list(adjusted_price_buckets)
    prices_summary = get_prices_summary_string(
        prices, price_bucket_list[0]['precision'])

    logger.info(u"""

    Going to create {name_start_format}{num_line_items}{format_end} new line items.
      {name_start_format}Order{format_end}: {value_start_format}{order_name}{format_end}
      {name_start_format}Advertiser{format_end}: {value_start_format}{advertiser}{format_end}

    Line items will have targeting:
      {name_start_format}hb_pb{format_end} = {value_start_format}{prices_summary}{format_end}
      {name_start_format}hb_bidder{format_end} = {value_start_format}{bidder_code}{format_end}
      {name_start_format}placements{format_end} = {value_start_format}{placements}{format_end}
      {name_start_format}ad units{format_end} = {value_start_format}{ad_units}{format_end}

    """.format(
        num_line_items=len(prices),
        order_name=order_name,
        advertiser=advertiser_name,
        user_email=user_email,
        prices_summary=prices_summary,
        bidder_code=bidder_code or '(Targeting all bidders)',
        placements=placements,
        ad_units=ad_units,
        sizes=sizes,
        name_start_format=color.BOLD,
        format_end=color.END,
        value_start_format=color.BLUE,
    ))

    ok = input('Is thisy correct? (y/n)\n')

    if ok != 'y':
        logger.info('Exiting.')
        return

    setup_partner(user_email, advertiser_name, order_name, placements,
                  ad_units, sizes, bidder_code, prices, num_creatives,
                  currency_code)