Date Variables
Date Variables
Time is a segmentation axis, a compliance requirement, and an attribution signal — all at once. Fire tags only during business hours. Send Meta CAPI the Unix timestamp it demands. Calculate lead time from form to purchase. Convert dates between every system that speaks a different format. Date is the category that makes time behave — 30 sandbox-safe variable templates for dayparting, timestamps, format conversion, and duration math. No Custom JavaScript.
Why this category exists
Section titled “Why this category exists”Every GTM container handles time somewhere. Some tags need to fire only at specific times of day. Some destinations require Unix timestamps in a specific unit. Some dataLayer values arrive as dates in the wrong format. Some attribution reports need duration math between events. These are separate problems with the same substrate — and almost every implementation solves them with one-off Custom JavaScript that nobody maintains.
The Date category covers four jobs:
- Dayparting and time-based triggers. Fire tags only during business hours, only on weekends, only in specific hour windows. Currently solved with
new Date().getHours()in Custom JavaScript — code that lives in one place but whose rules need to change seasonally. - Timestamps for destination compliance. Meta CAPI requires
event_timein Unix seconds. Some server endpoints want milliseconds. Event deduplication between pixel and CAPI needs the same timestamp in both tags. - Duration math. Lead time from form to purchase, days since first visit, time between engagement and conversion. Feeds attribution analysis and can be sent as a Smart Bidding signal.
- Format and unit conversion. CRM pushes
“25/12/2024”, data warehouse expects“2024-12-25”, internal system uses“20241225”. Engagement time in milliseconds, GA4 wants seconds.
All four jobs have clean named-template solutions. No Custom JavaScript required for any of them.
The dataLayer date problem
Section titled “The dataLayer date problem”Dates arrive in the dataLayer — and from DOM scraping, cookies, and third-party systems — in every format except the one you want:
ISO extended
”2024-12-25”ISO basic (compact)
“20241225”European slash
”25/12/2024”US slash
”12/25/2024”Unix milliseconds
1735084800000Unix seconds
1735084800Every one of these shows up in real containers — often more than one simultaneously, because different parts of the stack (backend, CRM, analytics) standardize on different conventions. The Date category doesn’t care which you start with; there’s a variable to move between any pair.
The variables — at a glance
Section titled “The variables — at a glance”Twenty-nine variables, grouped by the job they do. The Business time group is the hero — variables that turn timestamps into segmentation, attribution, and compliance signals.
Fire tags during business hours only
Section titled “Fire tags during business hours only”Service-focused campaigns often should run only when someone is available to answer the phone. B2B lead generation during working hours, e-commerce chat triggers when support is live, remarketing tags that match when a physical store is open.
| Field | Value |
|---|---|
| Start hour (24h) | 9 |
| End hour (24h) | 18 |
| Business days | Monday-Friday |
| Timezone | browser (or specify e.g. Europe/Paris) |
true between 9:00 and 18:00 local time on weekdays; false otherwiseAdd the variable as a trigger condition with isBusinessHours equals true to gate tag firing. To fire a different tag outside business hours (e.g., a “contact us tomorrow” notice), use isBusinessHours equals false on a parallel trigger.
Timezone gotcha. By default, isBusinessHours uses the browser timezone, which means a user in Tokyo hitting a French business’s site during Paris business hours will see “closed.” If your business operates in a specific timezone and you want that perspective globally, set the timezone parameter explicitly.
Fire tags only on weekdays or weekends
Section titled “Fire tags only on weekdays or weekends”Weekend promotions, weekday-only B2B campaigns, Tuesday-specific flash sales — day-of-week targeting is one of the most common segmentation patterns in marketing.
| Field | Value |
|---|---|
| Weekend days | Saturday, Sunday (configurable for Middle East markets where Friday-Saturday) |
| Timezone | browser or explicit |
true on weekend days; false on weekdaysFor specific-day targeting, use getDayIndexFromDateString and compare to the numeric index (0 = Sunday, 1 = Monday, through 6 = Saturday). Example trigger condition: getDayIndexFromDateString equals 2 fires only on Tuesdays.
Segment by hour of day (dayparting)
Section titled “Segment by hour of day (dayparting)”Hour-of-day segmentation goes deeper than business hours — you might want a GA4 custom dimension tracking “morning / afternoon / evening / night” visitor behavior, or a specific tag that fires only during prime-time ad slots (18:00-22:00).
| Field | Value |
|---|---|
| getHourOfDay output | Integer 0-23 |
| classifyByThreshold thresholds | [6, 12, 18, 22] |
| classifyByThreshold labels | [“night”, “morning”, “afternoon”, “evening”, “late_night”] |
14 (2pm) becomes “afternoon”, ready as GA4 custom dimension valueThe classified daypart value can feed a GA4 custom dimension, a Google Ads conversion parameter, or a trigger condition. Pair with isWeekend for a combined daypart × weekday/weekend matrix.
Calculate lead time between two events
Section titled “Calculate lead time between two events”Lead time — the duration between two events for the same user — is an attribution signal that most containers don’t capture. The form submission that converts within 24 hours is a hotter lead than the one that converts after 14 days.
| Field | Value |
|---|---|
| Start timestamp | {{Cookie - lead_form_timestamp}} |
| End timestamp | {{Apply - currentTimestamp}} |
| Output unit | days (or hours, minutes) |
3.5 (or 84 in hours)The result is a number you can send as a custom parameter on the conversion event. Advanced: use the lead-time value as an input to a scoring pipeline where shorter lead time increases the conversion value sent to Smart Bidding.
Calculate days between two dates
Section titled “Calculate days between two dates””Days since first visit,” “days until campaign end,” “days since last purchase for reactivation” — all variations of the same calculation.
| Field | Value |
|---|---|
| Start date | {{Cookie - first_visit_date}} |
| End date | {{Apply - currentTimestamp}} |
Bucket the result with classifyByThreshold to produce tiered segments: “new” (0-7 days), “returning” (8-30), “dormant” (31+).
Add Unix timestamps to Meta CAPI events
Section titled “Add Unix timestamps to Meta CAPI events”Meta’s Conversions API requires event_time in Unix seconds on every event. Omit it and the event fails. Send it in milliseconds by mistake and the timestamp resolves to the year 55000-something — Meta accepts the event but its attribution is broken.
”A Unix timestamp in seconds indicating when the actual event occurred. You must send this date in GMT time zone.”
| Field | Value |
|---|---|
| currentTimestamp output | Unix ms — 1735084800000 |
| millisecondsToSeconds output | Unix s — 1735084800 |
event_time in the Meta CAPI tagFor event deduplication between the browser pixel and CAPI, both tags must send the same event_time. Reference the same variable from both, and pair with an event_id (typically from randomInteger).
Convert date formats between CRM and warehouse
Section titled “Convert date formats between CRM and warehouse”Multi-system tracking runs into a universal problem: CRM sends “25/12/2024”, data warehouse expects “2024-12-25”, analytics system stores “20241225”.
| Field | Value |
|---|---|
| Input | ”25/12/2024” (DD/MM/YYYY) |
| After reverseDateSlash | ”2024/12/25” |
| After replace /→- | “2024-12-25” |
For the simplest format swap — ISO basic to extended — basicDateToExtended is the single-variable answer: “20241225” becomes “2024-12-25” directly. Use extendedDateToBasic for the reverse.
Convert engagement milliseconds to GA4-ready units
Section titled “Convert engagement milliseconds to GA4-ready units”Browser APIs return durations in milliseconds. performance.now(), custom timing marks, video playback duration. GA4’s engagement time parameters expect seconds.
| Field | Value |
|---|---|
| Input | {{DL - engagement_ms}} — e.g. 45000 |
45 (seconds) ready for the GA4 event parameterThe unit-conversion pair set (millisecondsToSeconds, millisecondsToMinutes, millisecondsToHours, millisecondsToDays and their reverses) covers every direction. Chain toFixedNumber downstream for specific decimal precision.
Extract readable month and day names
Section titled “Extract readable month and day names”Reports read better with month and day names than numbers. “December” in a GA4 custom dimension is more useful than 12.
| Field | Value |
|---|---|
| Source | current date (default) or configurable input date |
| Locale | en-US, fr-FR, de-DE, etc. |
“December” in English, “décembre” in French, “Dezember” in GermanFor charts with limited horizontal space, use getMonthNameShort (“Dec”) and getDayNameShort (“Mon”).
Convert Unix timestamps back to readable dates
Section titled “Convert Unix timestamps back to readable dates”Cookies and backend systems frequently store timestamps as Unix numbers — but for display in GA4 custom dimensions you need a readable date.
| Field | Value |
|---|---|
| Input | {{Cookie - first_visit_ts}} — Unix seconds or ms |
| Output format | YYYY-MM-DD (ISO) or configurable |
1735084800 becomes “2024-12-25”For just the day-of-week component, use timestampToDayIndex — a fast direct path that avoids the full date conversion when you only need 0-6.
Add or subtract days from a date
Section titled “Add or subtract days from a date”Campaign end dates, subscription renewal calculations, “next available date” logic — all need date arithmetic. addDays handles forward and backward moves (negative values go back in time).
| Field | Value |
|---|---|
| Source date | {{DL - campaign_start_date}} |
| Days to add | 30 |
“2024-12-01” + 30 days = “2024-12-31”For “7 days ago from now,” use addDays with input currentTimestamp and days -7. Combine with calculateDaysDifference to build recency/frequency segmentation entirely in the container.
Composed patterns — chaining variables
Section titled “Composed patterns — chaining variables”Four chains that cover most real-world date pipelines:
Meta CAPI event_time
Current time in Unix seconds, ready for the CAPI event_time parameter.
Dayparting for GA4 custom dimension
Current hour classified into a named daypart, ready as a dimension value.
Lead-time conversion value
Lead time converted to a Smart Bidding signal where shorter = higher conversion value.
CRM-to-warehouse date normalization
European slash date converted to ISO extended format for a data warehouse export.
Why you don’t need Custom JavaScript
Section titled “Why you don’t need Custom JavaScript”Every tutorial on date handling in GTM eventually arrives at a variation of the same pattern:
function() {
var now = new Date();
var hour = now.getHours();
var day = now.getDay();
if (day === 0 || day === 6) return false;
if (hour < 9 || hour >= 18) return false;
return true;
}Or worse:
function() {
var parts = {{DLV - date_str}}.split(’/’);
var iso = parts[2] + ’-’ + parts[1] + ’-’ + parts[0];
return iso;
}Works until it doesn’t. The first breaks silently in timezone edge cases. The second breaks the day someone pushes “12-25-2024” with dashes instead of slashes. The variable name is cjs - biz_hrs and nobody remembers whether it accounts for holidays.
Named templates replace the whole pattern:
- Intent in the name.
isBusinessHoursmeans exactly one thing.cjs - biz_hrsmeans whatever the code inside happens to do. - Configuration lives in the UI. Changing business hours for daylight savings means editing a variable config, not code.
- Format handling is centralized. The day someone discovers
reverseDateSlashdoesn’t handle a new CRM format, you fix it once and every container importing it picks up the fix. - Server-side portability. sGTM’s stricter sandbox accepts named templates that ad-hoc Custom JavaScript wouldn’t.
Cheatsheet
Section titled “Cheatsheet”| Goal | Variable | Mode |
|---|---|---|
| Fire tag only during business hours | isBusinessHours | Direct |
| Fire tag only on weekends / weekdays | isWeekend | Direct |
| Extract current hour (0-23) | getHourOfDay | Direct / Apply |
| Lead time between two events | calculateLeadTime | Direct / Apply |
| Days between two dates | calculateDaysDifference | Direct / Apply |
| Current Unix timestamp (ms) | currentTimestamp | Direct / Apply |
| Add or subtract days from a date | addDays | Direct / Apply |
| Full / short day name | getDayName / getDayNameShort | Direct |
| Day name from date string input | getDayNameFromDateString | Apply |
| Numeric day index (0 = Sunday) | getDayIndexFromDateString / timestampToDayIndex | Apply |
| Full / short month name | getMonthName / getMonthNameShort | Direct |
| ISO basic ↔ extended (YYYYMMDD ↔ YYYY-MM-DD) | basicDateToExtended / extendedDateToBasic | Apply |
| Swap date component order | reverseDateSlash / reverseDateCompact* | Apply |
| Date ↔ Unix timestamp | dateToUnixTimestamp / unixTimestampToDate | Apply |
| ms ↔ seconds | millisecondsToSeconds / secondsToMilliseconds | Apply |
| ms ↔ minutes / hours / days | millisecondsToMinutes, etc. | Apply |
How do I fire a GTM tag only during business hours?
Use isBusinessHours as a trigger condition. Configure the start hour, end hour, business days, and timezone. The variable returns true when the current time falls within the defined window, false otherwise.
How do I fire a tag only on weekdays or weekends?
isWeekend returns a boolean. Use as a trigger condition with equals true for weekend-only or equals false for weekday-only tags. For specific days, use getDayIndexFromDateString and compare to the numeric index (0 = Sunday, 1 = Monday, etc.).
How do I calculate lead time between a form submission and a purchase?
Store the form submission timestamp in a cookie. On the purchase event, read the stored timestamp and pass it with currentTimestamp to calculateLeadTime. Returns the duration in days (or configurable units). Send as a custom parameter on the conversion event.
How do I add a Unix timestamp to a Meta CAPI event?
Meta CAPI requires event_time in Unix seconds. Use currentTimestamp to get milliseconds, then chain millisecondsToSeconds. For event deduplication between the browser pixel and CAPI, reference the same variable in both tags.
How do I convert date formats between systems?
reverseDateSlash, reverseDateCompactDay1st, and reverseDateCompactYear1st handle common format swaps. basicDateToExtended converts YYYYMMDD to YYYY-MM-DD; extendedDateToBasic does the reverse. Chain them to normalize dates between CRM, warehouse, and analytics.
How do I extract the day of week?
getDayName returns a full name like “Monday”. getDayNameShort returns “Mon”. getDayIndexFromDateString returns the numeric index (0 = Sunday through 6 = Saturday) for comparison logic. Use the FromDateString variants when parsing from a date string input.
Are these variables sandbox-safe in server-side GTM?
Yes. All templates run inside GTM’s sandboxed JavaScript environment using only permissioned APIs. They work in web and server containers.