Home
Time-of-Day Behavioral Tagger

Time-of-Day Behavioral Tagger

Temporal User Segmentation

Automatically segments visitors based on time-of-day patterns, business hours, and behavioral timing to enable time-sensitive personalization and targeted messaging campaigns.

BehavioralIntermediateBehavioral Tracking

Key Features

Automatic timezone detection
Business hours classification
Time-based user segmentation
Behavioral pattern analysis
Custom time zone support
Weekend/weekday detection

Script Overview

📖

What It Does

This script analyzes the visitor's local time to create behavioral segments based on when they visit your site. It detects timezone, classifies visits into business hours, weekend/weekday patterns, and pushes detailed temporal data to GTM for personalized messaging and analytics.

🎯

Use Case

Great for businesses with time-sensitive offers or different messaging for business hours. Perfect for B2B companies that want to tailor messaging based on when prospects are most likely to be working vs browsing personally.

Key Benefits

  • Time-based visitor segmentation for personalization
  • Business hours vs after-hours visitor classification
  • Weekend and weekday behavioral analysis
  • Timezone-aware visitor insights
  • Enhanced behavioral targeting capabilities
  • Temporal conversion pattern analysis

JavaScript Code

<script>
(function() {
  'use strict';
  
  // Time-of-Day Behavioral Tagger Script
  // Version: 1.0
  // Description: Segments visitors by time patterns and behavior
  // Last Updated: 2025-09-09
  
  // Configuration
  var config = {
    // Business hours configuration (24-hour format)
    businessHours: {
      start: 9,  // 9 AM
      end: 17,   // 5 PM
      timezone: 'auto' // 'auto' to detect, or specify like 'America/New_York'
    },
    
    // Weekend configuration
    weekendDays: [0, 6], // Sunday = 0, Saturday = 6
    
    // Time segments configuration
    timeSegments: {
      'early-morning': { start: 5, end: 9 },    // 5 AM - 9 AM
      'morning': { start: 9, end: 12 },         // 9 AM - 12 PM
      'afternoon': { start: 12, end: 17 },      // 12 PM - 5 PM
      'evening': { start: 17, end: 21 },        // 5 PM - 9 PM
      'night': { start: 21, end: 24 },          // 9 PM - 12 AM
      'late-night': { start: 0, end: 5 }        // 12 AM - 5 AM
    },
    
    // DataLayer event configuration
    events: {
      timeSegment: 'time_behavioral_tag',
      sessionAnalysis: 'session_time_analysis'
    },
    
    // Storage for session analysis
    storageKey: 'time_behavioral_data',
    
    // Debug mode
    debug: false
  };

  // Utility functions
  function debugLog(message, data) {
    if (config.debug) {
      console.log('[Time Tagger] ' + message, data || '');
    }
  }

  function getCurrentTimeInfo() {
    var now = new Date();
    var timeInfo = {
      timestamp: now.getTime(),
      iso: now.toISOString(),
      
      // Local time information
      localHour: now.getHours(),
      localMinute: now.getMinutes(),
      localDay: now.getDay(), // 0 = Sunday, 6 = Saturday
      localDate: now.getDate(),
      localMonth: now.getMonth() + 1,
      localYear: now.getFullYear(),
      
      // Timezone information
      timezoneOffset: now.getTimezoneOffset(),
      timezone: Intl.DateTimeFormat().resolvedOptions().timeZone || 'Unknown'
    };
    
    return timeInfo;
  }

  function getTimeSegment(hour) {
    for (var segment in config.timeSegments) {
      var segmentConfig = config.timeSegments[segment];
      
      // Handle segments that cross midnight
      if (segmentConfig.start > segmentConfig.end) {
        if (hour >= segmentConfig.start || hour < segmentConfig.end) {
          return segment;
        }
      } else {
        if (hour >= segmentConfig.start && hour < segmentConfig.end) {
          return segment;
        }
      }
    }
    
    return 'unknown';
  }

  function isBusinessHours(hour, day) {
    // Check if it's a weekend
    if (config.weekendDays.includes(day)) {
      return false;
    }
    
    // Check if within business hours
    return hour >= config.businessHours.start && hour < config.businessHours.end;
  }

  function isWeekend(day) {
    return config.weekendDays.includes(day);
  }

  function getBehavioralClassification(timeInfo) {
    var classification = {
      timeSegment: getTimeSegment(timeInfo.localHour),
      isBusinessHours: isBusinessHours(timeInfo.localHour, timeInfo.localDay),
      isWeekend: isWeekend(timeInfo.localDay),
      dayType: isWeekend(timeInfo.localDay) ? 'weekend' : 'weekday',
      hourCategory: timeInfo.localHour < 12 ? 'am' : 'pm'
    };
    
    // Advanced behavioral insights
    if (classification.isBusinessHours && !classification.isWeekend) {
      classification.behaviorType = 'business-browsing';
      classification.intent = 'professional';
    } else if (classification.isWeekend) {
      classification.behaviorType = 'leisure-browsing';
      classification.intent = 'personal';
    } else if (!classification.isBusinessHours && !classification.isWeekend) {
      classification.behaviorType = 'after-hours-browsing';
      classification.intent = 'mixed';
    } else {
      classification.behaviorType = 'general-browsing';
      classification.intent = 'unknown';
    }
    
    return classification;
  }

  function getSessionTimePattern() {
    try {
      var stored = sessionStorage.getItem(config.storageKey + '_session');
      if (stored) {
        return JSON.parse(stored);
      }
    } catch (e) {
      debugLog('Error reading session time data:', e);
    }
    return null;
  }

  function updateSessionTimePattern(timeInfo, classification) {
    try {
      var sessionData = getSessionTimePattern() || {
        sessionStart: timeInfo.timestamp,
        visitCount: 0,
        timeSegments: [],
        behaviorTypes: []
      };
      
      sessionData.visitCount += 1;
      sessionData.lastVisit = timeInfo.timestamp;
      sessionData.sessionDuration = timeInfo.timestamp - sessionData.sessionStart;
      
      // Track unique time segments in this session
      if (!sessionData.timeSegments.includes(classification.timeSegment)) {
        sessionData.timeSegments.push(classification.timeSegment);
      }
      
      // Track unique behavior types in this session
      if (!sessionData.behaviorTypes.includes(classification.behaviorType)) {
        sessionData.behaviorTypes.push(classification.behaviorType);
      }
      
      sessionStorage.setItem(config.storageKey + '_session', JSON.stringify(sessionData));
      return sessionData;
    } catch (e) {
      debugLog('Error updating session time data:', e);
      return null;
    }
  }

  function getHistoricalTimePattern() {
    try {
      var stored = localStorage.getItem(config.storageKey);
      if (stored) {
        var data = JSON.parse(stored);
        
        // Clean old data (keep only last 30 days)
        var thirtyDaysAgo = Date.now() - (30 * 24 * 60 * 60 * 1000);
        if (data.visits) {
          data.visits = data.visits.filter(function(visit) {
            return visit.timestamp > thirtyDaysAgo;
          });
        }
        
        return data;
      }
    } catch (e) {
      debugLog('Error reading historical time data:', e);
    }
    
    return {
      visits: [],
      patterns: {},
      preferences: {}
    };
  }

  function updateHistoricalTimePattern(timeInfo, classification) {
    try {
      var historical = getHistoricalTimePattern();
      
      // Add current visit
      historical.visits.push({
        timestamp: timeInfo.timestamp,
        timeSegment: classification.timeSegment,
        behaviorType: classification.behaviorType,
        isBusinessHours: classification.isBusinessHours,
        isWeekend: classification.isWeekend
      });
      
      // Update patterns
      historical.patterns.mostCommonTimeSegment = getMostCommonValue(
        historical.visits.map(function(v) { return v.timeSegment; })
      );
      
      historical.patterns.mostCommonBehaviorType = getMostCommonValue(
        historical.visits.map(function(v) { return v.behaviorType; })
      );
      
      // Calculate preferences
      var businessHoursVisits = historical.visits.filter(function(v) { return v.isBusinessHours; });
      var weekendVisits = historical.visits.filter(function(v) { return v.isWeekend; });
      
      historical.preferences.businessHoursFrequency = businessHoursVisits.length / historical.visits.length;
      historical.preferences.weekendFrequency = weekendVisits.length / historical.visits.length;
      historical.preferences.totalVisits = historical.visits.length;
      
      localStorage.setItem(config.storageKey, JSON.stringify(historical));
      return historical;
    } catch (e) {
      debugLog('Error updating historical time data:', e);
      return null;
    }
  }

  function getMostCommonValue(array) {
    var counts = {};
    var mostCommon = array[0];
    var maxCount = 1;
    
    array.forEach(function(item) {
      counts[item] = (counts[item] || 0) + 1;
      if (counts[item] > maxCount) {
        mostCommon = item;
        maxCount = counts[item];
      }
    });
    
    return mostCommon;
  }

  function pushToDataLayer(timeInfo, classification, sessionData, historicalData) {
    window.dataLayer = window.dataLayer || [];
    
    // Main time behavioral event
    var eventData = {
      event: config.events.timeSegment,
      
      // Current time information
      time_segment: classification.timeSegment,
      is_business_hours: classification.isBusinessHours,
      is_weekend: classification.isWeekend,
      day_type: classification.dayType,
      behavior_type: classification.behaviorType,
      intent_type: classification.intent,
      
      // Time details
      local_hour: timeInfo.localHour,
      local_day: timeInfo.localDay,
      timezone: timeInfo.timezone,
      
      // Session information
      session_visit_count: sessionData ? sessionData.visitCount : 1,
      session_time_segments: sessionData ? sessionData.timeSegments : [classification.timeSegment],
      
      // Historical patterns (if available)
      visitor_time_preference: historicalData ? historicalData.patterns.mostCommonTimeSegment : classification.timeSegment,
      visitor_behavior_preference: historicalData ? historicalData.patterns.mostCommonBehaviorType : classification.behaviorType,
      business_hours_frequency: historicalData ? Math.round(historicalData.preferences.businessHoursFrequency * 100) : null,
      weekend_frequency: historicalData ? Math.round(historicalData.preferences.weekendFrequency * 100) : null
    };
    
    window.dataLayer.push(eventData);
    
    // Session analysis event (if multiple visits in session)
    if (sessionData && sessionData.visitCount > 1) {
      window.dataLayer.push({
        event: config.events.sessionAnalysis,
        session_duration_minutes: Math.round(sessionData.sessionDuration / (1000 * 60)),
        session_time_segments_count: sessionData.timeSegments.length,
        session_behavior_diversity: sessionData.behaviorTypes.length
      });
    }
    
    debugLog('Time behavioral data pushed to dataLayer:', eventData);
  }

  // Main execution
  function initTimeBehavioralTagger() {
    debugLog('Initializing Time Behavioral Tagger');
    
    var timeInfo = getCurrentTimeInfo();
    var classification = getBehavioralClassification(timeInfo);
    
    debugLog('Time classification:', classification);
    
    // Update session and historical data
    var sessionData = updateSessionTimePattern(timeInfo, classification);
    var historicalData = updateHistoricalTimePattern(timeInfo, classification);
    
    // Push to dataLayer
    pushToDataLayer(timeInfo, classification, sessionData, historicalData);
  }

  // Initialize when DOM is ready
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', initTimeBehavioralTagger);
  } else {
    initTimeBehavioralTagger();
  }

  // Expose utility functions
  window.timeBehavioralTagger = {
    getCurrentClassification: function() {
      var timeInfo = getCurrentTimeInfo();
      return getBehavioralClassification(timeInfo);
    },
    getSessionData: function() {
      return getSessionTimePattern();
    },
    getHistoricalData: function() {
      return getHistoricalTimePattern();
    },
    clearHistoricalData: function() {
      localStorage.removeItem(config.storageKey);
      debugLog('Historical time data cleared');
    },
    refreshAnalysis: function() {
      initTimeBehavioralTagger();
    }
  };

})();
</script>

💡 Pro Tip: Copy the entire code block above and paste it directly into a GTM Custom HTML tag. The script is self-contained and ready to use immediately.