From b8f6ae7cacace3e9b9b92673b34233a5d0d0ac20 Mon Sep 17 00:00:00 2001 From: Rafael Batista Date: Wed, 13 Mar 2024 09:12:51 -0700 Subject: [PATCH] Adding support to WhatsApp events on Business SDK Summary: CAPI CTWA has been launched to 100% since November 2023, but is still not supported in our Meta Business SDK. This diff adds support for WhatsApp events on the Business SDK. It includes changes to the Event class to add a new field for the messaging channel, as well as changes to the User Data class to include new constants for the CTWA_CLID and PAGE_ID parameters. Reviewed By: stcheng Differential Revision: D54851145 fbshipit-source-id: e896203602bac200ede2d0c2b14cfec164963685 --- .../ad_objects/server_side/action_source.rb | 3 ++ .../ad_objects/server_side/event.rb | 24 +++++++++- .../server_side/messaging_channel.rb | 27 ++++++++++++ .../ad_objects/server_side/user_data.rb | 44 +++++++++++++++++-- 4 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 lib/facebook_ads/ad_objects/server_side/messaging_channel.rb diff --git a/lib/facebook_ads/ad_objects/server_side/action_source.rb b/lib/facebook_ads/ad_objects/server_side/action_source.rb index 89f6af57..8f2e6552 100644 --- a/lib/facebook_ads/ad_objects/server_side/action_source.rb +++ b/lib/facebook_ads/ad_objects/server_side/action_source.rb @@ -41,6 +41,9 @@ module ServerSide # Conversion happened automatically, for example, a subscription renewal that's set on auto-pay each month. 'system_generated', + # Conversion happened through a business messaging channel, such as WhatsApp or Instagram Direct. + 'business_messaging', + # Conversion happened in a way that is not listed. 'other' ] diff --git a/lib/facebook_ads/ad_objects/server_side/event.rb b/lib/facebook_ads/ad_objects/server_side/event.rb index 5c3f3a4c..5e7e9305 100644 --- a/lib/facebook_ads/ad_objects/server_side/event.rb +++ b/lib/facebook_ads/ad_objects/server_side/event.rb @@ -75,6 +75,9 @@ class Event # Only used for the Advanced Measurement API in the Advanced Analytics product attr_accessor :advanced_measurement_table + # Messaging channel for the event + attr_accessor :messaging_channel + # @param [String] event_name # @param [int] event_time # @param [String] event_source_url @@ -88,6 +91,7 @@ class Event # @param [int] data_processing_options_state # @param String action_source # @param [String] advanced_measurement_table + # @param [String] messaging_channel def initialize(event_name: nil, event_time: nil, event_source_url: nil, @@ -100,7 +104,9 @@ def initialize(event_name: nil, data_processing_options_country: nil, data_processing_options_state: nil, action_source: nil, - advanced_measurement_table: nil) + advanced_measurement_table: nil, + messaging_channel: nil + ) unless event_name.nil? self.event_name = event_name @@ -141,6 +147,9 @@ def initialize(event_name: nil, unless advanced_measurement_table.nil? self.advanced_measurement_table = advanced_measurement_table end + unless messaging_channel.nil? + self.messaging_channel = messaging_channel + end end # build the object using the input hash @@ -202,6 +211,10 @@ def build(attributes = {}) if attributes.has_key?(:'advanced_measurement_table') self.advanced_measurement_table = attributes[:'advanced_measurement_table'] end + + if attributes.has_key?(:'messaging_channel') + self.messaging_channel = attributes[:'messaging_channel'] + end end # Show invalid properties with the reasons. Usually used together with valid? @@ -249,6 +262,7 @@ def ==(o) data_processing_options_state == o.data_processing_options_state && action_source == o.action_source && advanced_measurement_table == o.advanced_measurement_table + messaging_channel == o.messaging_channel end # @see the `==` method @@ -262,7 +276,7 @@ def hash [ event_name, event_time, event_source_url, opt_out, event_id, user_data, custom_data, app_data, data_processing_options, data_processing_options_country, data_processing_options_state, - action_source, advanced_measurement_table, + action_source, advanced_measurement_table, messaging_channel, ].hash end @@ -307,6 +321,9 @@ def to_s unless advanced_measurement_table.nil? hash['advanced_measurement_table'] = advanced_measurement_table end + unless messaging_channel.nil? + hash['messaging_channel'] = messaging_channel + end hash.to_s end @@ -356,6 +373,9 @@ def normalize unless advanced_measurement_table.nil? hash['advanced_measurement_table'] = advanced_measurement_table end + unless messaging_channel.nil? + hash['messaging_channel'] = messaging_channel + end hash end diff --git a/lib/facebook_ads/ad_objects/server_side/messaging_channel.rb b/lib/facebook_ads/ad_objects/server_side/messaging_channel.rb new file mode 100644 index 00000000..33242d7e --- /dev/null +++ b/lib/facebook_ads/ad_objects/server_side/messaging_channel.rb @@ -0,0 +1,27 @@ +# Copyright (c) 2017-present, Facebook, Inc. All rights reserved. +# +# You are hereby granted a non-exclusive, worldwide, royalty-free license to use, +# copy, modify, and distribute this software in source code or binary form for use +# in connection with the web services and APIs provided by Facebook. +# +# As with any software that integrates with the Facebook platform, your use of +# this software is subject to the Facebook Platform Policy +# [http://developers.facebook.com/policy/]. This copyright notice shall be +# included in all copies or substantial portions of the software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +module FacebookAds + module ServerSide + MessagingChannel = Set[ + + # Conversion happened on WhatsApp. + 'whatsapp', + ] + end +end diff --git a/lib/facebook_ads/ad_objects/server_side/user_data.rb b/lib/facebook_ads/ad_objects/server_side/user_data.rb index 44dff5b0..e3d1d063 100644 --- a/lib/facebook_ads/ad_objects/server_side/user_data.rb +++ b/lib/facebook_ads/ad_objects/server_side/user_data.rb @@ -236,6 +236,11 @@ def madid=(madid) @madids = [madid] end + # ctwaClid ID of a conversation that was started on WhatsApp + attr_accessor :ctwa_clid + + # pageId ID of the page that the ad is associated with + attr_accessor :page_id #UserData is a set of identifiers Facebook can use for targeted attribution # @param [String] email @@ -276,13 +281,16 @@ def madid=(madid) # @param [Array] anon_ids # @param [String] madid # @param [Array] madids + # @param [String] ctwa_clid + # @param [String] page_id def initialize(email: nil, emails: nil, phone: nil, phones: nil, gender: nil, genders: nil, date_of_birth: nil, dates_of_birth: nil, last_name: nil, last_names: nil, first_name: nil, first_names: nil, city: nil, cities: nil, state: nil, states: nil, country_code: nil, country_codes: nil, zip_code: nil, zip_codes: nil, external_id: nil, external_ids: nil, client_ip_address: nil, client_user_agent: nil, fbc: nil, fbp: nil, subscription_id: nil, lead_id: nil, - f5first: nil, f5last: nil, fi: nil, dobd: nil, dobm: nil, doby: nil, anon_id: nil, anon_ids: nil, madid:nil, madids: nil) + f5first: nil, f5last: nil, fi: nil, dobd: nil, dobm: nil, doby: nil, anon_id: nil, anon_ids: nil, madid:nil, madids: nil, + ctwa_clid: nil, page_id: nil) validate_constructor_values(emails, email, 'emails', 'email') validate_constructor_values(phones, phone, 'phones', 'phone') validate_constructor_values(genders, gender, 'genders', 'gender') @@ -409,6 +417,12 @@ def initialize(email: nil, emails: nil, phone: nil, phones: nil, gender: nil, ge unless madids.nil? self.madids = madids end + unless ctwa_clid.nil? + self.ctwa_clid = ctwa_clid + end + unless page_id.nil? + self.page_id = page_id + end end # build the object using the input hash @@ -540,6 +554,14 @@ def build(attributes = {}) elsif attributes.has_key?(:'madid') self.madids = [attributes[:'madid']] end + + if attributes.has_key?(:'ctwa_clid') + self.ctwa_clid = [attributes[:'ctwa_clid']] + end + + if attributes.has_key?(:'page_id') + self.page_id = [attributes[:'page_id']] + end end # Checks equality by comparing each attribute. @@ -570,7 +592,9 @@ def ==(o) dobm == o.dobm && doby == o.doby && anon_ids == o.anon_ids && - madids == o.madids + madids == o.madids && + ctwa_clid == ctwa_clid && + page_id == page_id end # @see the `==` method @@ -606,7 +630,9 @@ def hash dobm, doby, anon_ids, - madids + madids, + ctwa_clid, + page_id ].hash end @@ -690,6 +716,12 @@ def to_s unless madids.nil? hash['madids'] = madids end + unless ctwa_clid.nil? + hash['ctwa_clid'] = ctwa_clid + end + unless page_id.nil? + hash['page_id'] = page_id + end hash.to_s end @@ -772,6 +804,12 @@ def normalize unless madid.nil? hash['madid'] = madids end + unless ctwa_clid.nil? + hash['ctwa_clid'] = ctwa_clid + end + unless page_id.nil? + hash['page_id'] = page_id + end hash.select{|k, v| !v.nil?} end