From e688824d7fd585529ef03a1e6d2199c4acec8413 Mon Sep 17 00:00:00 2001 From: Henry Wang Date: Tue, 30 Jul 2024 12:50:24 -0700 Subject: [PATCH] add original_event_data and attribution_data to event payload Summary: Update business SDK to include original event data and attribution data for CAPI payload Differential Revision: D59702763 fbshipit-source-id: 3af042a81d333ed3858f297b1a0bab5adce48ddc --- .../Object/ServerSide/AttributionData.php | 305 ++++++++++++++++++ .../Object/ServerSide/AttributionModel.php | 56 ++++ src/FacebookAds/Object/ServerSide/Event.php | 46 +++ .../Object/ServerSide/OriginalEventData.php | 149 +++++++++ .../Object/ServerSide/AttributionDataTest.php | 65 ++++ .../Object/ServerSide/EventTest.php | 12 +- .../ServerSide/OriginalEventDataTest.php | 47 +++ 7 files changed, 678 insertions(+), 2 deletions(-) create mode 100644 src/FacebookAds/Object/ServerSide/AttributionData.php create mode 100644 src/FacebookAds/Object/ServerSide/AttributionModel.php create mode 100644 src/FacebookAds/Object/ServerSide/OriginalEventData.php create mode 100644 test/FacebookAdsTest/Object/ServerSide/AttributionDataTest.php create mode 100644 test/FacebookAdsTest/Object/ServerSide/OriginalEventDataTest.php diff --git a/src/FacebookAds/Object/ServerSide/AttributionData.php b/src/FacebookAds/Object/ServerSide/AttributionData.php new file mode 100644 index 000000000..0593c8ecf --- /dev/null +++ b/src/FacebookAds/Object/ServerSide/AttributionData.php @@ -0,0 +1,305 @@ + 'string', + 'visit_time' => 'int', + 'ad_id' => 'string', + 'adset_id' => 'string', + 'campaign_id' => 'string', + 'attribution_share' => 'float', + 'attribution_model' => 'FacebookAds\Object\ServerSide\AttributionModel', + 'attr_window' => 'int', + ); + + protected static $attributeMap = array( + 'scope' => 'scope', + 'visit_time' => 'visit_time', + 'ad_id' => 'ad_id', + 'adset_id' => 'adset_id', + 'campaign_id' => 'campaign_id', + 'attribution_share' => 'attribution_share', + 'attribution_model' => 'attribution_model', + 'attr_window' => 'attr_window', + ); + + protected static $setters = array( + 'scope' => 'setScope', + 'visit_time' => 'setVisitTime', + 'ad_id' => 'setAdId', + 'adset_id' => 'setAdsetId', + 'campaign_id' => 'setCampaignId', + 'attribution_share' => 'setAttributionShare', + 'attribution_model' => 'setAttributionModel', + 'attr_window' => 'setAttrWindow', + ); + + protected static $getters = array( + 'scope' => 'getScope', + 'visit_time' => 'getVisitTime', + 'ad_id' => 'getAdId', + 'adset_id' => 'getAdsetId', + 'campaign_id' => 'getCampaignId', + 'attribution_share' => 'getAttributionShare', + 'attribution_model' => 'getAttributionModel', + 'attr_window' => 'getAttrWindow', + ); + + protected $container = array(); + + public function __construct(array $data = null) { + $this->container['scope'] = isset($data['scope']) ? $data['scope'] : null; + $this->container['visit_time'] = isset($data['visit_time']) ? $data['visit_time'] : null; + $this->container['ad_id'] = isset($data['ad_id']) ? $data['ad_id'] : null; + $this->container['adset_id'] = isset($data['adset_id']) ? $data['adset_id'] : null; + $this->container['campaign_id'] = isset($data['campaign_id']) ? $data['campaign_id'] : null; + $this->container['attribution_share'] = isset($data['attribution_share']) ? $data['attribution_share'] : null; + $this->container['attribution_model'] = isset($data['attribution_model']) ? $data['attribution_model'] : null; + $this->container['attr_window'] = isset($data['attr_window']) ? $data['attr_window'] : null; + } + + public static function paramTypes() { + return self::$param_types; + } + + public static function attributeMap() { + return self::$attributeMap; + } + + public static function setters() { + return self::$setters; + } + + public static function getters() { + return self::$getters; + } + + public function listInvalidProperties() { + $invalid_properties = array(); + return $invalid_properties; + } + + public function valid() { + return true; + } + + /** + * Sets scope + * @param string $scope Touchpoint type. + * @return $this + */ + public function setScope($scope) { + $this->container['scope'] = $scope; + + return $this; + } + + /** + * Sets visit_time + * @param int $visit_time A Unix timestamp in seconds indicating time that the campaign_id or fbc was first received. + * @return $this + */ + public function setEventTime($visit_time) { + $this->container['visit_time'] = $visit_time; + + return $this; + } + + /** + * Sets ad_id + * @param string $ad_id Meta-provided ad id from URL/deeplink. + * @return $this + */ + public function setAdId($ad_id) { + $this->container['ad_id'] = $ad_id; + + return $this; + } + + /** + * Sets adset_id + * @param string $adset_id Meta-provided adset id from URL/deeplink. + * @return $this + */ + public function setAdsetId($adset_id) { + $this->container['adset_id'] = $adset_id; + + return $this; + } + + /** + * Sets campaign_id + * @param string $campaign_id Meta-provided campaign id from URL/deeplink. + * @return $this + */ + public function setCampaignId($campaign_id) { + $this->container['campaign_id'] = $campaign_id; + + return $this; + } + + /** + * Sets attribution_share + * @param float $attribution_share [0-1] weight of credit assigned to the visit. + * @return $this + */ + public function setAttributionShare($attribution_share) { + $this->container['attribution_share'] = $attribution_share; + + return $this; + } + + /** + * Sets attribution_model + * @param string $attribution_model Attribution model used to attribute the event. + * @return $this + */ + public function setAttributionModel($attribution_model) { + $this->container['attribution_model'] = $attribution_model; + + return $this; + } + + /** + * Sets attr_window + * @param string $attr_window Attribution window in days. + * @return $this + */ + public function setAttrWindow($attr_window) { + $this->container['attr_window'] = $attr_window; + + return $this; + } + + /** + * Gets touchpoint type. + * @return string + */ + public function getScope() { + return $this->container['scope']; + } + + /** + * Gets the Unix timestamp in seconds indicating time that the campaign_id or fbc was first received. + * @return int + */ + public function getVisitTime() { + return $this->container['visit_time']; + } + + /** + * Gets Meta-provided ad id from URL/deeplink. + * @return string + */ + public function getAdId() { + return $this->container['ad_id']; + } + + /** + * Gets Meta-provided adset id from URL/deeplink. + * @return string + */ + public function getAdsetId() { + return $this->container['adset_id']; + } + + /** + * Gets Meta-provided campaign id from URL/deeplink. + * @return string + */ + public function getCampaignId() { + return $this->container['campaign_id']; + } + + /** + * Gets attribution share. + * @return float + */ + public function getAttributionShare() { + return $this->container['attribution_share']; + } + + /** + * Gets attribution model used to attribute the event. + * @return string + */ + public function getAttributionModel() { + return $this->container['attribution_model']; + } + + /** + * Gets attribution window in days. + * @return string + */ + public function getAttrWindow() { + return $this->container['attr_window']; + } + + public function normalize() { + $normalized_payload = array(); + + $normalized_payload['scope'] = $this->getScope(); + $normalized_payload['visit_time'] = $this->getVisitTime(); + $normalized_payload['ad_id'] = $this->getAdId(); + $normalized_payload['adset_id'] = $this->getAdsetId(); + $normalized_payload['campaign_id'] = $this->getCampaignId(); + $normalized_payload['attribution_share'] = $this->getAttributionShare(); + $normalized_payload['attribution_model'] = $this->getAttributionModel(); + $normalized_payload['attr_window'] = $this->getAttrWindow(); + return $normalized_payload; + } + + /** + * Gets the string presentation of the object + * @return string + */ + public function __toString() { + if (defined('JSON_PRETTY_PRINT')) { // use JSON pretty print + return json_encode($this, JSON_PRETTY_PRINT); + } + + return json_encode($this); + } +} diff --git a/src/FacebookAds/Object/ServerSide/AttributionModel.php b/src/FacebookAds/Object/ServerSide/AttributionModel.php new file mode 100644 index 000000000..ef1ed3d57 --- /dev/null +++ b/src/FacebookAds/Object/ServerSide/AttributionModel.php @@ -0,0 +1,56 @@ + 'string', + 'FIRST_TOUCH' => 'string', + 'LAST_CLICK' => 'string', + 'LAST_TOUCH' => 'string', + 'LINEAR' => 'string', + 'POSITION_BASED' => 'string', + 'TIME_DECAY' => 'string', + 'UNKNOWN' => 'string', + ); + } +} diff --git a/src/FacebookAds/Object/ServerSide/Event.php b/src/FacebookAds/Object/ServerSide/Event.php index 4e1ad7a47..2aa5af26c 100644 --- a/src/FacebookAds/Object/ServerSide/Event.php +++ b/src/FacebookAds/Object/ServerSide/Event.php @@ -52,6 +52,8 @@ class Event implements ArrayAccess { 'app_data' => 'FacebookAds\Object\ServerSide\AppData', 'advanced_measurement_table' => 'string', 'messaging_channel' => 'string', + 'original_event_data' => 'FacebookAds\Object\ServerSide\OriginalEventData', + 'attribution_data' => 'FacebookAds\Object\ServerSide\AttributionData', ); /** * Array of attributes where the key is the local name, and the value is the original name @@ -72,6 +74,8 @@ class Event implements ArrayAccess { 'app_data' => 'app_data', 'advanced_measurement_table' => 'advanced_measurement_table', 'messaging_channel' => 'messaging_channel', + 'original_event_data' => 'original_event_data', + 'attribution_data' => 'attribution_data', ); /** @@ -93,6 +97,8 @@ class Event implements ArrayAccess { 'app_data' => 'setAppData', 'advanced_measurement_table' => 'setAdvancedMeasurementTable', 'messaging_channel' => 'setMessagingChannel', + 'original_event_data' => 'setOriginalEventData', + 'attribution_data' => 'setAttributionData', ); /** * Array of attributes to getter functions (for serialization of requests) @@ -113,6 +119,8 @@ class Event implements ArrayAccess { 'app_data' => 'getAppData', 'advanced_measurement_table' => 'getAdvancedMeasurementTable', 'messaging_channel' => 'getMessagingChannel', + 'original_event_data' => 'getOriginalEventData', + 'attribution_data' => 'getAttributionData', ); /** * Associative array for storing property values @@ -139,6 +147,8 @@ public function __construct(array $data = null) { $this->container['app_data'] = isset($data['app_data']) ? $data['app_data'] : null; $this->container['advanced_measurement_table'] = isset($data['advanced_measurement_table']) ? $data['advanced_measurement_table'] : null; $this->container['messaging_channel'] = isset($data['messaging_channel']) ? $data['messaging_channel'] : null; + $this->container['original_event_data'] = isset($data['original_event_data']) ? $data['original_event_data'] : null; + $this->container['attribution_data'] = isset($data['attribution_data']) ? $data['attribution_data'] : null; } public static function paramTypes() { @@ -414,6 +424,8 @@ public function normalize() { $normalized_payload['opt_out'] = $this->getOptOut(); } $normalized_payload['app_data'] = isset($this->container['app_data']) ? $this->getAppData()->normalize() : null; + $normalized_payload['original_event_data'] = isset($this->container['original_event_data']) ? $this->getOriginalEventData()->normalize() : null; + $normalized_payload['attribution_data'] = isset($this->container['attribution_data']) ? $this->getAttributionData()->normalize() : null; return $normalized_payload; } @@ -541,6 +553,40 @@ public function getMessagingChannel() { return $this->container['messaging_channel']; } + /** + * Sets the original event data of the event. + * @return $this + */ + public function setOriginalEventData($original_event_data) { + $this->container['original_event_data'] = $original_event_data; + return $this; + } + + /** + * Return the original event data of the event. + * @return OriginalEventData + */ + public function getOriginalEventData() { + return $this->container['original_event_data']; + } + + /** + * Sets the attribution data of the event. + * @return $this + */ + public function setAttributionData($attribute_data) { + $this->container['attribute_data'] = $attribute_data; + return $this; + } + + /** + * Return the attribution data of the event. + * @return AttributionData + */ + public function getAttributionData() { + return $this->container['attribution_data']; + } + /** * Gets the string representation of the object * @return string diff --git a/src/FacebookAds/Object/ServerSide/OriginalEventData.php b/src/FacebookAds/Object/ServerSide/OriginalEventData.php new file mode 100644 index 000000000..f27c3c100 --- /dev/null +++ b/src/FacebookAds/Object/ServerSide/OriginalEventData.php @@ -0,0 +1,149 @@ + 'string', + 'event_time' => 'int', + ); + + protected static $attributeMap = array( + 'event_name' => 'event_name', + 'event_time' => 'event_time', + ); + + protected static $setters = array( + 'event_name' => 'setEventName', + 'event_time' => 'setEventTime', + ); + + protected static $getters = array( + 'event_name' => 'getEventName', + 'event_time' => 'getEventTime', + ); + + protected $container = array(); + + public function __construct(array $data = null) { + $this->container['event_name'] = isset($data['event_name']) ? $data['event_name'] : null; + $this->container['event_time'] = isset($data['event_time']) ? $data['event_time'] : null; + } + + public static function paramTypes() { + return self::$param_types; + } + + public static function attributeMap() { + return self::$attributeMap; + } + + public static function setters() { + return self::$setters; + } + + public static function getters() { + return self::$getters; + } + + public function listInvalidProperties() { + $invalid_properties = array(); + return $invalid_properties; + } + + public function valid() { + return true; + } + + /** + * Sets a Meta pixel Standard Event or Custom Event name + * @param string $event_name A Meta pixel Standard Event or Custom Event name. + * @return $this + */ + public function setEventName($event_name) { + $this->container['event_name'] = $event_name; + + return $this; + } + + /** + * Sets a Unix timestamp in seconds indicating when the original event occurred + * @param int $event_time A Unix timestamp in seconds indicating when the original event occurred. + * @return $this + */ + public function setEventTime($event_time) { + $this->container['event_time'] = $event_time; + + return $this; + } + + /** + * Gets Meta pixel Standard Event or Custom Event name. + * @return string + */ + public function getEventName() { + return $this->container['event_name']; + } + + /** + * Gets Unix timestamp in seconds indicating when the original event occurred. + * @return int + */ + public function getEventTime() { + return $this->container['event_time']; + } + + public function normalize() { + $normalized_payload = array(); + + $normalized_payload['event_name'] = $this->getEventName(); + $normalized_payload['event_time'] = $this->getEventTime(); + return $normalized_payload; + } + + /** + * Gets the string presentation of the object + * @return string + */ + public function __toString() { + if (defined('JSON_PRETTY_PRINT')) { // use JSON pretty print + return json_encode($this, JSON_PRETTY_PRINT); + } + + return json_encode($this); + } +} diff --git a/test/FacebookAdsTest/Object/ServerSide/AttributionDataTest.php b/test/FacebookAdsTest/Object/ServerSide/AttributionDataTest.php new file mode 100644 index 000000000..0b0129edd --- /dev/null +++ b/test/FacebookAdsTest/Object/ServerSide/AttributionDataTest.php @@ -0,0 +1,65 @@ + 'click', + 'visit_time' => 123456, + 'ad_id' => '123', + 'adset_id' => '234', + 'campaign_id' => '345', + 'attr_window' => 7, + 'attribution_share' => 0.5, + 'attribution_model' => 'last_touch' + ); + $builder = (new AttributionData()) + ->setScope($expected['scope']) + ->setVisitTime($expected['visit_time']) + ->setAdId($expected['ad_id']) + ->setAdsetId($expected['adset_id']) + ->setCampaignId($expected['campaign_id']) + ->setAttrWindow($expected['attr_window']) + ->setAttributionShare($expected['attribution_share']) + ->setAttributionModel($expected['attribution_model']); + $this->assertEquals($expected, $builder->normalize()); + + $constructor = new AttributionData(array( + 'scope' => $expected['scope'], + 'visit_time' => $expected['visit_time'], + 'ad_id' => $expected['ad_id'], + 'adset_id' => $expected['adset_id'], + 'campaign_id' => $expected['campaign_id'], + 'attr_window' => $expected['attr_window'], + 'attribution_share' => $expected['attribution_share'], + 'attribution_model' => $expected['attribution_model'] + )); + $this->assertEquals($expected, $constructor->normalize()); + } +} diff --git a/test/FacebookAdsTest/Object/ServerSide/EventTest.php b/test/FacebookAdsTest/Object/ServerSide/EventTest.php index afeac66e7..9bd4c7f5e 100644 --- a/test/FacebookAdsTest/Object/ServerSide/EventTest.php +++ b/test/FacebookAdsTest/Object/ServerSide/EventTest.php @@ -26,14 +26,18 @@ use FacebookAdsTest\AbstractUnitTestCase; use FacebookAds\Object\ServerSide\ActionSource; +use FacebookAds\Object\ServerSide\AttributionData; use FacebookAds\Object\ServerSide\CustomData; use FacebookAds\Object\ServerSide\Event; +use FacebookAds\Object\ServerSide\OriginalEventData; use FacebookAds\Object\ServerSide\UserData; class EventTest extends AbstractUnitTestCase { public function testBuilder() { $user_data = new UserData(array('email' => 'eg@test.com')); $custom_data = new CustomData(array('order_id' => '123')); + $original_event_data = new OriginalEventData(array('event_name' => 'event-name-1')); + $attribution_data = new AttributionData(array('scope' => 'click')); $expected = array( 'event_name' => 'event_name-0', 'event_time' => 1234, @@ -46,6 +50,8 @@ public function testBuilder() { 'data_processing_options_country' => 1, 'data_processing_options_state' => 2, 'action_source' => ActionSource::WEBSITE, + 'original_event_data' => $original_event_data->normalize(), + 'attribution_data' => $attribution_data->normalize(), ); $event = (new Event()) @@ -59,7 +65,9 @@ public function testBuilder() { ->setDataProcessingOptions($expected['data_processing_options']) ->setDataProcessingOptionsCountry($expected['data_processing_options_country']) ->setDataProcessingOptionsState($expected['data_processing_options_state']) - ->setActionSource($expected['action_source']); + ->setActionSource($expected['action_source']) + ->setOriginalEventData($original_event_data) + ->setAttributionData($attribution_data); $this->assertEquals($expected, $event->normalize()); } @@ -75,7 +83,7 @@ public function testInvalidActionSource() { $event = (new Event())->setActionSource($action_source); try { - $normalized_payload = $event->normalize(); + $normalized_payload = $event->normalize(); } catch (\Exception $exception) { $has_thrown_exception = true; $expected_string = sprintf("Invalid action_source passed: %s",$action_source); diff --git a/test/FacebookAdsTest/Object/ServerSide/OriginalEventDataTest.php b/test/FacebookAdsTest/Object/ServerSide/OriginalEventDataTest.php new file mode 100644 index 000000000..84a60bab7 --- /dev/null +++ b/test/FacebookAdsTest/Object/ServerSide/OriginalEventDataTest.php @@ -0,0 +1,47 @@ + 'event-name-1', + 'event_time' => 123456 + ); + $builder = (new OriginalEventData()) + ->setEventName($expected['event_name']) + ->setCurrency($expected['event_time']); + $this->assertEquals($expected, $builder->normalize()); + + $constructor = new OriginalEventData(array( + 'event_name' => $expected['event_name'], + 'event_time' => $expected['event_time'] + )); + $this->assertEquals($expected, $constructor->normalize()); + } +}