core/ServerEventFactory.php (261 lines of code) (raw):
<?php
/*
* Copyright (C) 2017-present, Meta, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
/**
* @package FacebookPixelPlugin
*/
namespace FacebookPixelPlugin\Core;
use FacebookAds\Object\ServerSide\Event;
use FacebookAds\Object\ServerSide\UserData;
use FacebookAds\Object\ServerSide\CustomData;
use FacebookAds\Object\ServerSide\Normalizer;
use FacebookPixelPlugin\Core\AAMFieldsExtractor;
use FacebookPixelPlugin\Core\AAMSettingsFields;
use FacebookPixelPlugin\Core\EventIdGenerator;
use FacebookPixelPlugin\Core\FacebookWordpressOptions;
defined('ABSPATH') or die('Direct access not allowed');
class ServerEventFactory {
public static function newEvent(
$event_name,
$prefer_referrer_for_event_src = false)
{
$user_data = (new UserData())
->setClientIpAddress(self::getIpAddress())
->setClientUserAgent(self::getHttpUserAgent())
->setFbp(self::getFbp())
->setFbc(self::getFbc());
$event = (new Event())
->setEventName($event_name)
->setEventTime(time())
->setEventId(EventIdGenerator::guidv4())
->setEventSourceUrl(
self::getRequestUri($prefer_referrer_for_event_src))
->setActionSource('website')
->setUserData($user_data)
->setCustomData(new CustomData());
return $event;
}
private static function getIpAddress() {
$HEADERS_TO_SCAN = array(
'HTTP_CLIENT_IP',
'HTTP_X_FORWARDED_FOR',
'HTTP_X_FORWARDED',
'HTTP_X_CLUSTER_CLIENT_IP',
'HTTP_FORWARDED_FOR',
'HTTP_FORWARDED',
'REMOTE_ADDR'
);
foreach ($HEADERS_TO_SCAN as $header) {
if (array_key_exists($header, $_SERVER)) {
$ip_list = explode(',', $_SERVER[$header]);
foreach($ip_list as $ip) {
$trimmed_ip = trim($ip);
if (self::isValidIpAddress($trimmed_ip)) {
return $trimmed_ip;
}
}
}
}
return null;
}
private static function getHttpUserAgent() {
$user_agent = null;
if (!empty($_SERVER['HTTP_USER_AGENT'])) {
$user_agent = $_SERVER['HTTP_USER_AGENT'];
}
return $user_agent;
}
private static function getRequestUri($prefer_referrer_for_event_src) {
if ($prefer_referrer_for_event_src && !empty($_SERVER['HTTP_REFERER'])) {
return $_SERVER['HTTP_REFERER'];
}
$url = "http://";
if(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') {
$url = "https://";
}
if (!empty($_SERVER['HTTP_HOST'])) {
$url .= $_SERVER['HTTP_HOST'];
}
if (!empty($_SERVER['REQUEST_URI'])) {
$url .= $_SERVER['REQUEST_URI'];
}
return $url;
}
private static function getFbp() {
$fbp = null;
if (!empty($_COOKIE['_fbp'])) {
$fbp = $_COOKIE['_fbp'];
}
return $fbp;
}
private static function getFbc() {
$fbc = null;
if (!empty($_COOKIE['_fbc'])) {
$fbc = $_COOKIE['_fbc'];
}
return $fbc;
}
private static function isValidIpAddress($ip_address) {
return filter_var($ip_address,
FILTER_VALIDATE_IP,
FILTER_FLAG_IPV4
| FILTER_FLAG_IPV6
| FILTER_FLAG_NO_PRIV_RANGE
| FILTER_FLAG_NO_RES_RANGE);
}
/*
Given that the data extracted by the integration classes is a mix of
user data and custom data,
this function splits these fields in two arrays
and user data is formatted with the AAM field setting
*/
private static function splitUserDataAndCustomData($data){
$user_data = array();
$custom_data = array();
$key_to_aam_field = array(
'email' => AAMSettingsFields::EMAIL,
'first_name' => AAMSettingsFields::FIRST_NAME,
'last_name' => AAMSettingsFields::LAST_NAME,
'phone' => AAMSettingsFields::PHONE,
'state' => AAMSettingsFields::STATE,
'country' => AAMSettingsFields::COUNTRY,
'city' => AAMSettingsFields::CITY,
'zip' => AAMSettingsFields::ZIP_CODE,
'gender' => AAMSettingsFields::GENDER,
'date_of_birth' => AAMSettingsFields::DATE_OF_BIRTH,
);
foreach( $data as $key => $value ){
if( array_key_exists( $key, $key_to_aam_field ) ){
$user_data[$key_to_aam_field[$key]] = $value;
}
else{
$custom_data[$key] = $value;
}
}
return array(
'user_data' => $user_data,
'custom_data' => $custom_data
);
}
public static function safeCreateEvent(
$event_name,
$callback,
$arguments,
$integration,
$prefer_referrer_for_event_src = false)
{
$event = self::newEvent($event_name, $prefer_referrer_for_event_src);
try {
$data = call_user_func_array($callback, $arguments);
$data_split = self::splitUserDataAndCustomData($data);
$user_data_array = $data_split['user_data'];
$custom_data_array = $data_split['custom_data'];
$user_data_array =
AAMFieldsExtractor::getNormalizedUserData($user_data_array);
$user_data = $event->getUserData();
if(
array_key_exists(AAMSettingsFields::EMAIL, $user_data_array)
){
$user_data->setEmail(
$user_data_array[AAMSettingsFields::EMAIL]
);
}
if(
array_key_exists(AAMSettingsFields::FIRST_NAME, $user_data_array)
){
$user_data->setFirstName(
$user_data_array[AAMSettingsFields::FIRST_NAME]
);
}
if(
array_key_exists(AAMSettingsFields::LAST_NAME, $user_data_array)
){
$user_data->setLastName(
$user_data_array[AAMSettingsFields::LAST_NAME]
);
}
if(
array_key_exists(AAMSettingsFields::GENDER, $user_data_array)
){
$user_data->setGender(
$user_data_array[AAMSettingsFields::GENDER]
);
}
if(
array_key_exists(AAMSettingsFields::DATE_OF_BIRTH, $user_data_array)
){
$user_data->setDateOfBirth(
$user_data_array[AAMSettingsFields::DATE_OF_BIRTH]);
}
if(
array_key_exists(AAMSettingsFields::EXTERNAL_ID, $user_data_array)
){
$user_data->setExternalId(
Util::hash($user_data_array[AAMSettingsFields::EXTERNAL_ID])
);
}
if(
array_key_exists(AAMSettingsFields::PHONE, $user_data_array)
){
$user_data->setPhone(
$user_data_array[AAMSettingsFields::PHONE]
);
}
if(
array_key_exists(AAMSettingsFields::CITY, $user_data_array)
){
$user_data->setCity(
$user_data_array[AAMSettingsFields::CITY]
);
}
if(
array_key_exists(AAMSettingsFields::STATE, $user_data_array)
){
$user_data->setState(
$user_data_array[AAMSettingsFields::STATE]
);
}
if(
array_key_exists(AAMSettingsFields::ZIP_CODE, $user_data_array)
){
$user_data->setZipCode(
$user_data_array[AAMSettingsFields::ZIP_CODE]
);
}
if(
array_key_exists(AAMSettingsFields::COUNTRY, $user_data_array)
){
$user_data->setCountryCode(
$user_data_array[AAMSettingsFields::COUNTRY]
);
}
$custom_data = $event->getCustomData();
$custom_data->addCustomProperty('fb_integration_tracking', $integration);
if (!empty($data['currency'])) {
$custom_data->setCurrency($custom_data_array['currency']);
}
if (!empty($data['value'])) {
$custom_data->setValue($custom_data_array['value']);
}
if (!empty($data['contents'])) {
$custom_data->setContents($custom_data_array['contents']);
}
if (!empty($data['content_ids'])) {
$custom_data->setContentIds($custom_data_array['content_ids']);
}
if (!empty($data['content_type'])) {
$custom_data->setContentType($custom_data_array['content_type']);
}
if (!empty($data['num_items'])) {
$custom_data->setNumItems($custom_data_array['num_items']);
}
if (!empty($data['content_name'])) {
$custom_data->setContentName($custom_data_array['content_name']);
}
if (!empty($data['content_category'])){
$custom_data->setContentCategory($custom_data_array['content_category']);
}
} catch (\Exception $e) {
// Need to log
}
return $event;
}
public static function splitName($name) {
$first_name = $name;
$last_name = null;
$index = strpos($name, ' ');
if ($index !== false) {
$first_name = substr($name, 0, $index);
$last_name = substr($name, $index + 1);
}
return array($first_name, $last_name);
}
}