facebook_tracking_pixel.module in Facebook Tracking Pixel 7
Same filename and directory in other branches
facebook_tracking_pixel.module Facebook Tracking Module.
@author Brady Owens <info@fastglass.net>
File
facebook_tracking_pixel.moduleView source
<?php
/**
* @file facebook_tracking_pixel.module
* Facebook Tracking Module.
*
* @author Brady Owens <info@fastglass.net>
*/
/**
* Implements hook_menu().
*/
function facebook_tracking_pixel_menu() {
$items = [];
$items['admin/config/system/facebook_tracking_pixel'] = [
'title' => 'Administer Facebook Tracking Pixel',
'description' => 'Facebook Tracking pixel module.',
'page callback' => 'drupal_get_form',
'page arguments' => [
'facebook_tracking_pixel_settings_form',
],
'access arguments' => [
'administer facebook tracking pixels',
],
'file' => 'facebook_tracking_pixel.admin.inc',
'type' => MENU_NORMAL_ITEM,
];
$items['admin/config/system/facebook_tracking_pixel/default'] = [
'title' => 'Administer Facebook Tracking Pixel',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => 0,
];
$items['admin/config/system/facebook_tracking_pixel/base_codes'] = [
'title' => 'Base Tracking Codes',
'page arguments' => [
'facebook_tracking_pixel_base_codes_form',
],
'access arguments' => [
'administer facebook tracking pixels',
],
'file' => 'facebook_tracking_pixel.admin.inc',
'type' => MENU_LOCAL_TASK,
];
$items['admin/config/system/facebook_tracking_pixel/user_registration'] = [
'title' => 'Track User Registration',
'page callback' => 'drupal_get_form',
'page arguments' => [
'facebook_tracking_pixel_user_registration',
],
'access arguments' => [
'administer facebook tracking pixels',
],
'file' => 'facebook_tracking_pixel.admin.inc',
'type' => MENU_LOCAL_TASK,
];
$items['admin/config/system/facebook_tracking_pixel/base_codes/delete/%'] = [
'title' => 'Delete a Base Code',
'page callback' => 'drupal_get_form',
'page arguments' => [
'facebook_tracking_pixel_base_codes_delete_form',
6,
],
'access arguments' => [
'administer facebook tracking pixels',
],
'file' => 'facebook_tracking_pixel.admin.inc',
'type' => MENU_CALLBACK,
];
$items['admin/config/system/facebook_tracking_pixel/base_codes/edit/%'] = [
'title' => 'Edit a Base Code',
'page callback' => 'drupal_get_form',
'access arguments' => [
'administer facebook tracking pixels',
],
'file' => 'facebook_tracking_pixel.admin.inc',
'page arguments' => [
'facebook_tracking_pixel_base_codes_edit_form',
6,
],
'type' => MENU_CALLBACK,
];
$items['admin/config/system/facebook_tracking_pixel/purge'] = [
'title' => 'Purge',
'page callback' => 'drupal_get_form',
'page arguments' => [
'facebook_tracking_pixel_form_purge',
],
'access arguments' => [
'administer facebook tracking pixels',
],
'file' => 'facebook_tracking_pixel.admin.inc',
'type' => MENU_LOCAL_TASK,
'weight' => 50,
];
$items['admin/config/system/facebook_tracking_pixel/path'] = [
'title' => 'Track Events by Path',
'page callback' => 'drupal_get_form',
'page arguments' => [
'facebook_tracking_pixel_track_by_path_form',
],
'access arguments' => [
'administer facebook tracking pixels',
],
'file' => 'facebook_tracking_pixel.admin.path.inc',
'type' => MENU_LOCAL_TASK,
];
$items['admin/config/system/facebook_tracking_pixel/path/add'] = [
'title' => 'Add tracking based on path',
'page callback' => 'drupal_get_form',
'page arguments' => [
'facebook_tracking_pixel_path_add_form',
],
'access arguments' => [
'administer facebook tracking pixels',
],
'file' => 'facebook_tracking_pixel.admin.path.inc',
'type' => MENU_LOCAL_ACTION,
];
$items['admin/config/system/facebook_tracking_pixel/path/delete/%'] = [
'title' => 'Deleting an event',
'page callback' => 'drupal_get_form',
'page arguments' => [
'facebook_tracking_pixel_path_delete_form',
6,
],
'access arguments' => [
'administer facebook tracking pixels',
],
'file' => 'facebook_tracking_pixel.admin.path.inc',
'type' => MENU_CALLBACK,
];
$items['admin/config/system/facebook_tracking_pixel/path/edit/%'] = [
'title' => 'Update details of an event',
'page callback' => 'drupal_get_form',
'page arguments' => [
'facebook_tracking_pixel_path_edit_form',
6,
],
'access arguments' => [
'administer facebook tracking pixels',
],
'file' => 'facebook_tracking_pixel.admin.path.inc',
'type' => MENU_CALLBACK,
];
$items['admin/config/system/facebook_tracking_pixel/commercetracking'] = [
'title' => 'Commerce Tracking',
'page callback' => 'drupal_get_form',
'page arguments' => [
'facebook_tracking_pixel_commerce_form',
],
'access arguments' => [
'administer facebook tracking pixels',
],
'file' => 'facebook_tracking_pixel.admin.commerce.inc',
'type' => MENU_LOCAL_TASK,
];
$items['admin/config/system/facebook_tracking_pixel/enhanced'] = [
'title' => 'Enhanced Tracking',
'page callback' => 'drupal_get_form',
'page arguments' => [
'facebook_tracking_pixel_form_enhanced',
],
'access arguments' => [
'administer facebook tracking pixels',
],
'file' => 'facebook_tracking_pixel.admin.inc',
'type' => MENU_LOCAL_TASK,
'weight' => 35,
];
return $items;
}
/**
* Implements hook_permission().
*/
function facebook_tracking_pixel_permission() {
$permissions['administer facebook tracking pixels']['title'] = t('Administer Facebook Tracking Pixels.');
return $permissions;
}
/**
* Implements hook_page_build().
*/
function facebook_tracking_pixel_page_build(&$page) {
// Assertain which role should see the tracking information.
global $user;
// Default to no tracking.
$trackable = 0;
// Determin if the user is trackable based on roles assigned.
$trackable += _facebook_tracking_pixel_roles($user);
// Only process tracking codes if the user is trackable.
if ($trackable > 0) {
// Pull base code IDs from database and build the noscript header includes.
$basecodes = db_select('facebook_tracking_pixel_base_codes', 'c')
->fields('c')
->orderBy('weight')
->execute()
->fetchAllAssoc('base_code_id');
// Facebook static code.
$fb_noscript_src = facebook_tracking_pixel_base_code_nojs();
// Facebook JS code.
$fb_script_src = facebook_tracking_pixel_base_code_js();
// Script path.
$path = variable_get('facebook_tracking_pixel_path', 'public://facebook_tracking_pixel');
// Process anything that could be stored in the session.
if (!empty($_SESSION['facebook_tracking_pixel'])) {
// We use this foreach to step through the session variables for special
// case codes.
foreach ($_SESSION['facebook_tracking_pixel'] as $key => $value) {
switch ($key) {
case 'registration':
$userregfile = $path . '/registrationtracking/fb_trk_user_registration.js';
$page['content']['#attached']['js']['facebook_tracking_pixel_path_user_registration'] = [
'type' => 'file',
'group' => JS_THEME,
'data' => $userregfile,
'preprocess' => (bool) variable_get('facebook_tracking_pixel_aggregation', FALSE),
];
// Assemble code and pull the FBID from the session variable.
$fb_base_code_nojs = $fb_noscript_src[0] . $_SESSION['facebook_tracking_pixel']['registration_fbid'] . $fb_noscript_src[1];
drupal_add_html_head([
'#type' => 'markup',
'#markup' => $fb_base_code_nojs,
'#weight' => 150,
], 'facebook_tracking_pixel_path_user_registration');
// We remove the session variables, we do not want it loading but once.
unset($_SESSION['facebook_tracking_pixel']['registration']);
unset($_SESSION['facebook_tracking_pixel']['registration_fbid']);
// If this is a user registration event we stop processing.
return;
break;
case 'ftpdcaddtocart':
$ftpdcbasecodeid = variable_get('facebook_tracking_pixel_commerce_tracking_basecode');
$ftpdcfbid = db_select('facebook_tracking_pixel_base_codes', 'c')
->fields('c', [
'base_code_fbid',
])
->condition('base_code_id', $ftpdcbasecodeid, '=')
->execute()
->fetchField();
// Prepare an array of arguments to do text replacements.
$argreplace = [
'@cur' => $value['currency_code'],
'@id' => $value['content_id'],
'@quantity' => $value['quantity'],
'@val' => $value['value'],
];
// This event will require the JS to be inline in the page.
$reservedevents = facebook_tracking_pixel_events_reserved();
$ftpdcpurcode = format_string($reservedevents['ftpdcaddtocart']['code'], $argreplace);
$inlinejs = $fb_script_src[0] . $ftpdcfbid . $fb_script_src[1] . $ftpdcpurcode;
// JS to load into page header.
$page['content']['#attached']['js']['facebook_tracking_pixel_path_drupal_commerce_addtocart'] = [
'type' => 'inline',
'group' => JS_THEME,
'data' => $inlinejs,
'preprocess' => (bool) variable_get('facebook_tracking_pixel_aggregation', FALSE),
];
// Noscript for header.
$fb_base_code_nojs = $fb_noscript_src[0] . $ftpdcfbid . $fb_noscript_src[1];
drupal_add_html_head([
'#type' => 'markup',
'#markup' => $fb_base_code_nojs,
'#weight' => 150,
], 'facebook_tracking_pixel_path_drupal_commerce_addtocart');
// Delete session variable.
unset($_SESSION['facebook_tracking_pixel']['ftpdcaddtocart']);
break;
case 'ftpdcinitiatecheckout':
$ftpdcbasecodeid = variable_get('facebook_tracking_pixel_commerce_tracking_basecode');
$ftpdcfbid = db_select('facebook_tracking_pixel_base_codes', 'c')
->fields('c', [
'base_code_fbid',
])
->condition('base_code_id', $ftpdcbasecodeid, '=')
->execute()
->fetchField();
$subdir = variable_get('facebook_tracking_pixel_commerce_js_subdir', 'commercetracking');
$ftpdcfilname = $path . '/' . $subdir . '/' . 'fb_trk_checkoutstart_' . $ftpdcfbid . '.js';
// JS to load into page header.
$page['content']['#attached']['js']['facebook_tracking_pixel_path_drupal_commerce_initiatecheckout'] = [
'type' => 'file',
'group' => JS_THEME,
'data' => $ftpdcfilname,
'preprocess' => (bool) variable_get('facebook_tracking_pixel_aggregation', FALSE),
];
// Noscript for header.
$fb_base_code_nojs = $fb_noscript_src[0] . $ftpdcfbid . $fb_noscript_src[1];
drupal_add_html_head([
'#type' => 'markup',
'#markup' => $fb_base_code_nojs,
'#weight' => 150,
], 'facebook_tracking_pixel_path_drupal_commerce_initiatecheckout');
// Delete session variable.
unset($_SESSION['facebook_tracking_pixel']['ftpdcinitiatecheckout']);
unset($subdir);
break;
case 'ftpdcpurchase':
$ftpdcbasecodeid = variable_get('facebook_tracking_pixel_commerce_tracking_basecode');
$ftpdcfbid = db_select('facebook_tracking_pixel_base_codes', 'c')
->fields('c', [
'base_code_fbid',
])
->condition('base_code_id', $ftpdcbasecodeid, '=')
->execute()
->fetchField();
// We have to load the order and retrieve the total and currency
$order = commerce_order_load($value);
$wrapper = entity_metadata_wrapper('commerce_order', $order);
$currency_code = $wrapper->commerce_order_total->currency_code
->value();
$total = $wrapper->commerce_order_total->amount
->value();
$total = sprintf('%.2f', $total / 100);
// Add the products to the contents parameter, I am using the node ID as the product ID.
$order_contents = '';
foreach ($order->commerce_line_items['und'] as $order_line_item) {
$line_item = commerce_line_item_load($order_line_item['line_item_id']);
if ($line_item && $line_item->type == 'product') {
$order_contents .= '{"id":' . $line_item->data['context']['entity']['entity_id'] . ', "quantity":' . $line_item->quantity . '}';
}
}
// Prepare an array of arguments to do text replacements.
// Add the order contents to the replace array.
$argreplace = [
'@contents' => $order_contents,
'@cur' => $currency_code,
'@val' => $total,
];
// This event will require the JS to be inline in the page.
$reservedevents = facebook_tracking_pixel_events_reserved();
$ftpdcpurcode = format_string($reservedevents['ftpdcpurchase']['code'], $argreplace);
$inlinejs = $fb_script_src[0] . $ftpdcfbid . $fb_script_src[1] . $ftpdcpurcode;
$page['content']['#attached']['js']['facebook_tracking_pixel_path_drupal_commerce_purchase'] = [
'type' => 'inline',
'group' => JS_THEME,
'data' => $inlinejs,
'preprocess' => FALSE,
];
// Noscript for header.
$fb_base_code_nojs = $fb_noscript_src[0] . $ftpdcfbid . $fb_noscript_src[1];
drupal_add_html_head([
'#type' => 'markup',
'#markup' => $fb_base_code_nojs,
'#weight' => 150,
], 'facebook_tracking_pixel_path_drupal_commerce_purchase');
// Delete session variable.
unset($_SESSION['facebook_tracking_pixel']['ftpdcpurchase']);
break;
// If an alter hook has been created. Allow it to be displayed.
default:
$context = [
'fb_script_src' => $fb_script_src,
'fb_noscript_src' => $fb_noscript_src,
];
drupal_alter('facebook_tracking_pixel_event_' . $key, $value, $page, $context);
// Delete session variable for the custom tracking code.
unset($_SESSION['facebook_tracking_pixel'][$key]);
break;
}
}
}
// Gather the path based tracking codes.
$trackingpaths = facebook_tracking_pixel_path_codes();
// If we have tracking codes. Build the page items.
if (!empty($trackingpaths)) {
$i = 0;
foreach ($trackingpaths as $code) {
$page['content']['#attached']['js']['facebook_tracking_pixel_path_' . $i] = [
'type' => 'file',
'group' => JS_THEME,
'data' => $code['event_js_file'],
'preprocess' => (bool) variable_get('facebook_tracking_pixel_aggregation', FALSE),
];
// Assemble code.
if (isset($basecodes[$code['event_base_code_id']])) {
$fb_base_code_nojs = $fb_noscript_src[0] . $basecodes[$code['event_base_code_id']]->base_code_fbid . $fb_noscript_src[1];
drupal_add_html_head([
'#type' => 'markup',
'#markup' => $fb_base_code_nojs,
'#weight' => 150 + $i,
], 'facebook_tracking_pixel_path_noscript_' . $i);
$i++;
}
// If we have a tracking path with the same base code id, we must drop
// the base code ID so it is not loaded below. Preventing duplicate codes
// loading on the same page since the path code will contain the base code
// JS components.
if (array_key_exists($code['event_base_code_id'], $basecodes)) {
unset($basecodes[$code['event_base_code_id']]);
}
}
}
// Process global tracking codes that are to run on the entire site.
$i = 0;
foreach ($basecodes as $id => $values) {
if ($values->base_code_global == 1) {
// Our static tracking file.
$file = $path . '/fb_tkpx.' . $values->base_code_fbid . '.js';
// Page content with the static tracking file.
$page['content']['#attached']['js']['facebook_tracking_pixel_' . $i] = [
'type' => 'file',
'group' => JS_THEME,
'data' => $file,
'preprocess' => (bool) variable_get('facebook_tracking_pixel_aggregation', FALSE),
];
// Assemble noscript code and add it to the head.
$fb_base_code_nojs = $fb_noscript_src[0] . $values->base_code_fbid . $fb_noscript_src[1];
drupal_add_html_head([
'#type' => 'markup',
'#markup' => $fb_base_code_nojs,
'#weight' => 200 + $i,
], 'facebook_tracking_pixel_noscript_' . $i);
}
$i++;
}
}
}
/**
* Return keyed array of standard events.
*
* @return array
*/
function facebook_tracking_pixel_events() {
$hook = 'facebook_tracking_pixel_events';
$results = module_invoke_all($hook);
if (!is_array($results)) {
$results = [];
}
drupal_alter($hook, $results);
return $results;
}
/**
* Implements hook_facebook_tracking_pixel_events().
*
* This is a model of how other modules can alter tracking events. Events
* are keyed wih the name of the event per Facebook documentation. The sub-array
* contains the human readable name and the JS code for the event.
*
* @return array
*/
function facebook_tracking_pixel_facebook_tracking_pixel_events() {
$events = [];
$events['pageview'] = [
'name' => t('Key Page View'),
'code' => 'fbq(\'track\', \'ViewContent\');',
];
$events['search'] = [
'name' => t('Search'),
'code' => 'fbq(\'track\', \'Search\');',
];
$events['addtocart'] = [
'name' => t('Add to Cart'),
'code' => 'fbq(\'track\', \'AddToCart\');',
];
$events['addtowish'] = [
'name' => t('Add to Wishlist'),
'code' => 'fbq(\'track\', \'AddToWishlist\');',
];
$events['checkoutstart'] = [
'name' => t('Initiate checkout'),
'code' => 'fbq(\'track\', \'InitiateCheckout\');',
];
$events['addpaymentinfo'] = [
'name' => t('Add Payment Info'),
'code' => 'fbq(\'track\', \'AddPaymentInfo\');',
];
$events['lead'] = [
'name' => t('Lead'),
'code' => 'fbq(\'track\', \'Lead\');',
];
$events['registration'] = [
'name' => t('Complete Registration'),
'code' => 'fbq(\'track\', \'CompleteRegistration\');',
];
return $events;
}
/**
* Returns the events reserved for this module.
*
* @return array
*/
function facebook_tracking_pixel_events_reserved() {
$events = [];
$events['ftpregistration'] = [
'name' => t('Complete Registration'),
'code' => 'fbq(\'track\', \'CompleteRegistration\');',
];
$events['ftpdcinitiatecheckout'] = [
'name' => t('Initiate checkout'),
'code' => 'fbq(\'track\', \'InitiateCheckout\');',
];
$events['ftpdcaddtocart'] = [
'name' => t('Add to Cart'),
'code' => 'fbq(\'track\', \'AddToCart\', {contents: [{"id":@id, "quantity":@quantity}], content_type: \'product\', value: \'@val\', currency: \'@cur\'});',
];
$events['ftpdcpurchase'] = [
'name' => t('Make Purchase'),
'code' => 'fbq(\'track\', \'Purchase\', {contents: [@contents], content_type: \'product\', value: \'@val\', currency: \'@cur\'});',
];
return $events;
}
/**
* Return keyed array of standard events in a format for select boxes.
*
* @return array
*/
function facebook_tracking_pixel_events_options() {
$events = facebook_tracking_pixel_events();
$options = [];
foreach ($events as $key => $value) {
$options[$key] = $value['name'];
}
return $options;
}
/**
* Implements hook_theme().
*/
function facebook_tracking_pixel_theme() {
return [
'facebook_tracking_pixel_base_codes_form' => [
'render element' => 'form',
'file' => 'facebook_tracking_pixel.admin.inc',
],
'facebook_tracking_pixel_track_by_path_form' => [
'render element' => 'form',
'file' => 'facebook_tracking_pixel.admin.path.inc',
],
];
}
/**
* Returns the pieces of the FB tracking JS script.
*
* @return array
*/
function facebook_tracking_pixel_base_code_js() {
$fb_script_src = [
'!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
n.push=n;n.loaded=!0;n.version=\'2.0\';n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
document,\'script\',\'//connect.facebook.net/en_US/fbevents.js\');
fbq(\'init\', \'',
'\');fbq(\'track\', "PageView");',
];
return $fb_script_src;
}
/**
* Returns the noscript code.
*
* @return array
*/
function facebook_tracking_pixel_base_code_nojs() {
// Facebook static code.
$fb_noscript_src = [
'<noscript><img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=',
'&ev=PageView&noscript=1"/></noscript>',
];
return $fb_noscript_src;
}
/**
* Returns all the path codes and allows other modules to alter them.
*
* @return array
*/
function facebook_tracking_pixel_path_codes() {
$trackingpaths =& drupal_static(__FUNCTION__);
if (!$trackingpaths) {
$result = db_select('facebook_tracking_pixel_events_path', 'g')
->fields('g', [
'event_path',
'event_js_file',
'event_base_code_id',
])
->condition('event_enable', 1, '=');
$result = $result
->execute();
while ($code = $result
->fetchAssoc()) {
$trackingpaths[] = $code;
}
// Allow other modules to alter the codes.
drupal_alter('facebook_tracking_pixel', $trackingpaths);
}
return $trackingpaths;
}
/**
* Based on visibility setting this function an integer. Anything greater than
* 0 is trackable.
*
* @param object $account
* user object
*
* @return bool
*/
function _facebook_tracking_pixel_roles($account) {
// Pull role information from database.
$sql = 'select * from {variable} where name like :name';
$result = db_query($sql, [
':name' => 'facebook_tracking_pixel_roles_%',
])
->fetchAll();
// Pull the visibility setting. A value of 1 means the roles are inverted in
// the selection UI.
$visibility = variable_get('facebook_tracking_pixel_visibility_roles', 0);
// If the selection is inverted we enable visibility. Otherwise default is
// no tracking.
$enabled = $visibility;
$roles = [];
// Build array of role information.
if (!empty($result)) {
foreach ($result as $item) {
if ($item->value == 'i:1;') {
$roles[$item->name] = 1;
}
elseif ($item->value == 'i:0;') {
$roles[$item->name] = 0;
}
}
}
if (array_sum($roles) > 0) {
// One or more roles are selected.
foreach ($account->roles as $rid => $rname) {
// Fixup the role name.
$rname = str_replace(' ', '_', $rname);
$rname = 'facebook_tracking_pixel_roles_' . $rname;
// Is the current user a member of one of these roles?
if (isset($roles[$rname]) && $roles[$rname] == 1) {
// Current user is a member of a role that should be tracked/excluded
// from tracking. The visibility variable is used and inverted. This
// accounts for the settings in the UI of tracking only selected or
// tracking all but selected.
$enabled = !$visibility;
break;
}
}
}
return $enabled;
}
/**
* Implements hook_user_insert().
*/
function facebook_tracking_pixel_user_insert(&$edit, $account, $category) {
$registration = variable_get('facebook_tracking_pixel_user_registration_enable', FALSE);
if ($registration) {
// We add the FBID to a session variable.
$basecodeid = variable_get('facebook_tracking_pixel_user_registration_basecode');
$base_code_fbid = db_select('facebook_tracking_pixel_base_codes', 'c')
->fields('c', [
'base_code_fbid',
])
->condition('base_code_id', $basecodeid, '=')
->execute()
->fetchField();
facebook_tracking_pixel_add_session_event('registration');
facebook_tracking_pixel_add_session_event('registration_fbid', $base_code_fbid);
}
}
/**
* We use our own hook_alter to load the codes.
* This is also an example of how another module would alter the codes.
*
* @param $trackingpaths
*/
function facebook_tracking_pixel_facebook_tracking_pixel_alter(&$trackingpaths) {
if (!empty($trackingpaths)) {
foreach ($trackingpaths as $index => $code) {
$page_match = FALSE;
$paths = $code['event_path'];
$path = drupal_strtolower(drupal_get_path_alias($_GET['q']));
// Compare the lowercase internal and lowercase path alias (if any).
$path_match = drupal_match_path($path, $paths);
if ($path != $_GET['q']) {
$path_match = $path_match || drupal_match_path($_GET['q'], $paths);
}
if (!$path_match) {
unset($trackingpaths[$index]);
}
}
}
}
/**
* Remove a base code by the FBID number.
*
* @param int $tid
* @param int $fbid
*
* @return bool
*/
function facebook_tracking_pixel_base_code_delete($tid, $fbid) {
$status = TRUE;
// Remove JS file.
$filename = 'fb_tkpx.' . $fbid . '.js';
$filedelete = facebook_tracking_pixel_delete_file($filename);
if (!$filedelete) {
$status = FALSE;
}
if (!$status) {
drupal_set_message(t('Failed to delete base code file.'), 'error', FALSE);
}
// Remove base code from database.
if (!db_delete('facebook_tracking_pixel_base_codes')
->condition('base_code_id', $tid, '=')
->execute()) {
$status = FALSE;
}
$pathcount = db_select('facebook_tracking_pixel_events_path', 'c')
->fields('c')
->condition('event_base_code_id', $tid, '=')
->countQuery()
->execute()
->fetchField();
if ($pathcount > 0) {
$subdir = variable_get('facebook_tracking_pixel_path_subdir', 'pathtracking');
try {
$deletepathuids = db_select('facebook_tracking_pixel_events_path', 'c')
->fields('c', [
'event_uid',
])
->condition('event_base_code_id', $tid, '=')
->execute()
->fetchAssoc();
foreach ($deletepathuids as $item) {
facebook_tracking_pixel_delete_file('fb_trk.' . $item . '.js', $subdir);
}
} catch (Exception $e) {
watchdog('facebook_tracking_pixel', 'Failed to delete path items when deleting a base code %error.', [
'%error' => $e
->getMessage(),
], WATCHDOG_ERROR, NULL);
drupal_set_message('Could not save the JS file. Check the Drupal and PHP logs.', 'error', FALSE);
$status = FALSE;
}
// Remove path tracking referencing this basecode from the database.
try {
db_delete('facebook_tracking_pixel_events_path')
->condition('event_base_code_id', $tid, '=')
->execute();
} catch (Exception $e) {
watchdog('facebook_tracking_pixel', 'Failed to delete path items DB entries when deleting a base code %error.', [
'%error' => $e
->getMessage(),
], WATCHDOG_ERROR, NULL);
$status = FALSE;
}
}
// If the Base Code ID being deleted matches one use for user tracking, destroy.
$usertrackingid = variable_get('facebook_tracking_pixel_user_registration_basecode', NULL);
if ($usertrackingid == $tid) {
variable_del('facebook_tracking_pixel_user_registration_basecode');
variable_del('facebook_tracking_pixel_user_registration_enable');
unset($_SESSION['facebook_tracking_pixel']['registration']);
unset($_SESSION['facebook_tracking_pixel']['registration_fbid']);
facebook_tracking_pixel_delete_file('fb_trk_user_registration.js', 'registrationtracking');
}
if (!$status) {
drupal_set_message(t('Failed to remove base code from database.'), 'error', FALSE);
}
if (!$status) {
drupal_set_message(t('Check your PHP server logs.'), 'error', FALSE);
}
else {
drupal_set_message(t('Base code deleted.'), 'status', FALSE);
}
if ($filedelete) {
facebook_tracking_pixel_clear_cache();
}
return $status;
}
/**
* Deletes all CSS & JavaScript from the file system or a single file.
*
* @param null $filename
* @param null $subdir
*
* @return bool
*/
function facebook_tracking_pixel_delete_file($filename = NULL, $subdir = NULL) {
$path = variable_get('facebook_tracking_pixel_path', 'public://facebook_tracking_pixel');
// Calling the function without a file name will delete everything.
if ($filename == NULL) {
if (!($files = file_scan_directory($path, '/.*\\.js$/'))) {
foreach ($files as $key => $value) {
file_unmanaged_delete($path . '/' . $key);
}
return TRUE;
}
}
else {
if (!empty($subdir)) {
$deletepath = $path . '/' . $subdir . '/' . $filename;
}
else {
$deletepath = $path . '/' . $filename;
}
file_unmanaged_delete($deletepath);
return TRUE;
}
return FALSE;
}
/**
* Saves JavaScript in the file system (but only if not empty).
*
* @param $data
* @param $filename
* @param null $subdir
*
* @return bool|null|string
*/
function facebook_tracking_pixel_save_file($data, $filename, $subdir = NULL) {
if (!drupal_strlen(trim($data))) {
return FALSE;
}
$path = variable_get('facebook_tracking_pixel_path', 'public://facebook_tracking_pixel');
if (!empty($subdir)) {
$path = $path . '/' . $subdir;
}
file_prepare_directory($path, FILE_CREATE_DIRECTORY);
$file_saved = file_unmanaged_save_data($data, $path . '/' . $filename, FILE_EXISTS_REPLACE);
facebook_tracking_pixel_clear_cache();
return $file_saved;
}
/**
* Function to call from CRUD operations to clear caches.
*/
function facebook_tracking_pixel_clear_cache() {
cache_clear_all('*', 'cache_page', TRUE);
// Clear views cache if available.
if (module_exists('views')) {
cache_clear_all('*', 'cache_views', TRUE);
cache_clear_all('*', 'cache_views_data', TRUE);
}
// Trigger reloading the CSS and JS file cache in AdvAgg, if available.
if (module_exists('advagg')) {
module_load_include('inc', 'advagg', 'advagg.cache');
advagg_push_new_changes();
}
}
/**
* Adds Facebook Pixel event to the user session to be added to the page code.
*
* @param string $event
* A Facebook Pixel event to be added to the page code via sessions.
*
* @param string $value
* If the event has a value it can be passed.
*
* @see facebook_tracking_pixel_events() for details on events.
*/
function facebook_tracking_pixel_add_session_event($event, $value = NULL) {
// In the session variable we store the key to our array of events.
if (!isset($_SESSION['facebook_tracking_pixel'])) {
$_SESSION['facebook_tracking_pixel'] = [];
}
// Use event name for array key as well, so that we don't send
// the same event multiple times. And if a value is supplied it
// is passed in the session variable.
if (!empty($value)) {
$_SESSION['facebook_tracking_pixel'][$event] = $value;
}
else {
$_SESSION['facebook_tracking_pixel'][$event] = TRUE;
}
}
/**
* Returns currency codes from the xml file.
*
* This is used if Drupal Commerce is not available.
*
* @return array
*/
function facebook_tracking_pixel_get_currency_codes() {
$currencyfile = drupal_get_path('module', 'facebook_tracking_pixel') . '/' . 'currency-codes-iso4217.xml';
$currencydata = simplexml_load_file($currencyfile);
$json_string = json_encode($currencydata);
$result_array = json_decode($json_string, TRUE);
$currencycodes = [];
foreach ($result_array['CcyTbl']['CcyNtry'] as $item) {
if (!empty($item['Ccy'])) {
$currencycodes[$item['Ccy']] = $item['CcyNm'] . ' (' . $item['Ccy'] . ')';
}
}
return $currencycodes;
}
/**
* Implements hook_commerce_cart_product_add().
*
* Tracks when an item is added to the cart.
*
* @param $order
* @param $product
* @param $quantity
* @param $line_item
*/
function facebook_tracking_pixel_commerce_cart_product_add($order, $product, $quantity, $line_item) {
$enable = variable_get('facebook_tracking_pixel_commerce_tracking_enable', NULL);
if ($enable && ($options = variable_get('facebook_tracking_pixel_commerce_tracking_options_selection', NULL))) {
if (array_key_exists('addtocart', $options)) {
// I am using the node ID as the product ID.
$value = [
'content_id' => $line_item->data['context']['entity']['entity_id'],
'currency_code' => $line_item->commerce_unit_price['und'][0]['currency_code'],
'quantity' => $quantity,
'value' => commerce_currency_amount_to_decimal($line_item->commerce_unit_price['und'][0]['amount'], $line_item->commerce_unit_price['und'][0]['currency_code']),
];
facebook_tracking_pixel_add_session_event('ftpdcaddtocart', $value);
}
}
}
/**
* Implements hook_commerce_checkout_router().
*
* Tracks when a customer enters the checkout workflow.
*
* @param $order
* @param $checkout_page
*/
function facebook_tracking_pixel_commerce_checkout_router($order, $checkout_page) {
$enable = variable_get('facebook_tracking_pixel_commerce_tracking_enable', NULL);
$options = variable_get('facebook_tracking_pixel_commerce_tracking_options_selection', NULL);
if ($enable && !empty($options)) {
if (array_key_exists('checkoutstart', $options)) {
if ($checkout_page['page_id'] == 'checkout') {
facebook_tracking_pixel_add_session_event('ftpdcinitiatecheckout');
}
}
}
}
/**
* Implements hook_commerce_checkout_complete().
*
* This fires when checkout is complete to track the event.
*
* @param $order
*/
function facebook_tracking_pixel_commerce_checkout_complete($order) {
$enable = variable_get('facebook_tracking_pixel_commerce_tracking_enable', 0);
if ($enable) {
$options = variable_get('facebook_tracking_pixel_commerce_tracking_options_selection');
if (array_key_exists('purchase', $options)) {
// We pass and store the order ID number so it can be used to populate currency
// and total values in the page build.
facebook_tracking_pixel_add_session_event('ftpdcpurchase', $order->order_id);
}
}
}
/**
* Implements hook_node_delete().
*/
function facebook_tracking_pixel_node_delete($node) {
// If the node being deleted has a path tracking item, disable the item.
$result = db_select('facebook_tracking_pixel_events_path', 'c')
->fields('c')
->condition('event_path_system', 'node/' . $node->nid, '=')
->execute()
->fetchAssoc();
if ($result) {
// If a node exists then we update the DB to disable that item.
db_update('facebook_tracking_pixel_events_path')
->fields([
'event_enable' => 0,
])
->condition('event_id', $result['event_id'], '=')
->execute();
}
}