Skip to main content

Phone Call Tracking

SendSquared provides phone call tracking capabilities that allow you to monitor and track calls from various sources such as PPC campaigns. This guide explains how to set up and use the phone flip script for call tracking.

Accessing Phone Flip Script

You can access the Phone Flip Script in the SendSquared platform by following these steps:

  1. Navigate to Global Settings
  2. Select Integration Settings
  3. Choose Phone Flip

Installing the Phone Flip Script

The phone flip script needs to be installed on your website to enable call tracking functionality. This script allows you to create campaigns and add rotating numbers in your URL to track phone calls from PPC or any other source.

Basic Installation

Copy and paste the following code into your website:

<script src="https://app-api.sendsquared.com/tracking/v1/bse-analytics-es3.js"></script>
<script src="https://app-api.sendsquared.com/phone-tracking/v1/phone-tracking.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded',async function(event){
S2CallTracking('your-uuid-here');
});
</script>

Using the Phone Flip Feature

Once installed on your website, any phone number listed in Global SettingsPhone Numbers and Campaign Settings can be used for tracking by appending a query parameter to the URL.

Security & Anti-Phishing Protection

For your protection and to prevent phishing attacks, the phone flip feature includes built-in security measures:

  • Verified Phone Numbers: Only phone numbers that are registered and verified in your SendSquared account can be displayed
  • Domain Validation: The script will only work on domains that have been pre-approved and associated with your account
  • Account Binding: Each tracking script is uniquely tied to your account UUID, preventing unauthorized use

These safeguards ensure that malicious actors cannot use your tracking infrastructure to display unauthorized phone numbers or deploy phishing campaigns using your domain reputation.

URL Parameter Format

Add the following query parameter to your URL:

?s2number=%2B16122904467

Where:

  • %2B is the URL encoding for the plus sign (+)
  • 16122904467 is the phone number in format 1 (612) 290-4467, or whichever phone number you want to display on the website

📞 Phone Tracking URL Builder

Enter a phone number and your website URL to generate a trackable link.

Enter a US phone number - +1 will be added automatically

Persistence

When a visitor arrives via a URL with the phone number parameter:

  • A cookie is installed on the client's browser
  • The phone number change will persist for up to 30 days after the initial visit

Advanced Configuration

You can customize how the phone flip script works with additional settings:

Phone Flip Generator with Custom Options

<script src="https://app-api.sendsquared.com/tracking/v1/bse-analytics-es3.js"></script>
<script src="https://app-api.sendsquared.com/phone-tracking/v1/phone-tracking.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded',async function(event){
S2CallTracking('your-uuid-here', {
classRef:'s2-phone',
pattern:'1 (###) ###-####',
sourcePattern:'/(\b1[-.\s]?)?\(?(\d{3})\)?[-.\s]?(\d{3})[-.\s]?(\d{4})\b/g',
clickToCall: true,
debugMode: false,
formContainerSelectors: 'main, #content, .content, #app'
});
});
</script>

Customization Options

You can modify the following settings:

  • CSS class (classRef:'s2-phone'): This allows you to customize the class used to find phone numbers on your webpage that will be changed.

  • Pattern (pattern:'1 (###) ###-####'): This is the format used to replace the number on your webpage.

  • Read Pattern (sourcePattern:'/(\b1[-.\s]?)?\(?(\d{3})\)?[-.\s]?(\d{3})[-.\s]?(\d{4})\b/g'): This is the regular expression pattern used to read phone numbers from the inner HTML of elements on your page.

  • Click to Call (clickToCall: true): When enabled, tracks click-to-call events separately from regular link clicks for more detailed analytics.

  • Debug Mode (debugMode: true): Enables detailed console logging for troubleshooting (see Debug Mode section below).

  • Form Container Selectors (formContainerSelectors: 'main, #content'): CSS selectors for containers where forms are likely to appear, optimizing form tracking performance.

Automatic Click-to-Call Updates

The phone tracking script automatically updates tel: links when replacing phone numbers. Both the visible text and the href attribute are kept in sync with the tracked number, ensuring click-to-call functionality works correctly on mobile devices.

🛠️ Phone Flip Customization Playground

Configure how the phone flip script finds and formats phone numbers on your website.

Configuration Options

Elements with this class will have their phone numbers replaced
How the phone number will be formatted (# = digit)
Regular expression to find phone numbers in HTML

Example HTML Transformation

<div class="contact-info">
  <p>Call us at: <span class="s2-phone">1-800-555-1234</span></p>
  <p>Support: <span class="s2-phone">(555) 123-4567</span></p>
  <div class="s2-phone">1.888.999.0000</div>
</div>
<div class="contact-info">
  <p>Call us at: <span class="s2-phone">1 (612) 290-4467</span></p>
  <p>Support: <span class="s2-phone">1 (612) 290-4467</span></p>
  <div class="s2-phone">1 (612) 290-4467</div>
</div>
When URL has ?s2number=%2B16122904467

Debug Mode

Debug mode provides detailed console logging to help you troubleshoot phone tracking implementation and monitor GA4 event tracking in real-time.

Enabling Debug Mode

S2CallTracking('your-uuid-here', {
debugMode: true // Enable detailed console logging
});

Debug Output Examples

When debug mode is enabled, you'll see color-coded console logs for different operations:

1. Initialization Output

[S2 Phone Tracking] Initialization
Configuration:
Token: ✓ Set
Class Reference: s2-phone
Click to Call: Enabled
Debug Mode: Enabled
Cookie Domain: Default
Number Pattern: 1 (###) ###-####
Environment:
Current URL: https://example.com/landing?s2number=%2B16125551234
Referrer: https://google.com
User Agent: Chrome/120.0...
Analytics Method: gtag

2. Phone Number Rotation

[S2 Phone Tracking] Rotating Phone Number
Query Parameter: %2B16125551234
Using Token: Yes
API Response: {success: true, numbers: [...]}

3. GA4 Event Tracking

[S2 Phone Tracking] GA Event: phone_number_rotated
Event Data: {
event_category: "Phone Tracking",
tracking_source: "SendSquaredPhoneFlip",
tracking_phone_number: "+16125551234",
traffic_source: "google_ads",
is_google_ads: true
}
Timestamp: 2025-01-25T10:30:45.123Z
Analytics Method: gtag
✓ GA Event Sent via gtag()

4. Form Tracking

[S2 Phone Tracking] Form Tracking Initialization
Forms Found: 3
1. contact-form
2. newsletter-signup
3. demo-request
[S2 Phone Tracking] Tracking new form: {
id: "contact-form",
className: "main-contact",
action: "/submit",
fields: 5
}

5. API Calls

[S2 Phone Tracking] API Call
Endpoint: https://app-api.sendsquared.com/v1/public/phone-list
API Key: Provided
API Success: 4 phone numbers retrieved

Common Debug Scenarios

Checking if GA4 is Available

// In browser console with debug mode on
S2CallTracking('your-uuid-here', { debugMode: true });

// Look for:
// "Analytics Method: gtag" - Direct GA4 implementation
// "Analytics Method: dataLayer" - GTM implementation
// "⚠ No GA/GTM implementation found" - No analytics detected

Verifying Form Tracking

// Enable debug mode to see all forms being tracked
S2CallTracking('your-uuid-here', {
debugMode: true,
formContainerSelectors: 'main, #app'
});

// Submit a form to see the GA4 event:
// [S2 Phone Tracking] GA Event: form_submission_with_phone_tracking
S2CallTracking('your-uuid-here', { debugMode: true });

// Check for cookie loading:
// "[S2 Phone Tracking] Loading from Cookie"
// "Cookie Data: {token: '+16125551234', trackingPhoneNumber: '+16125551234'}"

Debug Mode Best Practices

  1. Development Only: Always disable debug mode in production to avoid console clutter
  2. Browser DevTools: Use Chrome DevTools filters to show only S2 Phone Tracking logs
  3. Event Rate Limiting: Debug mode shows when events are rate-limited (1 second between same events)
  4. Error Tracking: All API errors and validation failures are logged with detailed messages

GA4 Event Tracking

SendSquared's phone tracking automatically integrates with Google Analytics 4 (GA4) to provide comprehensive tracking of all phone-related interactions. Events are sent automatically when GA4 or Google Tag Manager is detected on your page.

Automatic Event Detection

The script automatically detects your GA4 implementation method:

  1. Direct GA4 (gtag): When you have GA4 installed directly on your site
  2. Google Tag Manager (dataLayer): When using GTM to manage GA4
  3. No Analytics: Script continues to function but events aren't sent

GA4 Events Tracked

The following events are automatically tracked and sent to GA4:

Event NameDescriptionWhen FiredKey Parameters
phone_tracking_initializedScript successfully initializedPage loadhas_cookie, has_query_param, traffic_source, analytics_method
phone_number_loaded_from_cookieNumber loaded from existing cookieCookie detectedtraffic_source, is_google_ads
phone_number_rotatedNew number set from URL parameterURL parameter processedsource, traffic_source, is_google_ads
phone_number_displayedNumber successfully replaced on pageDOM updatedformatted_number, class_ref, traffic_source
form_submission_with_phone_trackingForm submitted with tracking activeForm submissionform_id, form_action, form_fields, traffic_source
phone_click_to_callClick-to-call link clickedTel link clicked (when clickToCall: true)formatted_number, element_class
phone_link_clickedPhone link clickedTel link clicked (when clickToCall: false)formatted_number, element_class
phone_rotation_errorError during number rotationAPI or validation errorerror_message, traffic_source

Event Parameters

All events include these standard parameters:

{
event_category: "Phone Tracking",
tracking_source: "SendSquaredPhoneFlip",
tracking_phone_number: "+16125551234", // or "not_set" if no number
// Plus event-specific parameters
}

Understanding Click Event Types

Both phone_click_to_call and phone_link_clicked events track clicks on tel: phone links, but serve different analytics purposes. The event fired depends solely on your clickToCall configuration setting.

When to Use Each Event Type

Use phone_click_to_call (clickToCall: true) when:

  • You consider phone link clicks as conversion events
  • You want to track high-intent user actions
  • You're running call-focused campaigns
  • You need to measure call initiation attempts for ROI calculations

Use phone_link_clicked (clickToCall: false) when:

  • You want to track general engagement metrics
  • Phone clicks are informational (users might copy the number)
  • You need to distinguish between browsing behavior and conversion intent
  • You're analyzing user interaction patterns

Implementation Examples

Example 1: E-commerce Site with Sales Focus

// Track clicks as high-intent conversion actions
S2CallTracking('your-uuid-here', {
clickToCall: true, // Fires 'phone_click_to_call' events
classRef: 's2-phone'
});

// In GA4, set up conversion tracking:
// 1. Mark 'phone_click_to_call' as a conversion event
// 2. Assign conversion value (e.g., average call value)
// 3. Use for Google Ads conversion optimization

Example 2: Service Directory with Multiple Listings

// Track clicks as engagement metrics
S2CallTracking('your-uuid-here', {
clickToCall: false, // Fires 'phone_link_clicked' events (default)
classRef: 's2-phone'
});

// In GA4, use for engagement analysis:
// 1. Track which listings get most phone interactions
// 2. Analyze user behavior flow
// 3. Don't count as conversions (users comparing options)

Example 3: Different Tracking for Different Pages

// Landing pages - track as conversions
if (window.location.pathname.includes('/landing/')) {
S2CallTracking('your-uuid-here', {
clickToCall: true, // High intent from ad traffic
debugMode: false
});
}

// Support pages - track as engagement
else if (window.location.pathname.includes('/support/')) {
S2CallTracking('your-uuid-here', {
clickToCall: false, // Users might just copy number
debugMode: false
});
}

GA4 Configuration Differences

For phone_click_to_call Events:

// GA4 Setup:
// Event name: phone_click_to_call
// Mark as: Conversion
// Use in: Google Ads conversion tracking
// Audience: High-intent users
// Typical value: $50-200 per call

For phone_link_clicked Events:

// GA4 Setup:
// Event name: phone_link_clicked
// Mark as: Engagement metric
// Use in: Behavior flow analysis
// Audience: Engaged users
// Typical value: Not assigned

Testing Your Configuration

// Enable debug mode to verify which event fires
S2CallTracking('your-uuid-here', {
clickToCall: true, // or false
debugMode: true
});

// Click a phone link and check console:
// [S2 Phone Tracking] Added click tracking: phone_click_to_call
// OR
// [S2 Phone Tracking] Added click tracking: phone_link_clicked

Important: Both events track the exact same user action (clicking a tel: link). The only difference is the event name sent to GA4, which allows you to handle them differently in your analytics and conversion tracking strategy.

Traffic Source Detection

The script automatically detects and includes traffic source information:

  • Google Ads Detection: Checks for gclid, gbraid, wbraid parameters
  • UTM Parameters: Reads utm_source when available
  • Referrer: Falls back to referrer domain or "direct"

Viewing Events in GA4

Real-Time Reports

  1. Go to GA4 → Reports → Real time
  2. Look for custom events starting with phone_
  3. Click on an event to see parameters

DebugView

  1. Enable debug mode in your script: debugMode: true
  2. Go to GA4 → Configure → DebugView
  3. See events firing in real-time with all parameters

Custom Reports

Create custom reports in GA4 to track:

  • Phone tracking conversion rate by traffic source
  • Form submissions with phone tracking
  • Click-to-call interactions by page

Example GA4 Implementation

// Basic setup with GA4 tracking
S2CallTracking('your-uuid-here', {
classRef: 's2-phone',
clickToCall: true, // Track click-to-call separately
debugMode: false // Enable for GA4 DebugView
});

// Events will automatically flow to GA4 if gtag is present

Verifying GA4 Integration

// Check if GA4 is detected (in console)
if (typeof gtag === 'function') {
console.log('✓ GA4 detected - events will be tracked');
} else if (Array.isArray(dataLayer)) {
console.log('✓ GTM detected - events will be tracked');
} else {
console.log('✗ No GA4/GTM found - events won't be sent');
}

Form Processing with GA4

SendSquared automatically tracks form submissions when phone tracking is active, providing valuable attribution data for lead generation.

How Form Tracking Works

  1. Automatic Detection: All forms on the page are automatically detected
  2. Dynamic Form Support: New forms added via JavaScript are tracked
  3. Performance Optimized: Uses MutationObserver with debouncing
  4. No Duplicate Tracking: Each form is tracked only once

Form Submission Event Data

When a form is submitted, the following data is sent to GA4:

{
event: "form_submission_with_phone_tracking",
event_category: "Phone Tracking",
form_id: "contact-form", // Form ID or class name
form_action: "/submit", // Form action URL
form_fields: "name,email,phone,message", // Comma-separated field names
tracking_phone_number: "+16125551234", // Current tracking number
traffic_source: "google_ads", // Detected traffic source
is_google_ads: true, // Google Ads detection
page_url: "https://example.com/contact",
timestamp: "2025-01-25T10:30:45.123Z"
}

Optimizing Form Detection

For better performance on sites with many dynamic elements, specify where forms typically appear:

S2CallTracking('your-uuid-here', {
formContainerSelectors: '#main-content, .form-wrapper, [data-form-container]'
});

Form Tracking Examples

Contact Form with Attribution

<form id="contact-form" action="/submit">
<input name="name" type="text" required>
<input name="email" type="email" required>
<input name="phone" type="tel">
<textarea name="message"></textarea>
<button type="submit">Submit</button>
</form>

<script>
// Form submission will trigger GA4 event with:
// - form_id: "contact-form"
// - form_fields: "name,email,phone,message"
// - tracking_phone_number: (current tracked number)
// - traffic_source: (detected source)
</script>

Dynamic Form Support

// Forms added dynamically are automatically tracked
const newForm = document.createElement('form');
newForm.id = 'dynamic-form';
newForm.innerHTML = '<input name="email"><button>Submit</button>';
document.body.appendChild(newForm);
// Automatically tracked within 100ms

Creating GA4 Conversions

To track form submissions as conversions in GA4:

  1. Go to GA4 → Configure → Events
  2. Find form_submission_with_phone_tracking
  3. Toggle "Mark as conversion"
  4. Create audiences based on traffic_source or is_google_ads parameters

Google Tag Manager vs Direct GA4 Implementation

SendSquared supports both implementation methods seamlessly:

Direct GA4 Implementation

When GA4 is installed directly on your site:

<!-- Google Analytics 4 -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXXXXXXXX');
</script>

<!-- SendSquared Phone Tracking -->
<script src="https://app-api.sendsquared.com/tracking/v1/bse-analytics-es3.js"></script>
<script src="https://app-api.sendsquared.com/phone-tracking/v1/phone-tracking.min.js"></script>
<script>
// Events sent via gtag() function
S2CallTracking('your-uuid-here');
</script>

How it works: Events are sent directly using gtag('event', eventName, parameters)

Google Tag Manager Implementation

When using GTM to manage GA4:

<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXX');</script>

<!-- SendSquared Phone Tracking -->
<script src="https://app-api.sendsquared.com/tracking/v1/bse-analytics-es3.js"></script>
<script src="https://app-api.sendsquared.com/phone-tracking/v1/phone-tracking.min.js"></script>
<script>
// Events sent via dataLayer.push()
S2CallTracking('your-uuid-here');
</script>

How it works: Events are pushed to dataLayer: dataLayer.push({event: eventName, ...parameters})

GTM Configuration for Phone Tracking Events

To capture SendSquared events in GTM:

  1. Create Custom Event Triggers:

    • Trigger Type: Custom Event
    • Event name: phone_* (regex matching)
    • Or create specific triggers for each event
  2. Create Variables for Parameters:

    Variable Name: Phone Tracking Number
    Variable Type: Data Layer Variable
    Data Layer Variable Name: tracking_phone_number
  3. Create GA4 Event Tags:

    Tag Type: Google Analytics: GA4 Event
    Event Name: {{Event}}
    Event Parameters:
    - tracking_phone_number: {{Phone Tracking Number}}
    - traffic_source: {{Traffic Source}}
    - form_id: {{Form ID}}

Comparison Table

FeatureDirect GA4Google Tag Manager
Setup ComplexitySimpleMore complex
Event ControlAutomaticFull control via GTM
Custom ParametersPre-definedFully customizable
DebuggingGA4 DebugViewGTM Preview + GA4 DebugView
Event FilteringIn GA4 onlyCan filter in GTM
PerformanceDirect sendExtra dataLayer step
FlexibilityLimitedVery flexible

Best Practices

  1. Direct GA4: Best for simple implementations where you want automatic tracking
  2. GTM: Best when you need custom logic, filtering, or integration with other tools
  3. Testing: Always use debug mode to verify events are flowing correctly
  4. Documentation: Document which events trigger which conversions for your team

Migrating from Other Platforms

Number Porting Support

All phone number porting from CallRail, Invoca, or other providers is handled by SendSquared's support team. Our team manages the entire porting process to ensure a smooth transition. Please review our comprehensive porting guide and contact support to begin.

Migrating from CallRail

SendSquared provides a complete replacement for CallRail's call tracking functionality with additional marketing automation features. Here's how to migrate:

Step 1: Export Your CallRail Data

  1. Log into CallRail and export:
    • Phone numbers list
    • Tracking sources/campaigns
    • Historical call data (CSV export)
  2. Document your current tracking setup:
    • Which numbers track which campaigns
    • Dynamic number insertion settings
    • Routing rules

Step 2: Set Up SendSquared Phone Tracking

  1. Port Your Phone Numbers

    • Contact SendSquared support team to initiate number porting
    • Our team will handle the entire porting process for you
    • See our comprehensive porting guide for details
    • Important: Do NOT disconnect your CallRail service until porting is complete
  2. Replace CallRail's JavaScript

    Remove CallRail's swap script:

    <!-- Remove this -->
    <script type="text/javascript" src="//cdn.callrail.com/companies/123456789/swap.js"></script>

    Replace with SendSquared:

    <!-- Add this -->
    <script src="https://app-api.sendsquared.com/tracking/v1/bse-analytics-es3.js"></script>
    <script src="https://app-api.sendsquared.com/phone-tracking/v1/phone-tracking.min.js"></script>
    <script>
    document.addEventListener('DOMContentLoaded',async function(event){
    S2CallTracking('your-uuid-here');
    });
    </script>
  3. Update Campaign URLs

    • CallRail format: ?callrail_number=555-1234
    • SendSquared format: ?s2number=%2B15551234
    • Update all PPC campaigns, email links, and QR codes

Step 3: Advantages After Migration

  • Unified Platform: Phone tracking + SMS + email automation in one system
  • Advanced Attribution: Multi-touch attribution across all channels
  • Built-in CRM: No need for separate CRM integration
  • Automated Follow-ups: Trigger SMS/email sequences from phone calls

Migrating from Invoca

SendSquared offers a streamlined alternative to Invoca's enterprise call tracking with simpler implementation and transparent pricing.

Step 1: Audit Your Invoca Setup

  1. Document your Invoca configuration:
    • RingPools and number pools
    • Signal AI rules and custom parameters
    • Integration webhooks
  2. Export data:
    • Phone numbers inventory
    • Campaign mappings
    • Call recordings (if needed)

Step 2: Port Numbers & Set Up SendSquared

  1. Port Your Phone Numbers

    • Contact SendSquared support team to initiate number porting from Invoca
    • Our team manages the complete porting process
    • Review our porting guide for timeline expectations
    • Critical: Keep your Invoca service active during porting
  2. Dynamic Number Pools

    Invoca RingPool equivalent:

    // Invoca approach (complex)
    Invoca.PNAPI.run('RingPool', 'UniqueID', options);

    // SendSquared approach (simple)
    S2CallTracking('your-uuid-here', {
    classRef: 's2-phone',
    pattern: '1 (###) ###-####'
    });
  3. Campaign Attribution

    • Invoca: Complex promo number mapping
    • SendSquared: Simple URL parameter (?s2number=)
    • No need for separate campaign IDs or pool management
  4. Convert Invoca Tags

    Replace Invoca's tag:

    <!-- Remove Invoca -->
    <script src="//solutions.invocacdn.com/js/invoca-latest.min.js"></script>

    <!-- Add SendSquared -->
    <script src="https://app-api.sendsquared.com/tracking/v1/bse-analytics-es3.js"></script>
    <script src="https://app-api.sendsquared.com/phone-tracking/v1/phone-tracking.min.js"></script>

Step 3: Key Improvements

  • Simpler Implementation: No complex RingPools or JavaScript APIs
  • Transparent Pricing: No hidden fees or complex pricing tiers
  • Faster Setup: Minutes vs weeks for implementation
  • All-in-One Platform: Includes SMS, email, and automation
  • No Minimum Commits: Pay for what you use, scale as needed

Migration Checklist

Pre-Migration

  • Audit current phone numbers and ownership
  • Export historical data from current platform
  • Document current tracking logic and rules
  • List all integrated systems and webhooks
  • Contact SendSquared support to initiate porting
  • Plan migration timing (low-traffic period recommended)
  • Review porting documentation

During Migration

  • Work with SendSquared support team on number porting
  • Keep existing service active until porting completes
  • Configure domain whitelist with support team
  • Install SendSquared tracking script
  • Test with demo parameters before going live
  • Update all campaign URLs with new parameters
  • Verify tracking on staging environment

Post-Migration

  • Monitor first 24 hours closely
  • Verify all numbers are swapping correctly
  • Check attribution data is flowing
  • Remove old tracking scripts
  • Cancel previous service (after confirming success)
  • Set up automated workflows for call follow-ups

Quick Comparison

FeatureCallRail/InvocaSendSquared
Setup TimeDays/WeeksMinutes
JavaScript ComplexityComplex APIsSingle function call
Number ManagementManual poolsAutomatic via URL
SMS IntegrationSeparate serviceBuilt-in
Email AutomationRequires integrationNative feature
Minimum ContractOften requiredAnnual
Attribution ModelCall-focusedOmnichannel
CRM FeaturesLimited/IntegrationFull CRM included
SupportTieredIncluded for all

Common Migration Questions

Q: Can I keep my existing tracking numbers? A: Yes, SendSquared support will handle the complete porting process for you. See our porting guide for details.

Q: How long does migration take? A: Technical implementation takes 1-2 hours. Number porting typically takes 7-10 business days but can vary by carrier. Our support team will provide timeline estimates.

Q: Will I lose historical data? A: No, export your historical data before migration. SendSquared starts fresh tracking from implementation date.

Q: Can I run both systems in parallel? A: Yes, you can test SendSquared on specific pages while keeping your existing system on others during transition.

How-To Guides & Tutorials

How to Replace Phone Numbers on Specific Pages Only

Follow these steps to control which pages display tracked phone numbers:

Step 1: Identify Target Pages

Decide which pages should show tracked numbers (e.g., landing pages, PPC-specific pages).

Step 2: Conditional Script Loading

<!-- Option 1: Load script only on specific pages -->
<!-- Add this to your landing page template only -->
<script src="https://app-api.sendsquared.com/tracking/v1/bse-analytics-es3.js"></script>
<script src="https://app-api.sendsquared.com/phone-tracking/v1/phone-tracking.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded',async function(event){
// Check if we're on a landing page
if (window.location.pathname.includes('/landing/') ||
window.location.pathname.includes('/campaign/')) {
S2CallTracking('your-uuid-here');
}
});
</script>

Step 3: Use CSS Classes for Selective Replacement

<!-- Option 2: Use specific CSS classes -->
<!-- Mark only certain phone numbers for replacement -->
<div class="track-this-phone">Call us: 1-800-555-1234</div>
<div>Support (not tracked): 1-800-555-1234</div>

<script>
document.addEventListener('DOMContentLoaded',async function(event){
S2CallTracking('your-uuid-here', {
classRef:'track-this-phone', // Only replaces numbers in elements with this class
});
});
</script>

How to Test Number Swapping with Demo Parameters

Test your phone tracking implementation without affecting live visitors:

Step 1: Set Up Test Numbers

  1. Add test phone numbers in Global SettingsPhone Numbers and Campaign Settings
  2. Example test numbers:
    • Test Line 1: +16125551111
    • Test Line 2: +16125552222

Step 2: Create Test URLs

# Production URL
https://yoursite.com/contact

# Test URL with demo parameter
https://yoursite.com/contact?s2number=%2B16125551111&test=true

# Test multiple campaigns
https://yoursite.com/landing-a?s2number=%2B16125551111
https://yoursite.com/landing-b?s2number=%2B16125552222

Step 3: Validate in Browser DevTools

  1. Open Chrome DevTools (F12)
  2. Go to Application → Cookies
  3. Look for the s2_phone cookie
  4. Verify the test number is stored
  5. Navigate to other pages to confirm persistence

Step 4: Use Console for Debugging

// Add this to your script for debug mode
document.addEventListener('DOMContentLoaded',async function(event){
const urlParams = new URLSearchParams(window.location.search);
const isTest = urlParams.get('test') === 'true';

if (isTest) {
console.log('📞 Phone Tracking Test Mode Active');
console.log('Original numbers:', document.querySelectorAll('.s2-phone'));
}

S2CallTracking('your-uuid-here');

if (isTest) {
setTimeout(() => {
console.log('Replaced numbers:', document.querySelectorAll('.s2-phone'));
}, 1000);
}
});

How to Troubleshoot When Script Isn't Firing

Systematic approach to diagnose phone tracking issues:

Step 1: Verify Script Loading

// Open browser console and check:
console.log(typeof S2CallTracking); // Should output: "function"

// If undefined, scripts aren't loading properly

Step 2: Check for JavaScript Errors

  1. Open browser console (F12)
  2. Look for red error messages
  3. Common errors:
    • "S2CallTracking is not defined" → Scripts not loaded
    • "Authentication is required" → Missing API key (x-api-key header)
    • "Origin or referer is required" → Missing origin/referer headers
    • "Invalid token or domain" → API key not recognized or domain not whitelisted

Step 3: Validate DOM Ready

// Ensure DOM is fully loaded before script runs
console.log('DOM State:', document.readyState);

// Add loading check
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', function() {
S2CallTracking('your-uuid-here');
});
} else {
// DOM already loaded
S2CallTracking('your-uuid-here');
}

Step 4: Test with Manual Trigger

// Try running manually in console
S2CallTracking('your-uuid-here', {
classRef: 'body', // Target all numbers in body
pattern: '# (###) ###-####'
});

Code Recipes & Snippets

Format Phone Numbers as (###) ###-####

// Standard US format without country code
S2CallTracking('your-uuid-here', {
pattern: '(###) ###-####',
sourcePattern: '/\\(?([0-9]{3})\\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})/g'
});

Format with Country Code: +1 (###) ###-####

// International format with US country code
S2CallTracking('your-uuid-here', {
pattern: '+1 (###) ###-####',
sourcePattern: '/(\\+?1[-. ]?)?\\(?([0-9]{3})\\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})/g'
});
// Target footer phone numbers exclusively
S2CallTracking('your-uuid-here', {
classRef: 'footer-phone', // Add this class to footer phone elements
});

// Alternative: Use querySelector approach
document.addEventListener('DOMContentLoaded', function() {
// First run normal tracking
S2CallTracking('your-uuid-here', {
classRef: 'hidden-element-that-doesnt-exist' // Disable default
});

// Then target footer specifically
const footerPhones = document.querySelectorAll('footer .phone-number');
footerPhones.forEach(el => {
el.classList.add('s2-phone');
});

// Re-run on footer elements
S2CallTracking('your-uuid-here');
});

Replace Numbers in Multiple Sections

// Target header, footer, and sidebar
S2CallTracking('your-uuid-here', {
classRef: 'trackable-phone'
});

// Add class to multiple sections
document.querySelectorAll('header .phone, footer .phone, .sidebar .phone')
.forEach(el => el.classList.add('trackable-phone'));

Fallback Number if Parameter Missing

// Provide default number when no URL parameter exists
document.addEventListener('DOMContentLoaded', function() {
const urlParams = new URLSearchParams(window.location.search);
let phoneParam = urlParams.get('s2number');

// If no parameter, add default
if (!phoneParam) {
const defaultNumber = '+16125550000'; // Your default tracking number
const newUrl = new URL(window.location);
newUrl.searchParams.set('s2number', defaultNumber);

// Optional: Update URL without reload
history.replaceState({}, '', newUrl);
}

S2CallTracking('your-uuid-here');
});

Different Numbers for Mobile vs Desktop

// Show different numbers based on device
document.addEventListener('DOMContentLoaded', function() {
const isMobile = window.matchMedia('(max-width: 768px)').matches;
const urlParams = new URLSearchParams(window.location.search);

// Override parameter for mobile users
if (isMobile && !urlParams.get('mobile_override')) {
const mobileNumber = '+16125559999'; // Mobile-specific number
urlParams.set('s2number', mobileNumber);
urlParams.set('mobile_override', 'true');

const newUrl = new URL(window.location);
newUrl.search = urlParams.toString();
history.replaceState({}, '', newUrl);
}

S2CallTracking('your-uuid-here');
});

Test in Staging vs Production

// Environment-specific configuration
const config = {
staging: {
uuid: 'staging-uuid-here',
testNumbers: ['+16125551111', '+16125552222'],
debug: true
},
production: {
uuid: 'production-uuid-here',
testNumbers: [],
debug: false
}
};

const env = window.location.hostname.includes('staging') ? 'staging' : 'production';
const settings = config[env];

if (settings.debug) {
console.log('🔧 Phone Tracking Environment:', env);
}

S2CallTracking(settings.uuid, {
debug: settings.debug
});

Conceptual Overview

How SendSquared Phone Tracking Works Under the Hood

The Architecture

SendSquared's phone tracking system operates through a sophisticated client-side JavaScript implementation that ensures security while providing flexibility:

  1. UUID Authentication

    • Each account receives a unique UUID during setup
    • This UUID is cryptographically tied to your account
    • The tracking script validates the UUID against SendSquared's servers
    • Invalid UUIDs are rejected, preventing unauthorized usage
  2. Domain Validation Process

Client BrowserLoads ScriptSends UUID +DomainSendSquared APIValidates against whitelistReturns: Authorized/DeniedResponse flow
  1. Number Replacement Flow
    • Script scans DOM for elements matching the specified class/pattern
    • Extracts phone numbers using RegEx pattern matching
    • Checks URL parameters for replacement number
    • Validates replacement number against account's approved numbers
    • Replaces numbers in DOM if all validations pass
    • Stores preference in cookie for persistence

Security & Anti-Spoofing Measures

Why Spoofing is Prevented:

  1. Three-Layer Validation

    • Layer 1: UUID must match an active SendSquared account
    • Layer 2: Domain must be pre-registered for that UUID
    • Layer 3: Phone number must be verified in account settings
  2. Request Validation

    // Simplified representation of validation flow
    Request: {
    uuid: 'abc-123',
    domain: 'example.com',
    number: '+16125551234'
    }
    // Server validates uuid + domain combination
  3. Rate Limiting

    • API calls are rate-limited per UUID
    • Suspicious patterns trigger automatic blocking
    • Failed validation attempts are logged

How SendSquared Chooses Which Number to Show

Decision Tree Logic

Page LoadCheck URL for s2number parameterParameter exists?YESNOValidate numberCheck for cookieValid?Cookie exists?YESNOYESNOUse parameter+ Set cookieShow originalnumberUse cookienumberShow originalnumber
  1. Initial Visit with Parameter

    • User arrives via ?s2number=%2B16125551234
    • Cookie set: s2_phone=+16125551234
    • Expiry: 30 days from creation
    • Domain: Current domain and subdomains
  2. Subsequent Visits

    • No URL parameter needed
    • Script reads cookie value
    • Continues showing tracked number
    • Cookie expiry extends on each visit
  3. Parameter Override

    • New parameter overrides existing cookie
    • Cookie updated with new number
    • Useful for A/B testing different numbers

Invalid Number Handling

When an invalid number is passed:

  1. Validation Fails: Number not in approved list
  2. Fallback: Original page numbers remain unchanged
  3. Logging: Failed attempt logged for security monitoring
  4. No Cookie: Invalid numbers are never stored
  5. Console Warning: Debug message if debug mode enabled

Troubleshooting Playbook

Phone Number Not Swapping

Diagnostic Steps

  1. Check Class Reference

    // In browser console:
    document.querySelectorAll('.s2-phone').length
    // Should return > 0 if elements exist

    // Check your configuration:
    console.log('Looking for class:', 'your-class-here');
  2. Verify RegEx Pattern

    // Test your pattern:
    const testNumbers = [
    '(612) 555-1234',
    '612-555-1234',
    '6125551234',
    '+1 612 555 1234'
    ];

    const pattern = /(\b1[-.\s]?)?\(?([0-9]{3})\)?[-.\s]?([0-9]{3})[-.\s]?([0-9]{4})\b/g;

    testNumbers.forEach(num => {
    console.log(`${num}: ${pattern.test(num)}`);
    });
  3. Domain Validation Check

    // Verify domain is authorized:
    console.log('Current domain:', window.location.hostname);
    console.log('Protocol:', window.location.protocol);

    // Should be https:// for production
  4. Number Format in URL

    // Check URL encoding:
    const urlParams = new URLSearchParams(window.location.search);
    console.log('Raw parameter:', urlParams.get('s2number'));
    console.log('Decoded:', decodeURIComponent(urlParams.get('s2number') || ''));

Wrong Format Showing

Pattern Value Issues

  1. Diagnosis

    // Current configuration test:
    const currentPattern = '1 (###) ###-####';
    const testNumber = '6125551234';

    // Check what format is being applied:
    console.log('Input:', testNumber);
    console.log('Pattern:', currentPattern);
    console.log('Expected: 1 (612) 555-1234');
  2. Common Pattern Fixes

    // Problem: Extra spaces
    pattern: '1(###)###-####' // ❌ No spaces
    pattern: '1 (###) ###-####' // ✅ Correct spacing

    // Problem: Wrong placeholder
    pattern: '1 (XXX) XXX-XXXX' // ❌ Wrong placeholder
    pattern: '1 (###) ###-####' // ✅ Use # for digits

Script Not Firing

Browser Console Checks

  1. Check Script Loading Order

    <!-- ✅ Correct order -->
    <script src=".../bse-analytics-es3.js"></script>
    <script src=".../phone-tracking.min.js"></script>
    <script>S2CallTracking('uuid');</script>

    <!-- ❌ Wrong order -->
    <script>S2CallTracking('uuid');</script>
    <script src=".../phone-tracking.min.js"></script>
  2. Content Security Policy

    // Check for CSP errors:
    // Look for: "Refused to load script... Content Security Policy"

    // Fix: Add to CSP header
    Content-Security-Policy: script-src 'self' https://app-api.sendsquared.com;
  3. Ad Blockers

    // Test if tracking script is blocked:
    if (typeof S2CallTracking === 'undefined') {
    console.warn('Phone tracking may be blocked by ad blocker');
    // Implement fallback or notify user
    }
  1. Check Cookie Settings

    // Debug cookie storage:
    document.cookie.split(';').forEach(cookie => {
    if (cookie.includes('s2_phone')) {
    console.log('Found:', cookie);
    }
    });
  2. Browser Privacy Mode

    • Incognito/Private mode may block cookies
    • Some browsers block third-party cookies by default
    • Test in regular browser session
  3. Cross-Domain Issues

    // Ensure cookie domain matches:
    console.log('Cookie domain should be:', window.location.hostname);

Integration Best Practices

PPC Campaign Integration

  1. ValueTrack Parameters

    Final URL: https://yoursite.com/landing

    URL options: {lpurl}?s2number=%2B16125551234&utm_source=google&utm_medium=cpc&utm_campaign={campaignid}
  2. Campaign-Specific Numbers

    Campaign A: ?s2number=%2B16125551111
    Campaign B: ?s2number=%2B16125552222
    Campaign C: ?s2number=%2B16125553333
  3. Dynamic Number Insertion

    // Map campaigns to numbers
    const campaignNumbers = {
    'brand': '+16125551111',
    'competitor': '+16125552222',
    'generic': '+16125553333'
    };

    const urlParams = new URLSearchParams(window.location.search);
    const campaign = urlParams.get('utm_campaign');

    if (campaign && campaignNumbers[campaign]) {
    urlParams.set('s2number', campaignNumbers[campaign]);
    history.replaceState({}, '', `${window.location.pathname}?${urlParams}`);
    }

Facebook Ads Integration

// Facebook Pixel + Phone Tracking
fbq('track', 'PageView');

// After phone number replacement
S2CallTracking('your-uuid-here');

// Track phone number views
setTimeout(() => {
const displayedNumber = document.querySelector('.s2-phone')?.textContent;
if (displayedNumber) {
fbq('trackCustom', 'PhoneNumberViewed', {
number: displayedNumber,
source: 'SendSquared'
});
}
}, 1000);

Google Tag Manager Integration

  1. Create Custom HTML Tag

    <script>
    (function() {
    var script1 = document.createElement('script');
    script1.src = 'https://app-api.sendsquared.com/tracking/v1/bse-analytics-es3.js';
    document.head.appendChild(script1);

    var script2 = document.createElement('script');
    script2.src = 'https://app-api.sendsquared.com/phone-tracking/v1/phone-tracking.min.js';
    document.head.appendChild(script2);

    script2.onload = function() {
    S2CallTracking('{{SendSquared UUID}}');

    // Push event to dataLayer
    window.dataLayer.push({
    'event': 'phoneTrackingLoaded',
    'phoneNumber': new URLSearchParams(window.location.search).get('s2number')
    });
    };
    })();
    </script>
  2. Create Variable for UUID

    • Name: SendSquared UUID
    • Type: Constant
    • Value: Your UUID
  3. Set Trigger

    • Trigger Type: Page View
    • Some Page Views
    • Page Path contains /landing/

WordPress Integration

// Add to functions.php or custom plugin
function add_sendsquared_phone_tracking() {
// Only on specific pages
if (is_page(['contact', 'landing-page', 'services'])) {
?>
<script src="https://app-api.sendsquared.com/tracking/v1/bse-analytics-es3.js"></script>
<script src="https://app-api.sendsquared.com/phone-tracking/v1/phone-tracking.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
S2CallTracking('<?php echo get_option('sendsquared_uuid'); ?>');
});
</script>
<?php
}
}
add_action('wp_footer', 'add_sendsquared_phone_tracking');

// Add settings page for UUID
function sendsquared_settings_page() {
add_options_page(
'SendSquared Settings',
'SendSquared',
'manage_options',
'sendsquared',
'sendsquared_settings_html'
);
}
add_action('admin_menu', 'sendsquared_settings_page');

For Developers

JavaScript API Reference

Core Function

/**
* Initialize SendSquared phone tracking
* @param {string} token - Your SendSquared public token/UUID
* @param {Object} options - Configuration options
* @param {string} options.classRef - CSS class to target (default: null, targets all numbers)
* @param {boolean} options.cookieDomain - Use domain-wide cookie (default: false)
* @param {string} options.pattern - Output format pattern (default: '1.###.###.####')
* @param {boolean} options.clickToCall - Enable click-to-call updates (default: false)
* @param {RegExp} options.sourcePattern - RegEx to match phone numbers (default: /(\b1[-.\s]?)?\(?(\d{3})\)?[-.\s]?(\d{3})[-.\s]?(\d{4})\b/g)
*/
S2CallTracking(token, options = {})

Helper Functions

// Get current tracked number
function getTrackedNumber() {
const cookies = document.cookie.split(';');
for (let cookie of cookies) {
if (cookie.trim().startsWith('s2_phone=')) {
return cookie.split('=')[1];
}
}
return null;
}

// Check if tracking is active
function isTrackingActive() {
return document.cookie.includes('s2_phone=');
}

// Clear tracking cookie
function clearTracking() {
document.cookie = 's2_phone=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
}

// Force number update
function updateTrackingNumber(newNumber) {
const encoded = encodeURIComponent(newNumber);
const url = new URL(window.location);
url.searchParams.set('s2number', encoded);
window.location.href = url.toString();
}

Event Listeners

// Listen for tracking completion
window.addEventListener('s2:trackingComplete', function(e) {
console.log('Tracking completed:', e.detail);
// e.detail contains: { originalNumber, newNumber, elementsChanged }
});

// Listen for tracking errors
window.addEventListener('s2:trackingError', function(e) {
console.error('Tracking error:', e.detail);
// e.detail contains: { error, message, uuid }
});

Error Codes Reference

Error MessageCauseSolution
Authentication is requiredMissing x-api-key header or no headers at allEnsure UUID/public token is passed correctly in script initialization
Origin or referer is requiredMissing origin and referer headersScript must be loaded from a valid domain (not file:// or localhost without proper headers)
Invalid token or domainAPI key not found or domain not whitelisted1. Verify UUID/public token is correct. 2. Ensure domain is added to approved domains in SendSquared settings
S2CallTracking is not definedScripts not loaded properlyCheck script loading order and network connectivity
Rate limit exceededToo many API callsImplement caching or contact support for limit increase
Invalid phone formatPhone number format not recognizedEnsure number includes country code (e.g., +16125551234)
Cookie storage failedBrowser blocking cookiesCheck browser privacy settings and cookie permissions

Browser Compatibility

BrowserMinimum VersionNotes
Chrome60+Full support
Firefox55+Full support
Safari12+Full support
Edge79+Full support
IE11*Limited support with ES3 transpilation**

Note on IE11 Support:

  • The tracking script includes a polyfill for requestIdleCallback specifically for IE11 and Safari
  • The script is transpiled to ES3 for broader compatibility
  • Features like WeakSet and MutationObserver require IE11 (not available in IE9-10)
  • For older IE versions, consider implementing a server-side fallback

Performance Considerations

// Optimize for performance
S2CallTracking('your-uuid-here', {
// Limit scope to reduce DOM traversal
classRef: 'phone-tracking-enabled',

// Use efficient RegEx for faster pattern matching
sourcePattern: /\d{10}/g // Simple pattern for 10-digit numbers
});

// Lazy load for below-the-fold content
if ('IntersectionObserver' in window) {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
S2CallTracking('your-uuid-here');
observer.disconnect();
}
});
});

observer.observe(document.querySelector('.footer'));
}

Testing Suite Integration

// Jest/Mocha test example
describe('SendSquared Phone Tracking', () => {
beforeEach(() => {
// Mock the S2CallTracking function
window.S2CallTracking = jest.fn().mockResolvedValue(true);
});

test('should initialize with correct UUID', async () => {
await initPhoneTracking();
expect(window.S2CallTracking).toHaveBeenCalledWith('test-uuid-123');
});

test('should replace phone numbers', async () => {
document.body.innerHTML = '<div class="s2-phone">555-1234</div>';
await window.S2CallTracking('test-uuid');

const phone = document.querySelector('.s2-phone');
expect(phone.textContent).toMatch(/\d{3}-\d{4}/);
});
});