|
Server : Apache/2.4.18 (Ubuntu) System : Linux canvaswebdesign 3.13.0-71-generic #114-Ubuntu SMP Tue Dec 1 02:34:22 UTC 2015 x86_64 User : oppastar ( 1041) PHP Version : 7.0.33-0ubuntu0.16.04.15 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority, Directory : /var/www/laciasmara.com/public_html/shop/application/libraries/ |
Upload File : |
<?php defined('BASEPATH') or exit('No direct script access allowed');
class VisitorTracking
{
private $CI;
private $session_key = 'initial_visitor_tracking';
private $utm_session_key = 'utm_data';
private $cookie_name = 'visitor_tracking';
private $cookie_expire = 2592000; // 30 days
private $excluded_ips = [];
public function __construct()
{
$this->CI = &get_instance();
$this->CI->load->database();
$this->CI->load->library('session');
$this->CI->load->library('user_agent');
$this->CI->load->helper(['url', 'cookie']);
// Ensure session is started
if (!$this->CI->session->userdata('session_id')) {
$this->CI->session->set_userdata('session_id', session_id());
}
// Migrate old session data if exists
$this->migrateOldSessionData();
// Initialize session debugging
$this->debugSession('Constructor called');
}
private function migrateOldSessionData()
{
$old_tracking = $this->CI->session->userdata('visitor_tracking');
if ($old_tracking && !$this->CI->session->userdata($this->session_key)) {
$this->CI->session->set_userdata($this->session_key, $old_tracking);
$this->debugSession('Migrated old session data');
}
}
private function debugSession($message)
{
if (ENVIRONMENT === 'development') {
log_message('debug', 'VisitorTracking: ' . $message . ' | Session ID: ' . session_id());
}
}
public function trackVisitor()
{
$this->debugSession('trackVisitor() method called');
try {
$current_ip = $this->CI->input->ip_address();
if ($this->isExcludedIP($current_ip)) {
$this->debugSession('IP excluded: ' . $current_ip);
return false;
}
// Check UTM parameters first
$utm_params = $this->getUTMParams();
$initial_tracking = $this->getInitialTracking();
// If there are UTM parameters, this should override the existing tracking
if (!empty($utm_params['utm_source'])) {
$initial_tracking = $this->createTrackingFromUTM($utm_params);
} else {
// No UTM parameters in current URL
if (empty($initial_tracking)) {
$initial_tracking = $this->createTrackingFromSource();
}
}
// Always track the pageview with the original source
$this->trackPageview($initial_tracking);
return $initial_tracking;
} catch (Exception $e) {
log_message('error', 'Error in trackVisitor: ' . $e->getMessage());
return false;
}
}
private function getUTMParams()
{
return [
'utm_source' => $this->CI->input->get('utm_source'),
'utm_medium' => $this->CI->input->get('utm_medium'),
'utm_campaign' => $this->CI->input->get('utm_campaign'),
'utm_content' => $this->CI->input->get('utm_content'),
'utm_term' => $this->CI->input->get('utm_term'),
'q' => $this->CI->input->get('q')
];
}
private function getInitialTracking()
{
// Try session first
$tracking = $this->CI->session->userdata($this->session_key);
// If no session data, try cookie fallback
if (empty($tracking)) {
$cookie_data = get_cookie($this->cookie_name);
if ($cookie_data) {
$tracking = json_decode($cookie_data, true);
if ($tracking) {
// Restore to session
$this->setTrackingData($tracking);
$this->debugSession('Restored tracking from cookie');
}
}
}
return $tracking;
}
private function createTrackingFromUTM($utm_params)
{
$source = [
'utm_source' => $utm_params['utm_source'],
'utm_medium' => $utm_params['utm_medium'] ?? 'none',
'utm_campaign' => $utm_params['utm_campaign'] ?? 'none',
'utm_content' => $utm_params['utm_content'] ?? 'none',
'utm_term' => $utm_params['utm_term'] ?? 'none',
'utm_query' => $utm_params['q']
];
$tracking_data = $this->createTrackingData($source);
$this->setTrackingData($tracking_data);
return $tracking_data;
}
private function createTrackingFromSource()
{
$source = $this->determineTrafficSource();
$tracking_data = $this->createTrackingData($source);
$this->setTrackingData($tracking_data);
return $tracking_data;
}
private function createTrackingData($source)
{
$tracking_id = uniqid('track_' . time() . '_');
return [
'tracking_id' => $tracking_id,
'source' => $source['utm_source'],
'medium' => $source['utm_medium'],
'campaign' => $source['utm_campaign'],
'content' => $source['utm_content'],
'term' => $source['utm_term'],
'query' => $source['utm_query'],
'ip_address' => $this->CI->input->ip_address(),
'initial_url' => current_url(),
'timestamp' => time(),
'user_agent' => $this->CI->input->user_agent(),
'browser' => $this->CI->agent->browser(),
'browser_version' => $this->CI->agent->version(),
'platform' => $this->CI->agent->platform(),
'is_mobile' => $this->CI->agent->is_mobile(),
'is_robot' => $this->CI->agent->is_robot(),
'country' => $this->getCountryFromIP($this->CI->input->ip_address()),
'session_id' => session_id()
];
}
private function setTrackingData($tracking_data)
{
// Set session data with multiple attempts
$session_set = false;
$attempts = 0;
while (!$session_set && $attempts < 3) {
$this->CI->session->set_userdata($this->session_key, $tracking_data);
$this->CI->session->set_userdata('visitor_tracking', $tracking_data);
// Verify session was set
if ($this->CI->session->userdata($this->session_key)) {
$session_set = true;
$this->debugSession('Session data set successfully on attempt ' . ($attempts + 1));
} else {
$attempts++;
$this->debugSession('Session set failed, attempt ' . $attempts);
usleep(100000); // Wait 100ms before retry
}
}
// Cookie fallback
$cookie_data = json_encode($tracking_data);
set_cookie($this->cookie_name, $cookie_data, $this->cookie_expire);
$this->debugSession('Cookie backup set');
// Set UTM data for consistency
$utm_data = [
'utm_source' => $tracking_data['source'],
'utm_medium' => $tracking_data['medium'],
'utm_campaign' => $tracking_data['campaign'],
'utm_content' => $tracking_data['content']
];
$this->CI->session->set_userdata('data_utm', $utm_data);
$this->CI->session->set_userdata($this->utm_session_key, $utm_data);
}
private function trackPageview($initial_tracking)
{
if (empty($initial_tracking)) {
$this->debugSession('No initial tracking data for pageview');
return false;
}
$referral_code = $this->CI->session->userdata('referral');
$track_data = [
'id' => uniqid('page_' . time() . '_'),
'tracking_id' => $initial_tracking['tracking_id'],
'link_url' => current_url(),
'source' => $initial_tracking['source'],
'ip_address' => $this->CI->input->ip_address(),
'user_agent' => $this->CI->input->user_agent(),
'referer' => $this->CI->input->server('HTTP_REFERER'),
'session_id' => session_id(),
'utm_source' => $initial_tracking['source'],
'utm_medium' => $initial_tracking['medium'],
'utm_campaign' => $initial_tracking['campaign'],
'utm_content' => $initial_tracking['content'],
'utm_term' => $initial_tracking['term'],
'search_query' => $initial_tracking['query'],
'referral_code' => $referral_code,
'browser' => $initial_tracking['browser'] ?? '',
'browser_version' => $initial_tracking['browser_version'] ?? '',
'platform' => $initial_tracking['platform'] ?? '',
'is_mobile' => $initial_tracking['is_mobile'] ?? false,
'is_robot' => $initial_tracking['is_robot'] ?? false,
'country' => $initial_tracking['country'] ?? '',
'created_at' => date('Y-m-d H:i:s')
];
$insert_result = $this->CI->db->insert('link_tracks', $track_data);
if ($insert_result) {
$this->debugSession('Successfully inserted tracking data');
} else {
log_message('error', 'Failed to insert tracking data: ' . $this->CI->db->last_query());
}
return $insert_result;
}
private function getCountryFromIP($ip)
{
// Simple IP to country detection (you can enhance this with GeoIP)
if ($this->isExcludedIP($ip)) {
return 'Local';
}
// Basic country detection based on IP ranges (very simplified)
// In production, use a proper GeoIP service
return 'Unknown';
}
private function isExcludedIP($ip)
{
$checkIpInRange = function ($ip, $range) {
if (strpos($range, '/') !== false) {
list($range, $netmask) = explode('/', $range, 2);
$range_decimal = ip2long($range);
$ip_decimal = ip2long($ip);
$wildcard_decimal = pow(2, (32 - $netmask)) - 1;
$netmask_decimal = ~$wildcard_decimal;
return (($ip_decimal & $netmask_decimal) == ($range_decimal & $netmask_decimal));
} else {
return $ip === $range;
}
};
foreach ($this->excluded_ips as $excluded) {
if ($checkIpInRange($ip, $excluded)) {
return true;
}
}
return false;
}
private function determineTrafficSource()
{
$source = [
'utm_source' => 'direct',
'utm_medium' => 'none',
'utm_campaign' => 'none',
'utm_content' => 'none',
'utm_term' => 'none',
'utm_query' => null,
'raw_referer' => null
];
// Get UTM parameters
$utm_params = $this->getUTMParams();
// If UTM parameters exist, use them
if (!empty($utm_params['utm_source'])) {
$source['utm_source'] = $utm_params['utm_source'];
$source['utm_medium'] = $utm_params['utm_medium'] ?? 'none';
$source['utm_campaign'] = $utm_params['utm_campaign'] ?? 'none';
$source['utm_content'] = $utm_params['utm_content'] ?? 'none';
$source['utm_term'] = $utm_params['utm_term'] ?? 'none';
$source['utm_query'] = $utm_params['q'];
return $source;
}
// Check for existing UTM data in session
$session_utm = $this->CI->session->userdata($this->utm_session_key);
if (!empty($session_utm)) {
return $session_utm;
}
// If no UTM parameters, check referer
$referer = $this->CI->input->server('HTTP_REFERER');
if ($referer) {
$parsed_referer = parse_url($referer);
$host = strtolower($parsed_referer['host'] ?? '');
$known_referrers = [
'google' => ['source' => 'google', 'medium' => 'organic'],
'facebook.com' => ['source' => 'facebook', 'medium' => 'social'],
'instagram.com' => ['source' => 'instagram', 'medium' => 'social'],
'm.facebook.com' => ['source' => 'facebook', 'medium' => 'social'],
'm.instagram.com' => ['source' => 'instagram', 'medium' => 'social'],
'l.facebook.com' => ['source' => 'facebook', 'medium' => 'paid'],
'lm.facebook.com' => ['source' => 'facebook', 'medium' => 'paid'],
'l.instagram.com' => ['source' => 'instagram', 'medium' => 'paid'],
't.co' => ['source' => 'twitter', 'medium' => 'social'],
'twitter.com' => ['source' => 'twitter', 'medium' => 'social'],
'linkedin.com' => ['source' => 'linkedin', 'medium' => 'social'],
'youtube.com' => ['source' => 'youtube', 'medium' => 'social'],
'm.youtube.com' => ['source' => 'youtube', 'medium' => 'social'],
'youtu.be' => ['source' => 'youtube', 'medium' => 'social'],
'tiktok.com' => ['source' => 'tiktok', 'medium' => 'social'],
'vm.tiktok.com' => ['source' => 'tiktok', 'medium' => 'social'],
'm.tiktok.com' => ['source' => 'tiktok', 'medium' => 'social']
];
foreach ($known_referrers as $domain => $props) {
if (strpos($host, $domain) !== false) {
$source['utm_source'] = $props['source'];
$source['utm_medium'] = $props['medium'];
break;
}
}
if ($source['utm_source'] === 'direct' && !empty($host)) {
$source['utm_source'] = $host;
$source['utm_medium'] = 'referral';
}
$source['raw_referer'] = $referer;
}
return $source;
}
// Public methods for accessing tracking data
public function getTrackingData()
{
$tracking_data = $this->getInitialTracking();
$this->debugSession('Retrieved tracking data: ' . ($tracking_data ? 'found' : 'not found'));
return $tracking_data;
}
public function getUTMData()
{
return $this->CI->session->userdata($this->utm_session_key);
}
public function clearTrackingData()
{
$this->CI->session->unset_userdata($this->session_key);
$this->CI->session->unset_userdata('visitor_tracking');
$this->CI->session->unset_userdata($this->utm_session_key);
$this->CI->session->unset_userdata('data_utm');
delete_cookie($this->cookie_name);
$this->debugSession('Tracking data cleared');
}
public function getSessionDebugInfo()
{
return [
'session_id' => session_id(),
'session_data' => $this->CI->session->all_userdata(),
'cookie_data' => get_cookie($this->cookie_name),
'tracking_data' => $this->getTrackingData(),
'utm_data' => $this->getUTMData()
];
}
// IP management methods
public function addExcludedIP($ip)
{
if (!in_array($ip, $this->excluded_ips)) {
$this->excluded_ips[] = $ip;
}
}
public function getExcludedIPs()
{
return $this->excluded_ips;
}
public function removeExcludedIP($ip)
{
$key = array_search($ip, $this->excluded_ips);
if ($key !== false) {
unset($this->excluded_ips[$key]);
}
}
}