Skip to content

normalizePhone β€” GTM Variable Template for String

VARIABLES β€Ί STRING
normalizePhone EXTENDED String
Direct (.tpl) Apply (.tpl)

Normalizes a phone number to E.164 format following Google Ads, Campaign Manager 360, and Meta CAPI specifications for Enhanced Conversions. Normalization steps: 1. Strip all non-digit characters (except a leading +) 2. If no country code is detected, prepend the configured default 3. Optionally remove the leading + for Meta CAPI compatibility


String Manipulation

Transform, clean, and normalize text data for consistent downstream processing.

Formatting

Normalize casing, spacing, encoding, and presentation of data values.

GA4 Ecommerce

Build and transform ecommerce data structures for GA4 event tracking.


US phone with formatting
INPUT
Phone Number: (800) 555-0200
Default Country Code: 1
OUTPUT
+18005550200
Meta CAPI mode (no plus)
INPUT
Phone Number: +1 650-555-1234
Default Country Code: 1
OUTPUT
16505551234
Non-string returns undefined
INPUT
Phone Number: undefined
OUTPUT
undefined

This is what you'll see when you open this variable in Google Tag Manager. Hover the icons for details.

normalizePhone
Phone Number
πŸ’Ύ The phone number to normalize to E.164 format.

Supported formats:
  βœ“ String
  βœ“ Number
Default Country Code
🌍 The default country code to prepend when the input does not already include one. Digits only, no + sign.

Examples: 1 (US/Canada), 44 (UK), 33 (France), 49 (Germany).

The country code is prepended only if the cleaned digits do not already start with it.
β˜‘οΈ When enabled, the output omits the leading + sign.

Google Ads / CM360: requires the + β†’ leave unchecked (default).
Meta CAPI: expects digits only β†’ check this box.
Input Setup
Input Function (optional)
βš™οΈ Optional pre-processing function applied to the input before internal logic (e.g., extract phone from an object).
Result Handling
Output Function (optional)
βš™οΈ Optional function to apply to the result before returning it (e.g., pipe into a SHA-256 hash function). Useful for chaining transformations on the output.
Phone Number number
πŸ’‘ Type any text to see the result update live
🎯 Using special value β€” click input to type instead
Test with:
Falsy
Truthy
Default Country Code number
normalizePhone()


πŸ“œ View Implementation Code
/**
* Normalizes a phone number to E.164 format for Enhanced Conversions.
*
* Follows the normalization rules required by Google Ads, Campaign Manager 360,
* and Meta CAPI before SHA-256 hashing:
* 1. Strip all non-digit characters (preserving knowledge of a leading +)
* 2. If no country code detected, prepend the configured default
* 3. Optionally omit the leading + for Meta CAPI compatibility
*
* @param {string|number} data.src - The phone number to normalize.
* @param {string} [data.cc] - Default country code (digits only, default "1").
* @param {boolean} [data.noPlus] - If true, omit the leading + (Meta CAPI mode).
* @param {Function|string} [data.out] - Optional output handler.
*
* Direct-mode specific parameters:
* @param {Function} [data.pre] - Optional pre-processor function.
*
* @returns {string|undefined} The E.164-formatted phone number, or undefined if input is invalid.
*
* @framework ggLowCodeGTMKit
*/
const makeString = require('makeString');
const normalizePhone = function(phone, countryCode, omitPlus) {
var str = makeString(phone);
if (!str || str === 'undefined' || str === 'null') { return undefined; }
var hadPlus = str.charAt(0) === '+';
var digits = '';
for (var i = 0; i < str.length; i++) {
var ch = str.charAt(i);
if (ch >= '0' && ch <= '9') {
digits += ch;
}
}
if (digits.length === 0) { return undefined; }
var cc = countryCode || '1';
var cleanCC = '';
for (var j = 0; j < cc.length; j++) {
var d = cc.charAt(j);
if (d >= '0' && d <= '9') {
cleanCC += d;
}
}
if (cleanCC.length === 0) { cleanCC = '1'; }
var fullDigits = digits;
if (!hadPlus) {
var startsWithCC = true;
if (digits.length <= cleanCC.length) {
startsWithCC = false;
} else {
for (var k = 0; k < cleanCC.length; k++) {
if (digits.charAt(k) !== cleanCC.charAt(k)) {
startsWithCC = false;
break;
}
}
}
if (!startsWithCC) {
fullDigits = cleanCC + digits;
}
}
if (omitPlus) {
return fullDigits;
}
return '+' + fullDigits;
};
const safeFunction = fn => typeof fn === 'function' ? fn : x => x;
const out = safeFunction(data.out);
// ===============================================================================
// normalizePhone - Direct mode
// ===============================================================================
const applyCast = (castFn, value) => safeFunction(castFn)(value);
const value = applyCast(data.pre, data.src);
return out(normalizePhone(value, data.cc, data.noPlus));
// ===============================================================================
// normalizePhone() – Apply Mode
// ===============================================================================
/*
return function(value) {
return out(normalizePhone(value, data.cc, data.noPlus));
};
*/
πŸ§ͺ View Test Scenarios (10 tests)
βœ… '[example] US phone with formatting'
βœ… '[example] Meta CAPI mode (no plus)'
βœ… Already has leading + and country code - preserves digits
βœ… French number without country code - prepends 33
βœ… Number already starting with country code digits - no double prepend
βœ… German number with dashes and dots
βœ… Numeric input coerced to string
βœ… '[example] Non-string returns undefined'
βœ… Empty string - returns undefined
βœ… No digits in input - returns undefined