module FacebookAds::CustomAudienceHelpers

Constants

MULTIKEY_SCHEMAS
SCHEMAS
SCHEMAS_WITHOUT_HASH

Public Instance Methods

add_user(data, schema, options = {}) click to toggle source
# File lib/facebook_ads/ad_objects/helpers/custom_audience_helpers.rb, line 53
def add_user(data, schema, options = {})
  self.users.create(prepare_params(data, schema, options))
end
prepare_params(data, schema, app_ids: nil, page_ids: nil, pre_hashed: false, namespace: nil, session: nil, data_source: nil) click to toggle source
# File lib/facebook_ads/ad_objects/helpers/custom_audience_helpers.rb, line 61
def prepare_params(data,
                   schema,
                   app_ids:     nil,
                   page_ids:    nil,
                   pre_hashed:  false,
                   namespace:   nil,
                   session:     nil,
                   data_source: nil)

  unless schema.is_a?(Array) || schema.split(',').length > 1
    # single key
    schema = schema.upcase
    unless is_valid_single_key?(schema) || is_combinational_key?(schema)
      raise InvalidParameterError, "#{schema} is not a valid schema"
    end

    data = pre_hashed ? data : data.map { |entry| generate_hash(entry, schema)}
    is_raw = !is_combinational_key?(schema)
  else
    # multi key
    schema = schema.split(',') unless schema.is_a?(Array)

    data = data.map do |row|
      raise 'Schema size and data size mismatch' if row.length != schema.length

      row.each_with_index.map do |val, idx|
        pre_hashed ? val : generate_hash(val, schema[idx])
      end
    end

    is_raw = !(schema.map { |s| is_combinational_key?(s) }.any?)
  end

  {
    payload: {
      schema: schema,
      data: data,
      is_raw: is_raw,
      app_ids: app_ids,
      page_ids: page_ids,
      data_source: data_source,
    }.compact,
    namespace: namespace,
    session: session,
  }.compact
end
remove_user(data, schema, options = {}) click to toggle source
# File lib/facebook_ads/ad_objects/helpers/custom_audience_helpers.rb, line 57
def remove_user(data, schema, options = {})
  self.users.destroy(prepare_params(data, schema, options))
end

Private Instance Methods

generate_hash(data, schema) click to toggle source
# File lib/facebook_ads/ad_objects/helpers/custom_audience_helpers.rb, line 117
def generate_hash(data, schema)
  SCHEMAS_WITHOUT_HASH.include?(schema) ? normalize(data, schema) : hash_sha256(normalize(data, schema))
end
hash_sha256(data) click to toggle source
# File lib/facebook_ads/ad_objects/helpers/custom_audience_helpers.rb, line 166
def hash_sha256(data)
  Digest::SHA256.hexdigest(data)
end
is_combinational_key?(schema) click to toggle source
# File lib/facebook_ads/ad_objects/helpers/custom_audience_helpers.rb, line 121
def is_combinational_key?(schema)
  schema_parts = schema.split('_').map(&:upcase)
  return false if schema == 'EXTERN_ID' || schema_parts.count <= 1
  # EXTERN_ID will be safe here since it's can be used as combination key

  (schema_parts - MULTIKEY_SCHEMAS).empty?
end
is_raw_schema?(schemas) click to toggle source
# File lib/facebook_ads/ad_objects/helpers/custom_audience_helpers.rb, line 113
def is_raw_schema?(schemas)
  (schemas - MULTIKEY_SCHEMAS).empty?
end
is_valid_single_key?(schema) click to toggle source
# File lib/facebook_ads/ad_objects/helpers/custom_audience_helpers.rb, line 109
def is_valid_single_key?(schema)
  SCHEMAS.include?(schema)
end
normalize(data, schema) click to toggle source
# File lib/facebook_ads/ad_objects/helpers/custom_audience_helpers.rb, line 129
def normalize(data, schema)
  schema = schema.gsub(/_SHA256$/,'') # remove hash suffix
  # Data normalization
  # Refer to https://developers.facebook.com/docs/marketing-api/audiences-api for rules

  case schema
    when 'EMAIL'
      data.to_s.strip.downcase
    when 'PHONE'
      data.to_s.gsub(/[^0-9]/,'')
    when 'GEN'
      # Match the first F or M character
      data.to_s[/[mfMF]/] || (raise InvalidParameterError, "Invalid value: #{data} for Gender")
    when 'DOBY'
      data.to_s.strip.gsub(/[^0-9]/,'')
    when 'DOBM','DOBD'
      data.to_s.strip.gsub(/[^0-9]/,'').rjust(2,'0')
    when 'LN', 'FN'
      data.to_s.strip.gsub(/[^[:alpha:]]/,'').downcase # using [:alpha] here to include also Unicode
    when 'FI'
      data.to_s.strip[0].downcase
    when 'ST', 'CT'
      data.to_s.strip.downcase.gsub(/[^a-z]+/,'')
    when 'ZIP'
      data.to_s.split('-').first.strip.gsub(/[:blank:]+/,'').downcase
    when 'MADID'
      data.to_s.downcase
    when 'COUNTRY'
      if data.strip.length != 2
        raise InvalidParameterError, "Only 2-letter country codes is accepted for COUNTRY"
      end
      data.strip.downcase
    else # UID, EXTERN_ID, MOBILE_ADVERTISER_ID
      data
  end
end