Class: FacebookAds::ServerSide::Util

Inherits:
Object
  • Object
show all
Defined in:
lib/facebook_ads/ad_objects/server_side/util.rb

Constant Summary collapse

PHONE_NUMBER_IGNORE_CHAR_SET =
/[\-\s\(\)]+/
PHONE_NUMBER_DROP_PREFIX_ZEROS =
/^\+?0{0,2}/
US_PHONE_NUMBER_REGEX =
/^1\(?\d{3}\)?\d{7}$/
INTL_PHONE_NUMBER_REGEX =
/^\d{1,4}\(?\d{2,3}\)?\d{4,}$/
EMAIL_REGEX =

RFC 2822 for email format

/\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i

Class Method Summary collapse

Class Method Details

.is_already_hashed?(input) ⇒ TrueClass|FalseClass

Boolean method which checks if a input is already hashed with MD5 or SHA256



119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/facebook_ads/ad_objects/server_side/util.rb', line 119

def self.is_already_hashed?(input)

  # We support Md5 and SHA256, and highly recommend users to use SHA256 for hashing PII keys.
  md5_match = /^[a-f0-9]{32}$/.match(input)
  sha256_match = /^[a-f0-9]{64}$/.match(input)

  if md5_match != nil or sha256_match != nil
    return true
  end

  return false
end

.is_international_number?(phone_number) ⇒ TrueClass | FalseClass

Boolean method which checks if a given number is represented in international format



239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/facebook_ads/ad_objects/server_side/util.rb', line 239

def self.is_international_number?(phone_number)

  # Drop upto 2 leading 0s from the number
  phone_number = phone_number.gsub(PHONE_NUMBER_DROP_PREFIX_ZEROS, '')

  if phone_number.start_with?('0')
    return false;
  end

  if phone_number.start_with?('1') && US_PHONE_NUMBER_REGEX.match(phone_number) != nil
    return false;
  end

  if INTL_PHONE_NUMBER_REGEX.match(phone_number) != nil
    return true;
  end

  return false;
end

.normalize(input, field_type) ⇒ String

Normalizes the input string given the field_type



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/facebook_ads/ad_objects/server_side/util.rb', line 54

def self.normalize(input, field_type)

  if input.nil? or field_type.nil?
    return nil;
  end

  input = input.strip.downcase

  # If the data is already hashed, we by-pass input normalization
  if is_already_hashed?(input) == true
    return input
  end

  normalized_input = input;

  case field_type
  when 'action_source'
    return normalize_action_source input
  when 'country'
    normalized_input = normalize_country input
  when 'ct'
    normalized_input = normalize_city input
  when 'currency'
    return normalize_currency input
  when 'delivery_category'
    return normalize_delivery_category input
  when 'em'
    normalized_input = normalize_email input
  when 'ge'
    normalized_input = normalize_gender input
  when 'ph'
    normalized_input = normalize_phone input
  when 'st'
    normalized_input = normalize_state input
  when 'zp'
    normalized_input = normalize_zip input
  when 'f5first'
    normalized_input = normalize_f5 input
  when 'f5last'
    normalized_input = normalize_f5 input
  when 'fi'
    normalized_input = normalize_fi input
  when 'dobd'
    normalized_input = normalize_dobd input
  when 'dobm'
    normalized_input = normalize_dobm input
  when 'doby'
    normalized_input = normalize_doby input
  end

  normalized_input = sha256Hash normalized_input

  return normalized_input
end

.normalize_action_source(action_source) ⇒ Object

Normalizes the input action_source and returns valid value (or throw exception if invalid).



311
312
313
314
315
316
317
318
319
320
# File 'lib/facebook_ads/ad_objects/server_side/util.rb', line 311

def self.normalize_action_source(action_source)
  unless FacebookAds::ServerSide::ActionSource.include?(action_source)
    values = FacebookAds::ServerSide::ActionSource.to_a.join(',')
    raise ArgumentError.new(
      "Invalid action_source passed: #{action_source}. Please use one of the defined values: #{values}"
    )
  end

  action_source
end

.normalize_array(input_array, field_type) ⇒ Array<String>

Normalizes the input array of strings given the field_type



39
40
41
42
43
44
45
46
47
48
# File 'lib/facebook_ads/ad_objects/server_side/util.rb', line 39

def self.normalize_array(input_array, field_type)
  return nil unless input_array.is_a?(Enumerable)
  return nil if input_array.empty?
  return nil unless input_array.all?{|value| value.is_a?(String)}

  input_array
    .map{|value| self.normalize(value, field_type)}
    .to_set
    .to_a
end

.normalize_city(city) ⇒ Object

Normalizes the given city and returns acceptable hashed city value



146
147
148
149
150
151
152
# File 'lib/facebook_ads/ad_objects/server_side/util.rb', line 146

def self.normalize_city(city)

     # Remove commonly occuring characters from city name.
  city = city.gsub(/[0-9.\s\-()]/,'')

  return city
end

.normalize_country(country) ⇒ Object

Normalizes the given country code and returns acceptable hashed country ISO code



133
134
135
136
137
138
139
140
141
142
143
# File 'lib/facebook_ads/ad_objects/server_side/util.rb', line 133

def self.normalize_country(country)

  # Replace unwanted characters and retain only alpha characters bounded for ISO code.
  country = country.gsub(/[^a-z]/,'')
  iso_country = ISO3166::Country.search(country)
  if iso_country == nil
    raise ArgumentError, "Invalid format for country:'" + country + "'.Please follow ISO 2-letter ISO 3166-1 standard for representing country. eg: us"
  end

  return  country
end

.normalize_currency(currency) ⇒ Object

Normalizes the given currency code and returns acceptable hashed currency ISO code



155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/facebook_ads/ad_objects/server_side/util.rb', line 155

def self.normalize_currency(currency)

  # Retain only alpha characters bounded for ISO code.
  currency = currency.gsub(/[^a-z]/,'')

  iso_currency = Money::Currency.find(currency)
  if iso_currency == nil
    raise ArgumentError, "Invalid format for currency:'" + currency + "'.Please follow ISO 3-letter ISO 4217 standard for representing currency. Eg: usd"
  end

  return currency;
end

.normalize_delivery_category(delivery_category) ⇒ Object

Normalizes the input delivery category and returns valid value (or throw exception if invalid).



301
302
303
304
305
306
307
308
# File 'lib/facebook_ads/ad_objects/server_side/util.rb', line 301

def self.normalize_delivery_category(delivery_category)

  unless FacebookAds::ServerSide::DeliveryCategory.include?(delivery_category)
    raise ArgumentError.new("Invalid delivery_category passed: " + delivery_category + ". Please use one of the defined values #{FacebookAds::ServerSide::DeliveryCategory.to_a.join(',')}" )
  end

  delivery_category;
end

.normalize_dobd(dobd) ⇒ Object



267
268
269
270
271
272
273
274
275
276
277
278
# File 'lib/facebook_ads/ad_objects/server_side/util.rb', line 267

def self.normalize_dobd(dobd)
  if dobd.length == 1
    dobd = '0' + dobd
  end

  dobd_int = dobd.to_i
  if dobd.length > 2 or dobd_int < 1 or dobd_int > 31
    raise ArgumentError.new("Invalid dobd format: '#{dobd}'. Please pass in a valid date of birth day in 'DD' format.")
  end

  return dobd
end

.normalize_dobm(dobm) ⇒ Object



280
281
282
283
284
285
286
287
288
289
290
291
# File 'lib/facebook_ads/ad_objects/server_side/util.rb', line 280

def self.normalize_dobm(dobm)
  if dobm.length == 1
    dobm = '0' + dobm
  end

  dobm_int = dobm.to_i
  if dobm.length > 2 or dobm_int < 1 or dobm_int > 12
    raise ArgumentError.new("Invalid dobm format: '#{dobm}'. Please pass in a valid date of birth month in 'MM' format.")
  end

  return dobm
end

.normalize_doby(doby) ⇒ Object



293
294
295
296
297
298
# File 'lib/facebook_ads/ad_objects/server_side/util.rb', line 293

def self.normalize_doby(doby)
  unless doby.match("^[0-9]{4}$")
    raise ArgumentError.new("Invalid doby format: '#{doby}'. Please pass in a valid birth year in 'YYYY' format.")
  end
  doby
end

.normalize_email(email) ⇒ Object

Normalizes the given email and returns acceptable hashed email value



169
170
171
172
173
174
175
176
# File 'lib/facebook_ads/ad_objects/server_side/util.rb', line 169

def self.normalize_email(email)

  if EMAIL_REGEX.match(email) == nil
    raise ArgumentError, "Invalid email format for the passed email: '#{email}'. Please check the passed email format."
  end

  return email
end

.normalize_f5(input) ⇒ Object



259
260
261
# File 'lib/facebook_ads/ad_objects/server_side/util.rb', line 259

def self.normalize_f5(input)
  input[0, 5]
end

.normalize_fi(fi) ⇒ Object



263
264
265
# File 'lib/facebook_ads/ad_objects/server_side/util.rb', line 263

def self.normalize_fi(fi)
  fi[0, 1]
end

.normalize_gender(gender) ⇒ Object

Normalizes the given gender and returns acceptable hashed gender value



179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/facebook_ads/ad_objects/server_side/util.rb', line 179

def self.normalize_gender(gender)

  # Replace extra characters with space, to bound under alpha characters set.
  gender = gender.gsub(/[^a-z]/,'')

  case gender
  when 'female' , 'f'
    gender = 'f'
  when 'male' , 'm'
    gender = 'm'
  else
    return nil
  end

  return gender
end

.normalize_phone(phone) ⇒ Object

Normalizes the given phone and returns acceptable hashed phone value



197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/facebook_ads/ad_objects/server_side/util.rb', line 197

def self.normalize_phone(phone)

  # Drop the spaces, hyphen and parenthesis from the Phone Number
  normalized_phone = phone.gsub(PHONE_NUMBER_IGNORE_CHAR_SET, '')

  if(is_international_number?(normalized_phone))
    normalized_phone = normalized_phone.gsub(PHONE_NUMBER_DROP_PREFIX_ZEROS, '')
  end

  if normalized_phone.length < 7 || normalized_phone.length > 15
    return nil;
  end

  return normalized_phone
end

.normalize_state(state) ⇒ Object

Normalizes the given state and returns acceptable hashed state value



214
215
216
217
218
# File 'lib/facebook_ads/ad_objects/server_side/util.rb', line 214

def self.normalize_state(state)
  state = state.gsub(/[0-9.\s\-()]/,'')

  return state
end

.normalize_zip(zip) ⇒ Object

Normalizes the given zip and returns acceptable hashed zip code value



221
222
223
224
225
226
227
228
229
230
231
232
233
234
# File 'lib/facebook_ads/ad_objects/server_side/util.rb', line 221

def self.normalize_zip(zip)

  # Remove spaces from the Postal code
  zip = zip.gsub(/[\s]/,'')

  # If the zip code '-', we retain just the first part alone.
  zip = zip.split('-')[0]

  if zip.length < 2
    return nil
  end

  return zip
end

.sha256Hash(input) ⇒ String



110
111
112
113
114
# File 'lib/facebook_ads/ad_objects/server_side/util.rb', line 110

def self.sha256Hash(input)
  unless input.nil?
    Digest::SHA256.hexdigest input
  end
end