# Get Started

Ring Tonic is a modern **AI-Powered Call Tracking & Analytics** platform that helps businesses understand which marketing efforts drive phone calls, automatically qualify leads, and extract valuable insights from every conversation—without the traditional 400-500% markup competitors charge.

<div data-full-width="true" data-with-frame="true"><figure><img src="/files/n3rvDBbc6630j7eopBWi" alt=""><figcaption><p>Ring Tomnic - Call Activity Analytics</p></figcaption></figure></div>

### 🚀 What Ring Tonic Does

**Call Tracking & Attribution**

* Track which campaigns, ads, and sources generate phone calls
* Website Tracker with dynamic number insertion and form attribution
* Form submission capture as leads, even when the customer's backend fails ([Agency plan](/guides/form-submissions))
* Unlimited tracking numbers and campaigns (no artificial limits)

**Lightweight CRM**

* [Pipeline view](/guides/contacts) with stages: New → Contacted → Form Submitted → Qualified → Appointment Booked → Proposal Sent → Won / Lost
* Auto-advance from calls and form submissions; manual drag-and-drop in Kanban
* Workspace-defined custom fields (string, number, date, select, boolean, URL)
* [Postback API](/guides/crm-api) for external systems (Calendly, HubSpot, Zapier)

**AI-Powered Intelligence**

* Automatic call transcription with speaker identification
* Sentiment analysis to identify happy or frustrated customers
* Keyword extraction to spot buying signals and urgency
* Automatic lead qualification with customizable criteria
* Deal value estimation based on your pricing catalog

**Cost Transparency**

* Bring Your Own Twilio account (pay wholesale rates directly)
* No hidden overage fees or marked-up minutes
* Complete visibility into your actual costs

**Multi-Workspace Architecture**

* Agencies: Create unlimited separate workspaces for each client
* Complete data isolation between workspaces
* Team collaboration with role-based permissions

### 📋 Quick Start Guide

#### 1. Register an Account

Visit [ringtonic.app](https://ringtonic.app/) and create your account in under 2 minutes.

#### 2. Subscribe to a Plan

Choose the plan that fits your needs:

| Indie                                    | Agency                                         |
| ---------------------------------------- | ---------------------------------------------- |
| 1 workspace                              | Unlimited workspaces                           |
| Unlimited tracking numbers and campaigns | Team collaboration with role-based permissions |
| 6 months data retention                  | White-label reporting                          |
| All AI features included                 | 12 months data retention                       |
|                                          | API & Webhook (Soon)                           |
|                                          | All AI features included                       |

{% hint style="info" %}
See [pricing details](https://ringtonic.app/#pricing) for current rates.
{% endhint %}

#### 3. Set Up Your Workspace

After subscribing, you'll set up your workspace by connecting a few API services. Here's what you need:

{% tabs fullWidth="false" %}
{% tab title="Required: Twilio (Call Tracking & Recording)" %}
**What it does:** Twilio powers your phone numbers, routes calls, and provides call recordings.

**Setup time:** \~5 minutes

**Cost:** \~$1.15/month per number + \~$0.0085/minute for calls

**How to set up:**

1. Create a free Twilio account at [twilio.com](https://www.twilio.com/try-twilio)
2. Get your Account SID and Auth Token from the Twilio Console
3. Paste them into Ring Tonic workspace settings (Basic tab)

{% hint style="info" %}
[📖 Full Twilio setup guide](https://help.ringtonic.app/pages/crg7tMxXMDacQLAiSpgl#id-1.-set-up-twilio-for-tracking-calls)
{% endhint %}
{% endtab %}

{% tab title="Recommended: Transcription" %}
**What it does:** Converts call recordings into searchable text with speaker identification (Agent vs Customer).

**Setup time:** \~3 minutes

**Cost:** \~$0.00065-$0.0043/minute (depending on provider)

**Providers:** Choose one

* **AssemblyAI** (Recommended) - Best accuracy, great for noisy environments
* **Deepgram** - 10x faster processing, ideal for high-volume call centers

**How to set up:**

1. Create account with AssemblyAI or Deepgram
2. Get your API key
3. Paste it into Ring Tonic workspace settings (Transcription tab)
4. Enable "Automatically transcribe call recordings"

{% hint style="info" %}
[📖 Full transcription setup guide](https://help.ringtonic.app/pages/crg7tMxXMDacQLAiSpgl#id-2.-set-up-call-transcription-and-sentiment-analysis)
{% endhint %}
{% endtab %}

{% tab title="Nice to Have: AI Automation & Sentiment" %}
**AI Automation (Smart Lead Qualification)**

**What it does:**

* Extracts keywords that indicate buying intent
* Automatically qualifies leads based on conversation content
* Estimates deal values using your pricing catalog
* Tags calls for easy filtering ("Ready to Buy", "Urgent", etc.)

**Setup time:** \~3 minutes

**Cost:** \~$0.003-$0.005 per call analyzed

**Requirements:** OpenAI API key

**How to set up:**

1. Create an OpenAI account at [platform.openai.com](https://platform.openai.com/signup)
2. Generate an API key
3. Paste it into Ring Tonic workspace settings (AI Automation tab)
4. Enable "Automatically analyze keywords" and "Automatically estimate deal value"

{% hint style="info" %}
[📖 Full AI automation setup guide](https://help.ringtonic.app/pages/crg7tMxXMDacQLAiSpgl#id-3.-set-up-ai-automation-with-openai)
{% endhint %}

***

**Sentiment Analysis (Customer Satisfaction Tracking)**

**What it does:** Analyzes emotional tone of conversations to identify positive, neutral, or negative calls.

**Setup time:** \~5 minutes

**Cost:**

* $300 free credits for new Google Cloud users
* First \~500-1,000 calls/month: Free
* After: \~$0-5 per 1,000 calls (depending on call length)

**Requirements:** Google Cloud Natural Language API key

**How to set up:**

1. Create a Google Cloud account
2. Enable the Natural Language API
3. Generate an API key
4. Paste it into Ring Tonic workspace settings (Transcription tab, Sentiment Analysis section)

📖 [Full sentiment analysis setup guide](https://github.com/phuclh/ringtonic-help/blob/main/setup-workspace.md#set-up-google-natural-language-api-for-sentiment-analysis-optional)
{% endtab %}
{% endtabs %}

### 📚 Documentation

* [Setup Workspace](/guides/setup-workspace) - Complete workspace configuration guide
* [Products & Services](/guides/products-and-services) - Configure pricing catalog for deal value estimation

### 💰 Pricing Breakdown

With Ring Tonic's Bring Your Own Key (BYOK) model, you only pay for what you use:

**Ring Tonic Platform Fee:**

* Indie: See current pricing at [ringtonic.app](https://ringtonic.app/#pricing)
* Agency: See current pricing at [ringtonic.app](https://ringtonic.app/#pricing)

**Twilio (Required):**

* \~$1.15/month per tracking number
* \~$0.0085/minute for incoming calls

**AssemblyAI Transcription (Optional):**

* \~$0.00065/minute
* $50 free credits to start

**OpenAI AI Analysis (Optional):**

* \~$0.003-$0.005 per analyzed call
* Free credits available for new accounts

**Google NLP Sentiment (Optional):**

* $300 free credits for new Google Cloud users
* First \~500-1,000 calls/month: Free
* After: \~$0-5 per 1,000 calls (depending on call length)

{% hint style="success" %}
**Example Total Cost:** 10 tracking numbers + 1,000 minutes/month with all features = \~$30-35/month total (including Ring Tonic subscription).

Compare to competitors charging $200-500/month for the same usage. 💰
{% endhint %}

### 🆚 Why Ring Tonic?

**Traditional Call Tracking Platforms:**

* Pay $200-500/month for 10 numbers and 1,000 minutes
* Hidden overage fees and per-minute charges
* Black box pricing with 400-500% markup
* Limited AI features or expensive add-ons

**Ring Tonic:**

* Pay \~$30-35/month for same usage with all AI features
* Complete cost transparency
* Wholesale rates from Twilio (no markup)
* State-of-the-art AI from OpenAI and Google

### 🔒 Security

* All API keys encrypted at rest using AES-256 encryption
* Keys never shared with third parties
* Only used to make authorized API calls on your behalf
* Full data isolation between workspaces

### 📞 Support

Questions? Please post them on [Ring Tonic's Facebook Group](https://www.facebook.com/groups/ringtonic).

***

**Ready to get started?** [Sign up now](https://ringtonic.app/register) and set up your first workspace in under 15 minutes.


# Setup Workspace

### What is a workspace?

A workspace is an isolated environment for managing a single business or client. Each workspace has its own dedicated tracking numbers, campaigns, call logs, team members, and analytics reports. This separation is essential for agencies that need to keep client data completely private and organized. Think of it like having multiple separate accounts, but managed from one convenient dashboard.

{% hint style="info" %}
When you create an account, Ring Tonic automatically sets up a default workspace for you.
{% endhint %}

Here are a few quick steps to get your new workspace ready:

### 1. Set up Twilio for Tracking Calls

Ring Tonic uses Twilio to provision phone numbers and track calls. To get started, create a Twilio account and connect it to your workspace using your Account SID and Auth Token. This lets Ring Tonic search for numbers, purchase tracking lines, and log incoming calls on your behalf.

#### How to Get Your Twilio Credentials

**Step 1: Create a Twilio Account**

1. Go to <https://www.twilio.com/try-twilio>
2. Fill out the registration form with your information
3. Verify your email address and phone number
4. Complete the onboarding process

{% hint style="info" %}
Twilio offers a free trial with credits to get started. You can test Ring Tonic's features before committing to a paid plan.
{% endhint %}

{% hint style="warning" %}
**Important:** During Twilio account setup, if asked about your account type or business model, select **"Direct"** (not ISV/reseller). Since you own the account and the API keys, Twilio considers you a direct customer. 'ISV' is a specific status for software platforms (like Ring Tonic) that resell connectivity. Choosing Direct makes your account verification and SMS registration much simpler!
{% endhint %}

**Step 2: Find Your Account SID and Auth Token**

Once you're logged into Twilio:

1. Navigate to the [Twilio Console](https://console.twilio.com)
2. You'll see your **Account SID** and **Auth Token** displayed under the Account Info section
3. The Account SID starts with "AC" followed by 32 characters
4. Click "Show" next to the Auth Token to reveal it

<figure><img src="/files/t3WlHyZOBYQ1EEQPAzcr" alt=""><figcaption><p>Your Account SID and Auth Token are displayed on the Twilio Console dashboard</p></figcaption></figure>

{% hint style="warning" %}
**Important:** Your Auth Token is sensitive information. Never share it publicly or commit it to version control. Ring Tonic encrypts and stores these credentials securely.
{% endhint %}

**Step 3: Add Credentials to Your Workspace**

1. In Ring Tonic, navigate to your workspace settings
2. Scroll down to the **Twilio Credentials** section
3. Paste your **Account SID** into the "Account SID" field
4. Paste your **Auth Token** into the "Auth Token" field
5. Click "Save" or "Update Workspace" to save your credentials

<figure><img src="/files/mwGDisJTCZWQQJARdl3i" alt=""><figcaption><p>Enter your Twilio credentials in the workspace settings</p></figcaption></figure>

Once saved, Ring Tonic will be able to:

* Search for available phone numbers in your desired area codes
* Purchase tracking numbers on your behalf
* Receive and log incoming calls
* Provide call recordings and metadata

{% hint style="success" %}
**What's Next?** After connecting Twilio, you can start creating campaigns and purchasing tracking numbers.
{% endhint %}

### 2. Call Control — Disable Calls for a Workspace (Agency Plan)

{% hint style="info" %}
This feature is available exclusively on the **Agency plan**. If you're on the Indie plan, you'll see the toggle but will be prompted to upgrade when you try to use it.
{% endhint %}

If you manage multiple workspaces for different clients, there may be times when you need to temporarily disable all calling for a specific workspace—for example, if a client stops paying or requests a pause on their campaigns. The **Call Control** toggle gives you a single master switch to turn off all inbound and outbound calls for a workspace instantly.

When calling is disabled:

* **Inbound calls** to all tracking numbers in the workspace are rejected (callers hear a busy signal or a custom message you define)
* **Outbound dialer** is hidden and blocked for all team members in the workspace
* **No call logs** are created for rejected inbound calls, so your analytics stay clean

#### How to Disable Calls

1. Navigate to your workspace settings
2. Scroll down to the **Call Control** section (below Twilio Credentials)
3. Toggle **"Calling Enabled"** off

<figure><img src="/files/FKj9BV6YfPdKABUcq3Ph" alt=""><figcaption><p>The Call Control toggle in workspace settings</p></figcaption></figure>

#### Choosing a Rejection Method

When you disable calls, you can choose what callers hear when they dial one of your tracking numbers:

| Method             | What Callers Hear                           | Twilio Cost      | Best For                                                                               |
| ------------------ | ------------------------------------------- | ---------------- | -------------------------------------------------------------------------------------- |
| **Busy Signal**    | A standard busy tone, then the call ends    | $0 (no charge)   | Temporary suspensions where you don't want to reveal any details                       |
| **Custom Message** | Your custom message, then the call hangs up | \~$0.01 per call | Professional communication, letting callers know the number is temporarily unavailable |

**To configure the rejection method:**

1. After toggling calls off, select either **"Busy Signal"** or **"Custom Message"**
2. If you chose **Custom Message**, enter your message in the text field (up to 500 characters)
3. Click **"Save"** or **"Update Workspace"**

**Example custom messages:**

* "The number you have called is temporarily unavailable. Please try again later."
* "This line is currently not accepting calls. Please contact us at our main office number."
* "Service for this account has been temporarily suspended. Please contact your account manager."

{% hint style="warning" %}
**Important:** When calls are disabled, ALL inbound calls to every tracking number in the workspace will be rejected, and the outbound dialer will be completely hidden. Make sure this is what you intend before saving.
{% endhint %}

#### Re-enabling Calls

To restore calling, simply toggle **"Calling Enabled"** back on and save. All inbound call tracking and the outbound dialer will resume immediately—no need to reconfigure anything.

#### Per-Number Call Control

Need more granular control? Instead of disabling an entire workspace, you can disable calling for **individual phone numbers**. This is useful when you want to suspend just one line while keeping the rest of the workspace active.

Per-number call control is managed from the **Phone Numbers** page. See the [Phone Numbers guide](/guides/phone-numbers#per-number-call-control-agency-plan) for full details.

### 3. Set up Call Transcription & Sentiment Analysis

Call transcription turns recorded conversations into searchable text, making it easy to find calls, analyze patterns, and spot keywords without replaying full recordings.

<figure><img src="/files/QvJoQXSOSOAJiQY4JJCu" alt=""><figcaption><p>Transcription with AssemblyAI</p></figcaption></figure>

Ring Tonic supports Deepgram and AssemblyAI—both offer automatic transcription with speaker identification, but differ in speed, accuracy, and pricing.

{% hint style="info" %}
**Don't know which provider to choose?** We recommend **AssemblyAI** for most users. It provides the best accuracy with 30% improvement in noisy environments, making it ideal for phone call transcription where audio quality can vary.
{% endhint %}

#### Choosing a Transcription Provider

Ring Tonic integrates with two powerful transcription providers. Here's how they compare:

| Feature                 | Deepgram                                   | AssemblyAI                                       |
| ----------------------- | ------------------------------------------ | ------------------------------------------------ |
| **Processing Speed**    | 10x faster than real-time                  | Standard processing                              |
| **Accuracy**            | Excellent                                  | Best-in-class (30% better in noisy environments) |
| **Speaker Diarization** | Up to 100,000+ speakers                    | Up to 50 speakers                                |
| **Language Support**    | 30+ languages                              | 100+ languages                                   |
| **Best For**            | High-volume call centers, batch processing | Maximum accuracy, challenging audio conditions   |
| **Pricing**             | \~$0.0043/minute                           | \~$0.00065/minute                                |

{% tabs %}
{% tab title="AssemblyAI" %}
**How to Set Up AssemblyAI**

**Step 1: Create an AssemblyAI Account**

1. Visit <https://www.assemblyai.com/app/signup>
2. Sign up for a new account
3. Verify your email address
4. Complete the onboarding questionnaire

{% hint style="info" %}
AssemblyAI provides $50 free credits to get started, allowing you to test their transcription quality with your actual call recordings.
{% endhint %}

**Step 2: Get Your AssemblyAI API Key**

1. After logging in, you'll be taken to the AssemblyAI Dashboard
2. Your API key is displayed prominently on the dashboard homepage
3. Click "Copy" to copy your API key to your clipboard
4. Alternatively, you can access your API key at any time from the [API Keys page](https://assemblyai.com/dashboard/api-keys)

<figure><img src="/files/R4Gw4YYnjoCJaVv6OIkM" alt=""><figcaption><p>Your AssemblyAI API key is shown on the dashboard</p></figcaption></figure>

**Step 3: Add AssemblyAI Credentials to Your Workspace**

1. In Ring Tonic, navigate to your workspace settings
2. Go to the **Transcription** tab
3. Select **AssemblyAI** as your transcription provider
4. Paste your API key into the "AssemblyAI API Key" field
5. Enable "Automatically transcribe call recordings" if you want transcriptions to run after every call
6. Enable "Enable speaker diarization" to identify different speakers (Agent vs Customer)
7. Optionally select a language, or leave it on "Auto-detect" for automatic language detection
8. Click "Save" or "Update Workspace"

<figure><img src="/files/mFbGhpqwM0wP8Vkuk6TI" alt=""><figcaption><p>Configure AssemblyAI in your workspace transcription settings</p></figcaption></figure>
{% endtab %}

{% tab title="Deepgram" %}
**How to Set Up Deepgram**

**Step 1: Create a Deepgram Account**

1. Visit <https://console.deepgram.com>
2. Sign up for a new account
3. Verify your email address
4. Complete the onboarding process

{% hint style="info" %}
Deepgram offers $200 in free credits to get started, which is approximately 46,500 minutes of transcription.
{% endhint %}

**Step 2: Get Your Deepgram API Key**

1. Once logged in, navigate to the [API Keys page](https://console.deepgram.com/project/default/settings/api-keys) in your Deepgram Console
2. Click "Create a New API Key"
3. Give your key a descriptive name (e.g., "Ring Tonic Production")
4. Set appropriate permissions (at minimum, you'll need "Usage" and "Transcription" permissions)
5. Click "Create Key" and copy the API key immediately (you won't be able to see it again)

<figure><img src="/files/1UUbSfgKvADW5j4s5JiS" alt=""><figcaption><p>Create a new API key in the Deepgram Console</p></figcaption></figure>

{% hint style="warning" %}
**Important:** Store your API key securely. Deepgram only shows the key once when you create it. If you lose it, you'll need to generate a new one.
{% endhint %}

**Step 3: Add Deepgram Credentials to Your Workspace**

1. In Ring Tonic, navigate to your workspace settings
2. Go to the **Transcription** tab
3. Select **Deepgram** as your transcription provider
4. Paste your API key into the "Deepgram API Key" field
5. Enable "Automatically transcribe call recordings" if you want transcriptions to run after every call
6. Enable "Enable speaker diarization" to identify different speakers (Agent vs Customer)
7. Optionally select a language, or leave it on "Auto-detect" for automatic language detection
8. Click "Save" or "Update Workspace"

<figure><img src="/files/VBQiKazxoMExcNYVLWMH" alt=""><figcaption><p>Configure Deepgram in your workspace transcription settings</p></figcaption></figure>
{% endtab %}
{% endtabs %}

#### Understanding Transcription Settings

After choosing your provider and entering your API key, you'll need to configure a few important settings:

**Automatically Transcribe Call Recordings**

<figure><img src="/files/7YGJleX7a8NgGCKLkLlf" alt=""><figcaption><p>Automatically Transcribe Call Recordings</p></figcaption></figure>

When enabled, Ring Tonic will automatically send each call recording to your chosen transcription provider as soon as the call ends. The transcription usually completes within a few minutes, and you'll be able to view the full text conversation in your call log.

If disabled, you'll need to manually trigger transcription for each call you want transcribed.

{% hint style="success" %}
**Recommendation:** Keep this enabled. Automatic transcription ensures you never miss capturing important conversation details, and you can always search through past calls by keywords.
{% endhint %}

**Enable Speaker Diarization**

Speaker diarization is the process of identifying and labeling different speakers in the conversation.

<figure><img src="/files/f4UXDkbUKjRyjZzBvXgA" alt=""><figcaption><p>Enable Speaker Diarization</p></figcaption></figure>

When enabled, your transcription will show:

* **Agent:** The person who answered or made the call (usually your team member)
* **Customer:** The caller
* **Speaker C, D, E...:** If more than two people participate in the call

Example transcription with speaker diarization:

```
Agent: Thanks for calling ABC Plumbing, this is Sarah. How can I help you today?

Customer: Hi Sarah, I have a leaking pipe under my kitchen sink and it's getting worse.

Agent: I understand, that sounds urgent. Let me check our schedule for you.
```

Without speaker diarization, the entire conversation would appear as a single block of text, making it harder to follow.

{% hint style="info" %}
Speaker diarization adds minimal cost to your transcription and significantly improves readability. We recommend keeping it enabled.
{% endhint %}

**Language Selection**

Both Deepgram and AssemblyAI support automatic language detection, which is the default setting. However, if you know your calls will always be in a specific language, selecting it manually can slightly improve accuracy and processing speed.

<figure><img src="/files/o379fzeDuKqsL8Es8XD3" alt=""><figcaption></figcaption></figure>

Ring Tonic supports:

* **Deepgram:** 30+ languages including English, Spanish, French, German, Chinese, Japanese, and more
* **AssemblyAI:** 100+ languages covering most global markets

{% hint style="info" %}
Leave the language setting on "Auto-detect" unless you exclusively handle calls in a single language. The auto-detection is highly accurate and adapts to different accents and dialects.
{% endhint %}

#### Live AI Call Transcription (AI Agent flows only)

If your call flows use the [AI Agent node](/guides/ai-call-answering), the Transcription tab has a second section: **AI call transcription (live)**. This controls the speech-to-text engine that understands the caller **during** the live AI conversation — separate from the post-call transcription provider above.

A few things make it different from post-call transcription:

* It runs on your **Twilio account** — no separate API key needed.
* Only **Google** and **Deepgram** are available for live calls.
* The default, **Automatic — let Twilio pick the default (recommended)**, uses whichever engine Twilio selects for your account.

<figure><img src="/files/YFsuPv1gJdURE0tWaXFx" alt=""><figcaption><p>The AI call transcription (live) section on the Transcription tab</p></figcaption></figure>

{% hint style="info" %}
**Leave this on Automatic** unless a specific engine understands your callers better — accents and industry vocabulary occasionally favor one provider. If you never use the AI Agent node, this setting has no effect.
{% endhint %}

#### Set up Google Natural Language API for Sentiment Analysis (Optional)

Sentiment analysis examines the emotional tone of your call transcriptions, helping you identify whether conversations were positive, negative, or neutral. This is incredibly valuable for:

* Flagging potentially unhappy customers for follow-up
* Identifying calls that might need manager review
* Tracking overall customer satisfaction trends
* Spotting training opportunities for your team

<figure><img src="/files/oE2ffekvKOtZEhY7dNs6" alt=""><figcaption></figcaption></figure>

Ring Tonic uses Google's Natural Language API to analyze sentiment from your transcriptions. The API examines the entire conversation and returns a sentiment score ranging from -1.0 (very negative) to +1.0 (very positive).

**How Sentiment Categories Work**

Ring Tonic categorizes sentiment into three groups:

| Sentiment Score   | Category     | Meaning                                                            |
| ----------------- | ------------ | ------------------------------------------------------------------ |
| Greater than 0.25 | **Positive** | Customer expressed satisfaction, enthusiasm, or approval           |
| -0.25 to 0.25     | **Neutral**  | Factual conversation with balanced or mixed emotions               |
| Less than -0.25   | **Negative** | Customer expressed frustration, disappointment, or dissatisfaction |

{% hint style="success" %}
**Use Case:** Set up alerts for calls with negative sentiment so managers can review them promptly and reach out to unhappy customers before the situation escalates.
{% endhint %}

**Step 1: Create a Google Cloud Account**

1. Visit <https://console.cloud.google.com>
2. Sign in with your Google account (or create one if needed)
3. Accept the terms of service
4. You may need to set up billing, but Google offers $300 in free credits for new users

**Step 2: Create a New Project**

1. In the Google Cloud Console, click the project dropdown at the top of the page
2. Click "New Project"
3. Enter a project name (e.g., "Ring Tonic Sentiment Analysis")
4. Click "Create"
5. Wait for the project to be created, then select it from the project dropdown

<figure><img src="/files/nNqOGuNdXhKrE1EkhIZ0" alt=""><figcaption><p>Create a new project in Google Cloud Console</p></figcaption></figure>

**Step 3: Enable the Natural Language API**

1. In the left sidebar, navigate to "APIs & Services" > "Library"
2. Search for "Cloud Natural Language API"
3. Click on "Cloud Natural Language API" from the results
4. Click the "Enable" button
5. Wait for the API to be enabled (usually takes a few seconds)

<figure><img src="/files/utL2fuP9VBDJw7KEaX0L" alt=""><figcaption><p>Enable the Cloud Natural Language API</p></figcaption></figure>

**Step 4: Create an API Key**

1. Navigate to "APIs & Services" > "Credentials"
2. Click "Create Credentials" at the top
3. Select "API key" from the dropdown
4. Your new API key will be displayed (it starts with "AIza...")
5. Click "Copy" to copy the key
6. **Optional but recommended:** Click "Restrict Key" and add API restrictions to limit the key to only the Natural Language API

<figure><img src="/files/JVSFA0r28BWspxpD52hH" alt=""><figcaption><p>Create a new API key for the Natural Language API</p></figcaption></figure>

{% hint style="warning" %}
**Security Best Practice:** Restrict your API key to only the Natural Language API to prevent unauthorized use. You can do this by clicking "Restrict Key" after creating it, then under "API restrictions," select "Restrict key" and choose "Cloud Natural Language API."
{% endhint %}

**Step 5: Add Google NLP API Key to Your Workspace**

1. In Ring Tonic, navigate to your workspace settings
2. Go to the **Transcription** tab
3. Scroll down to the "Sentiment Analysis (Optional)" section
4. Paste your API key into the "Google NLP API Key" field
5. Enable "Automatically analyze sentiment from transcriptions"
6. Click "Save" or "Update Workspace"

<figure><img src="/files/bc2SRUFV99jROCNlqiHM" alt=""><figcaption><p>Configure Google NLP for sentiment analysis</p></figcaption></figure>

Once configured, Ring Tonic will automatically analyze sentiment for every transcribed call and display the results in your call log.

**Supported Languages for Sentiment Analysis**

<details>

<summary>Google's Natural Language API supports sentiment analysis in the following languages:</summary>

1. Arabic (ar)
2. Chinese (Simplified) (zh)
3. Chinese (Traditional) (zh-Hant)
4. Dutch (nl)
5. English (en)
6. French (fr)
7. German (de)
8. Indonesian (id)
9. Italian (it)
10. Japanese (ja)
11. Korean (ko)
12. Portuguese (pt)
13. Spanish (es)
14. Thai (th)
15. Turkish (tr)
16. Vietnamese (vi)

</details>

{% hint style="info" %}
If your transcription is in a language not supported for sentiment analysis, the sentiment will be marked as "Unsupported" in your call log. The transcription will still work normally.
{% endhint %}

{% hint style="success" %}
**What's Next?** After setting up transcription and sentiment analysis, Ring Tonic will automatically process your call recordings and provide searchable transcripts with sentiment scores. You can view all this data in your call logs and use it to improve customer service, train your team, and qualify leads more effectively.
{% endhint %}

### 4. Set up AI Automation with OpenAI

AI automation supercharges your call analytics by automatically extracting insights from every conversation. With OpenAI integration, Ring Tonic can identify important keywords, categorize calls, qualify leads, and even estimate deal values—all without manual review.

<figure><img src="/files/BnROhggyLqiA3O1zKcHt" alt=""><figcaption><p>Keyword Spotting</p></figcaption></figure>

This is incredibly powerful for:

* Automatically identifying hot leads ready to buy
* Spotting keywords that indicate urgency or specific needs
* Auto-tagging calls for easy filtering ("Ready to Buy", "Needs Escalation", "Price Shopping")
* Estimating potential revenue from each call
* Training your team by highlighting what customers care about

Ring Tonic uses OpenAI's GPT models to analyze your call transcriptions and provide actionable intelligence on every conversation.

{% hint style="success" %}
**The same key powers AI Call Answering.** Once your OpenAI key is saved here, the [AI Agent node](/guides/ai-call-answering) can answer calls live — greeting, qualifying, and booking on your behalf. Usage bills directly to your OpenAI account.
{% endhint %}

{% hint style="info" %}
**Important:** AI automation requires transcription to be set up first. Make sure you've completed [Section 3: Transcription](#id-3.-set-up-call-transcription-and-sentiment-analysis) before configuring AI features.
{% endhint %}

#### How to Set Up OpenAI

**Step 1: Create an OpenAI Account**

1. Visit <https://platform.openai.com/signup>
2. Sign up with your email or Google account
3. Verify your email address
4. Complete the onboarding process

**Step 2: Get Your OpenAI API Key**

1. After logging in, navigate to the [API Keys page](https://platform.openai.com/api-keys)
2. Click "Create new secret key"
3. Give your key a name (e.g., "Ring Tonic Production")
4. Optionally restrict permissions to only what's needed
5. Click "Create secret key"
6. Copy the API key immediately (it starts with "sk-" and you won't be able to see it again)

<figure><img src="/files/BAkhNtOOvcPCmVmMraNm" alt=""><figcaption><p>Create a new API key in the OpenAI Platform</p></figcaption></figure>

{% hint style="warning" %}
**Important:** Store your API key securely. OpenAI only shows the full key once when you create it. If you lose it, you'll need to generate a new one and update Ring Tonic.
{% endhint %}

**Step 3: Add OpenAI API Key to Your Workspace**

1. In Ring Tonic, navigate to your workspace settings
2. Go to the **AI Automation** tab
3. Paste your API key into the "OpenAI API Key" field
4. Configure your AI automation settings (explained below)
5. Click "Save" or "Update Workspace"

<figure><img src="/files/RCQsVp3AD5oHJnL3BGMU" alt=""><figcaption><p>Configure OpenAI in your workspace AI automation settings</p></figcaption></figure>

#### Automatically Analyze Keywords and Qualify Leads

When enabled, Ring Tonic's AI will analyze every transcribed call to:

1. **Extract Important Keywords** - Identifies meaningful words and phrases that indicate customer intent, needs, or concerns
2. **Categorize Each Keyword** - Labels keywords by type (sales, scheduling, support, urgent, pricing, escalation, etc.)
3. **Identify the Speaker** - Knows whether the Agent or Customer said each keyword
4. **Auto-Tag Calls** - Applies tags like "Ready to Buy", "Needs Escalation", "Price Shopping", "Product Inquiry" for easy filtering
5. **Qualify Leads Automatically** - Determines if the call represents a qualified lead based on your criteria

<figure><img src="/files/iAhBZ40DVoI2gZWr3ZOk" alt=""><figcaption><p>Auto-tagging and keyword spotting</p></figcaption></figure>

**Example: How It Works**

Imagine a customer calls and says:

> "Hi, I need someone to fix my water heater today. It's leaking everywhere and I'm worried about water damage. Can you give me a quote and come out this afternoon?"

The AI would extract keywords like:

* **"water heater"** (category: product, importance: 8, speaker: Customer)
* **"today"** (category: urgent, importance: 9, speaker: Customer)
* **"leaking"** (category: support, importance: 7, speaker: Customer)
* **"quote"** (category: pricing, importance: 9, speaker: Customer)
* **"this afternoon"** (category: scheduling, importance: 10, speaker: Customer)

Auto-tags applied: "Ready to Buy", "Urgent", "Needs Quote"

Lead qualification: **QUALIFIED** (95% confidence) because the customer requested a quote, showed urgency, and wanted to schedule service.

<figure><img src="/files/VSsLc8rHwQSR7PcUoqpr" alt=""><figcaption><p>Auto-qualify Leads</p></figcaption></figure>

{% hint style="success" %}
**Recommendation:** Enable this feature. It saves hours of manual call review and ensures no qualified leads slip through the cracks. The AI is remarkably accurate at identifying buying intent.
{% endhint %}

#### Custom Qualification Criteria (Optional)

Every business defines "qualified leads" differently. Ring Tonic provides sensible defaults, but you can customize the qualification criteria to match your specific business needs.

**Default Qualification Criteria**

Out of the box, Ring Tonic considers a call qualified if the customer:

1. Requests a quote or pricing information
2. Wants to schedule an appointment within 2 weeks
3. Has an urgent problem that needs immediate attention
4. Mentions they are ready to move forward with the service

<figure><img src="/files/S6fGcDgxuADA2NzIKyJS" alt=""><figcaption><p>Default Qualification Criteria</p></figcaption></figure>

**Customizing for Your Business**

You can override the default criteria with your own business-specific guidelines. For example:

**For a High-End Law Firm:**

```
A lead is qualified if:
- Case value exceeds $50,000
- Client has immediate legal needs
- Decision-maker is on the call
- Case type matches our practice areas (corporate, real estate, litigation)
```

**For a Roofing Company:**

```
A lead is qualified if:
- Customer owns the property (not renters)
- Roof damage is current, not future planning
- Customer requests inspection or estimate
- Property is within our service area
- Customer has decision-making authority
```

**For a SaaS Business:**

```
A lead is qualified if:
- Company size is 50+ employees
- Customer discusses budget or pricing
- Decision-maker or influencer is on the call
- Timeline is within 3 months
- Specific use case mentioned that matches our product
```

The AI will incorporate your custom criteria when analyzing calls and determining qualification status.

{% hint style="info" %}
Don't worry about making it perfect. The AI is smart enough to understand natural language guidelines. Write your criteria as if you're explaining it to a new team member.
{% endhint %}

#### Confidence Threshold

The confidence threshold determines how certain the AI must be before automatically qualifying a lead. This is a crucial setting that balances quantity versus quality.

<figure><img src="/files/xYBL9ScwkziZ1mnv9WEF" alt=""><figcaption><p>Confidence threshold field</p></figcaption></figure>

**How It Works**

When the AI analyzes a call, it assigns a qualification confidence score from 0-100:

* **90-100%:** Very confident this is a qualified lead
* **75-89%:** Confident, but some uncertainty
* **60-74%:** Moderate confidence
* **Below 60%:** Low confidence

Your workspace confidence threshold (default: 80%) acts as a filter. Only calls meeting or exceeding this threshold will be automatically marked as qualified.

**Choosing Your Threshold**

| Threshold   | Effect                                              | Best For                                                                 |
| ----------- | --------------------------------------------------- | ------------------------------------------------------------------------ |
| **50-65%**  | More leads auto-qualified, lower accuracy           | High-volume businesses that manually review all leads anyway             |
| **70-80%**  | Balanced approach, good accuracy                    | Most businesses (recommended)                                            |
| **85-100%** | Only very obvious qualified leads, highest accuracy | Businesses with limited sales resources, want to focus only on hot leads |

**Example Scenario**

With an 80% threshold:

* Call A: 95% confidence → Auto-qualified ✅
* Call B: 82% confidence → Auto-qualified ✅
* Call C: 75% confidence → Not auto-qualified (you can manually review) ❌
* Call D: 60% confidence → Not auto-qualified ❌

{% hint style="success" %}
**Recommendation:** Start with 80% (the default) and adjust based on your results. If you find the AI is missing qualified leads, lower it to 70-75%. If you're getting too many false positives, raise it to 85-90%.
{% endhint %}

#### Re-qualify Existing Leads

Edits to your qualification criteria or confidence threshold apply to new calls going forward. To bring your **existing** leads in line with the updated criteria, re-qualify them. Ring Tonic re-runs the AI analysis on calls you've already received, using your latest criteria and threshold — no new phone calls are made, it reads the transcripts you already have.

There are two ways to start, depending on whether you want to re-qualify everyone or just a selection.

{% tabs %}
{% tab title="All leads (from this page)" %}
Click **"Re-qualify existing leads"** directly beneath the Custom Qualification Criteria box. This re-runs qualification for every eligible lead in the workspace — the natural next step right after you edit your criteria or threshold.

<figure><img src="/files/YzVgYBp63pLn2J0kbZOS" alt=""><figcaption><p>The "Re-qualify existing leads" button beneath the Custom Qualification Criteria editor</p></figcaption></figure>
{% endtab %}

{% tab title="Selected leads (from Call Activity)" %}
Go to **Analytics > Call Activity**, tick the calls you want, then choose **Actions > Re-qualify Leads**. To re-qualify the whole workspace from here, use the header checkbox to select all.

<figure><img src="/files/TuWC5MkjxPDuTLcriH0T" alt=""><figcaption><p>The "Re-qualify Leads" bulk action in the Call Activity Actions menu</p></figcaption></figure>
{% endtab %}
{% endtabs %}

**Choosing how the re-run behaves**

Before it starts, a dialog lets you adjust three options:

| Option                             | Default | What it does                                                                                                                            |
| ---------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| **Allow downgrades**               | On      | Lets stricter criteria move an already-qualified lead back to *not qualified*. Turn off to only upgrade leads and never downgrade them. |
| **Trigger webhooks & automations** | On      | Re-fires lead webhooks and notifications for leads that *newly* become qualified. Turn off for a silent update.                         |
| **Include voicemails**             | On      | Also re-qualifies missed calls that left a transcribed voicemail.                                                                       |

<figure><img src="/files/q6RkHDC83sssD2TLnsrJ" alt="" width="563"><figcaption><p>Re-qualification options dialog with the allow-downgrades, webhooks, and voicemails toggles</p></figcaption></figure>

{% hint style="info" %}
Re-qualification runs in the background and can take a while on large workspaces. Ring Tonic emails you a summary when it finishes, showing how many leads ended up qualified, not qualified, still pending, or flagged as spam.
{% endhint %}

{% hint style="warning" %}
Only calls with a transcription — or a transcribed voicemail — are re-qualified; calls without one are skipped. Leads you've set by hand are always preserved and never changed by a re-run.
{% endhint %}

#### Automatically Estimate Deal Value

Deal value estimation helps you prioritize leads based on potential revenue. When enabled, Ring Tonic's AI analyzes customer conversations and automatically estimates the potential deal value using your Products & Services pricing catalog.

<figure><img src="/files/yCQybfKvKbyPHeHJ7rwz" alt=""><figcaption><p>Automatically Estimate Deal Value field</p></figcaption></figure>

**How It Works**

When a customer mentions specific products or services during a call, the AI:

1. Matches their needs to items in your catalog
2. Considers context (urgency, scope, complexity)
3. Estimates a deal value within your pricing ranges
4. Displays the estimate in your call log

**Example:** A customer calls about a broken water heater needing same-day replacement. The AI identifies "Water Heater Replacement" ($1,200-$3,500) plus "Emergency Service" ($150) from your catalog and estimates the deal at $1,500-$3,650.

**Setting Up Deal Value Estimation**

To use this feature:

1. **Enable the feature** - Toggle "Automatically estimate deal value" in the AI Automation tab
2. **Optionally build your catalog** - Add Products & Services with pricing ranges for more accurate estimates

**How Deal Values Are Estimated:**

**With a Products & Services Catalog (Recommended):**

* AI matches customer needs to your catalog items
* Estimates within your defined price ranges
* More accurate and consistent estimations

**Without a Catalog:**

* AI can still estimate if customers explicitly mention budgets or prices
* Example: "I'm looking to spend around $5,000" → AI estimates $5,000
* Less reliable as it depends on customers volunteering pricing information

See the complete [Products & Services Guide](/guides/products-and-services) for detailed instructions on building your catalog for best results.

{% hint style="info" %}
**Recommendation:** Set up your Products & Services catalog for the most accurate deal value estimates. The AI works best when it has your actual pricing data to reference.
{% endhint %}

#### Automatically Detect Caller Name

<figure><img src="/files/VKoIsYcRwImsyGy3gmCU" alt=""><figcaption><p>Automatically Detect Caller Name setting</p></figcaption></figure>

When enabled, the AI extracts caller names from transcriptions when callers introduce themselves (e.g., "Hi, this is John Smith..."). This supplements [CNAM lookup](/guides/phone-numbers#toggling-cnam-lookup) from phone carriers. If both are enabled, AI only overrides the CNAM name when detection confidence exceeds 80%.

#### Voice & Audio — ElevenLabs Voices (Optional)

At the bottom of the **AI Automation** tab, you'll find a **Voice & Audio** section where you can connect your [ElevenLabs](https://elevenlabs.io) account. ElevenLabs provides ultra-realistic AI voices that Ring Tonic uses for call-flow greetings and IVR prompts — a big upgrade from Twilio's built-in voices.

<figure><img src="/files/Pfj2hV2fUTJZEXHDkfDm" alt=""><figcaption><p>The Voice &#x26; Audio section at the bottom of the AI Automation tab</p></figcaption></figure>

This is a **bring-your-own-key** integration, so you pay ElevenLabs directly based on your own plan and usage. Leaving the field empty simply hides the ElevenLabs option in the call-flow builder — Twilio's built-in voices remain available.

{% hint style="success" %}
**Also the AI Agent's voice.** The [AI Agent node](/guides/ai-call-answering) speaks in your ElevenLabs voices — the node's Voice tab loads them from this key. Each supported language ships with a curated default voice, and you can pick any voice from your own ElevenLabs library.
{% endhint %}

**Step 1: Create an ElevenLabs Account**

1. Visit <https://elevenlabs.io>
2. Sign up with your email or Google account
3. Verify your email address
4. Choose a plan that matches your expected usage (free tier available for testing)

{% hint style="info" %}
ElevenLabs' free tier includes enough characters per month to test voices with a handful of short greetings. For production IVR flows, we recommend at least their Starter plan.
{% endhint %}

**Step 2: Get Your ElevenLabs API Key**

1. Once logged in, navigate to [Settings → API Keys](https://elevenlabs.io/app/settings/api-keys)
2. Click **"Create API Key"**
3. Give your key a descriptive name (e.g., "Ring Tonic Production")
4. Set permissions (see the table below) — leave everything else on **No Access** for safety
5. Copy the API key immediately — ElevenLabs only shows it once

**Required permissions**

Ring Tonic only needs two permissions. Keeping the rest disabled limits the damage if the key is ever exposed.

| Permission         | Setting | Why Ring Tonic needs it                                                                  |
| ------------------ | ------- | ---------------------------------------------------------------------------------------- |
| **Text to Speech** | Access  | Generates the MP3 audio for each greeting and IVR prompt when you publish a call flow    |
| **Voices**         | Read    | Lists the voices on your ElevenLabs account so you can pick one in the call-flow builder |

{% hint style="info" %}
**Voices only needs Read, not Write.** Ring Tonic never creates, clones, or deletes voices on your ElevenLabs account — it only reads the list of voices you already have.
{% endhint %}

All other permissions — Speech to Speech, Speech to Text, Sound Effects, Audio Isolation, Music Generation, Dubbing, ElevenAgents, Projects, Audio Native, Voice Generation, Forced Alignment — should stay on **No Access**.

<figure><img src="/files/x41tl8WRXUMLmmxHXH6R" alt="" width="375"><figcaption><p>Create a new API key in the ElevenLabs dashboard</p></figcaption></figure>

{% hint style="warning" %}
**Important:** Store your API key securely. If you lose it, you'll need to generate a new one and update Ring Tonic.
{% endhint %}

**Step 3: Add ElevenLabs API Key to Your Workspace**

1. In Ring Tonic, navigate to your workspace settings
2. Go to the **AI Automation** tab
3. Scroll down to the **Voice & Audio** section
4. Paste your API key into the **ElevenLabs API Key** field
5. Click "Save" or "Update Workspace"

Once saved, the ElevenLabs voice option becomes available inside the Greeting and IVR nodes of the call-flow builder. You can pick from your full ElevenLabs voice library when designing each greeting.

{% hint style="info" %}
**How audio is generated:** ElevenLabs audio is pre-generated when you **publish** a call flow (not on every keystroke), so you only consume API credits on real changes. The generated audio is cached, so published flows serve instantly without hitting ElevenLabs on each incoming call.
{% endhint %}

**Free tier limitation — "Free users cannot use library voices via the API"**

If you're on the ElevenLabs free plan, the API can only synthesize voices that belong to your account. The default "library" voices (Rachel, Adam, Bella, and the other premade voices in the voice picker) require a paid plan to use via API, even though you can preview them in the ElevenLabs web app.

You have three options:

| Option                            | Cost       | What you get                                                                                                                                                        |
| --------------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Upgrade to ElevenLabs Starter** | \~$6/month | All library voices (Rachel, Adam, etc.) become usable via API, plus \~30,000 characters/month                                                                       |
| **Create your own voice (free)**  | $0         | Use **Voice Design** in the ElevenLabs web app — describe the voice you want, generate it, save it to your library. Voices you own are API-usable on the free tier. |
| **Skip ElevenLabs**               | $0         | Switch the Greeting / IVR node's audio provider to **Twilio** or **Amazon Polly**. No ElevenLabs account required.                                                  |

{% hint style="info" %}
If you created your own voice in ElevenLabs but don't see it in Ring Tonic's voice picker, refresh the call-flow editor — Ring Tonic fetches your voice list when the page loads.
{% endhint %}

{% hint style="success" %}
**Clearing the key:** To disconnect ElevenLabs, empty the field and save. The ElevenLabs option will disappear from the call-flow builder and your already-published flows keep working from cache.
{% endhint %}

{% hint style="success" %}
**What's Next?** After setting up AI automation, Ring Tonic will automatically analyze every transcribed call, extract keywords, qualify leads, estimate deal values, and detect caller names. You can view all this intelligence in your call logs and use it to prioritize follow-ups, train your team, and close more deals.
{% endhint %}

### 5. Configure Currency, Language & Branding, Timezone

Beyond the core integrations, your workspace has a few additional settings that control how Ring Tonic displays information and represents your brand.

#### Currency

The currency setting determines how money values are displayed throughout Ring Tonic—in call logs, deal value estimates, pricing catalogs, and reports.

<figure><img src="/files/hYv4APcFEedE5FQyLXFb" alt=""><figcaption></figcaption></figure>

**What It Affects:**

* **Deal value estimates** - Shows amounts in your chosen currency ($1,500 vs €1,500 vs ₫1,500,000)
* **Products & Services pricing** - Your catalog displays in your currency
* **Reports and exports** - All financial data formatted correctly

#### Language & Region (Locale)

The locale setting controls regional formatting preferences for dates, times, numbers, and currency display. It works together with your currency setting to ensure everything displays correctly for your region.

<figure><img src="/files/1VMgI3LkF03x2pRu7avc" alt=""><figcaption></figcaption></figure>

**What It Affects:**

* **Date and time formats** - US format (MM/DD/YYYY, 12-hour) vs European (DD/MM/YYYY, 24-hour)
* **Number formatting** - Decimal and thousands separators (1,500.00 vs 1.500,00)
* **Currency symbol position** - Before ($1,500) or after (1.500€)
* **Day/month names** - Language for calendar displays
* **First day of week** - Sunday vs Monday in calendars

{% hint style="info" %}
**Currency + Locale Work Together:** Your currency determines what currency to use (USD, EUR, etc.), while your locale determines how to format it. For example, if you choose USD currency with the de\_DE locale, amounts will show as "1.500,00 $" using German formatting conventions.
{% endhint %}

#### Timezone

The timezone setting controls how dates and times are displayed throughout Ring Tonic—in call logs, analytics, date ranges, and reports. Choose the timezone where your business operates for accurate reporting aligned with your business hours.

**Default:** UTC

<figure><img src="/files/eGrn6mAocLrqf9xTknOo" alt=""><figcaption></figcaption></figure>

### 6. Configure Analytics Defaults

The **Analytics** tab in workspace settings (**Settings** → **Workspace** → **Analytics**) controls two workspace-wide defaults: the missed-call alert threshold and Google Ads consent fallbacks.

#### Missed Call Alert Threshold

A slider from 0% to 100%. Tracking numbers whose missed-call rate exceeds this percentage are flagged with a warning icon in analytics — useful for spotting underperforming numbers at a glance.

**Default:** 5%

Lower the value to be more sensitive (alert on small missed-call rates); raise it to suppress noise from low-volume numbers.

#### Default Ad Consent

*(Relevant when you use* [*Form Submissions*](/guides/form-submissions) *and have Google Ads conversion uploads configured on the Agency plan.)*

Google Ads' privacy framework (Consent Mode v2) requires every conversion upload to carry a consent signal for two flags:

* **`ad_user_data`** — whether the user consented to their data being sent to Google
* **`ad_personalization`** — whether that data can be used for personalized advertising

Your customer's page *should* push these signals via `window.dataLayer` or Google Tag Manager at form-submit time. When the page does push them, those signals win. When the page *doesn't* — common on first integration — Ring Tonic falls back to the workspace defaults you set here.

| Setting                     | Use when                                                                                                                                                                        |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Unspecified (no signal)** | You haven't determined the right default yet. Google treats this as the strictest case — no user-level matching, lower conversion quality.                                      |
| **Granted**                 | Your customer has gathered consent off-page (cookie banner, terms-of-service checkbox) and you're confident every visitor whose form lands has consented.                       |
| **Denied**                  | You operate in a region where ad tracking is opt-in only and the form fill itself doesn't grant consent. Uploads still happen but Google won't match to user-level identifiers. |

{% hint style="warning" %}
Default to **Unspecified** until you have a documented basis (cookie banner, T\&C) for choosing Granted. Setting Granted without that basis is a compliance risk in GDPR / CCPA / LGPD jurisdictions.
{% endhint %}

{% hint style="info" %}
Page-level signals always override the workspace default. Setting Granted here doesn't force-grant for visitors whose page explicitly pushed Denied.
{% endhint %}

***

{% hint style="success" %}
**You're All Set!** After configuring these basic settings along with your Twilio, transcription, and AI integrations, your workspace is fully configured and ready to track calls, analyze conversations, and generate valuable insights.
{% endhint %}

{% hint style="info" %}
**Agency Plan Users:** If you're on the Agency plan, you can also [invite team members to collaborate on your workspace](/guides/team-management).
{% endhint %}


# Team Management

### What is Team Management?

Team Management allows you to invite colleagues to collaborate on your workspace. Team members can access call tracking data, analytics, and campaigns based on their assigned role. This feature is perfect for agencies managing multiple clients or teams that need to collaborate on call tracking.

<div data-full-width="true"><figure><img src="/files/E1f4m2wh9TiKcfAF8ioh" alt=""><figcaption></figcaption></figure></div>

{% hint style="warning" %}
**Agency Plan Required:** Team Management is only available on the Agency plan. Indie plan users can upgrade to access this feature.
{% endhint %}

***

### Team Roles

Ring Tonic offers three role levels to control what team members can access and modify:

#### Admin

**Full access including billing and team management**

Admins have complete control over the workspace:

* Manage billing and subscription
* Invite and remove team members
* Change member roles
* Create, edit, and delete campaigns
* View and export all analytics
* Configure workspace settings
* Access all API integrations

{% hint style="success" %}
**Best for:** Account managers, workspace owners, or senior team members who need full control.
{% endhint %}

#### Manager

**Create and edit campaigns, view analytics**

Managers can work with campaigns and analytics but cannot manage billing or team:

* Create, edit, and delete campaigns
* View and export all analytics
* Configure campaign settings
* Cannot manage billing
* Cannot invite or remove team members
* Cannot change workspace settings

{% hint style="info" %}
**Best for:** Campaign managers, marketing specialists, or team leads who manage campaigns but don't need billing access.
{% endhint %}

#### Member

**View-only access to analytics**

Members have read-only access to workspace data:

* View analytics and reports
* View campaign details
* Export analytics data
* Cannot create or edit campaigns
* Cannot manage billing or team
* Cannot modify any settings

{% hint style="info" %}
**Best for:** Clients, stakeholders, or junior team members who need visibility into performance without editing permissions.
{% endhint %}

***

### 1. Invite Team Members

Add new members to your workspace by sending email invitations.

#### How to Invite a Member

**Step 1: Open the Invite Dialog**

1. Go to **Workspace Members**
2. Click **Invite Member** button in the top right

<figure><img src="/files/TfjmIClazN1i5ihi2VtH" alt=""><figcaption><p>Click Invite Member to add a new team member</p></figcaption></figure>

**Step 2: Enter Member Details**

1. **Email address:** Enter the colleague's email address
2. **Role:** Select the appropriate role (Admin, Manager, or Member)

<figure><img src="/files/unviKnpAf7ALDqnHZMzo" alt="" width="563"><figcaption><p>Enter email and select role for the new member</p></figcaption></figure>

**Step 3: Send Invitation**

Click **Send Invitation** to email the invitation to your colleague.

{% hint style="success" %}
The invitation email includes a secure link that expires in 7 days. The recipient can click the link to accept the invitation and join your workspace.
{% endhint %}

<figure><img src="/files/Qdy9lGQRNNxyOSAgZc5g" alt="" width="563"><figcaption><p>Invitation sent successfully</p></figcaption></figure>

#### What Happens After Sending?

1. **Email Sent:** Recipient receives an invitation email with a secure link
2. **Pending Status:** Invitation appears in the "Pending Invitations" table
3. **7-Day Expiry:** Invitation expires automatically after 7 days
4. **Acceptance:** When accepted, the member is added to your workspace with the assigned role

{% hint style="info" %}
You cannot send duplicate invitations to the same email address. If someone is already invited or is already a member, you'll see an error message.
{% endhint %}

***

### 2. Manage Pending Invitations

Track and manage invitations that haven't been accepted yet.

#### View Pending Invitations

The "Pending Invitations" table shows all outstanding invitations with:

* **Email:** Invited person's email address
* **Role:** Assigned role (Admin, Manager, or Member)
* **Invited By:** Team member who sent the invitation
* **Expires:** Expiration date (7 days from send date)
* **Status:** Pending or Expired

<figure><img src="/files/Jd4tfUX4SNLmTFtsbnqe" alt=""><figcaption><p>View and manage pending workspace invitations</p></figcaption></figure>

#### Resend an Invitation

If the recipient didn't receive the email or the link expired:

1. Find the invitation in the "Pending Invitations" table
2. Click the **Resend** button (refresh icon)
3. A new email is sent with a fresh 7-day expiration

{% hint style="success" %}
Resending an invitation automatically extends the expiration by 7 days from the current date.
{% endhint %}

#### Revoke an Invitation

To cancel an invitation before it's accepted:

1. Find the invitation in the "Pending Invitations" table
2. Click the **Revoke** button (trash icon)
3. Confirm the revocation

{% hint style="warning" %}
Once revoked, the invitation link becomes invalid. The recipient cannot use it to join the workspace, even if they had the email.
{% endhint %}

***

### 3. Change Member Roles

Update a team member's role to adjust their permissions.

#### How to Change a Role

**Step 1: Open Change Role Dialog**

1. Find the member in the "Current Members" table
2. Click the **Change Role** button (user-cog icon)

{% hint style="info" %}
You cannot change your own role or the workspace owner's role. These buttons are hidden for those members.
{% endhint %}

<figure><img src="/files/VaQv53w6Np35eIuYBbso" alt=""><figcaption><p>Click the user-cog icon to change a member's role</p></figcaption></figure>

**Step 2: Select New Role**

1. Review the current role in the dialog description
2. Select the new role from the dropdown:
   * **Admin:** Full access
   * **Manager:** Can edit campaigns
   * **Member:** View only

<figure><img src="/files/vq0NVukIgM9LtjVexaie" alt="" width="563"><figcaption><p>Select new role for the team member</p></figcaption></figure>

**Step 3: Update Role**

Click **Update Role** to save the changes.

{% hint style="success" %}
Role changes take effect immediately. The member's permissions update as soon as you confirm the change.
{% endhint %}

***

### 5. Remove Team Members

Remove a member's access to the workspace.

#### How to Remove a Member

**Step 1: Click Remove Button**

1. Find the member in the "Current Members" table
2. Click the **Remove** button (trash icon)

{% hint style="warning" %}
You cannot remove yourself or the workspace owner. These buttons are hidden for those members.
{% endhint %}

**Step 2: Confirm Removal**

1. Read the confirmation message carefully
2. Click **Remove** to confirm

{% hint style="danger" %}
**Warning:** Removed members immediately lose access to ALL workspace data including:

* Call logs and analytics
* Campaign details
* Workspace settings
* Any in-progress work

This action cannot be undone. The member must be re-invited to regain access.
{% endhint %}

<figure><img src="/files/68mCgx7UngVpcexKVlod" alt="" width="563"><figcaption><p>Confirm member removal - this action is immediate</p></figcaption></figure>

***

### Troubleshooting

<details>

<summary>An invitation has already been sent to this email address</summary>

**Problem:** You're trying to invite someone who already has a pending invitation.

**Solution:**

* Check the "Pending Invitations" table
* Find the existing invitation
* Click **Resend** to send a fresh email with extended expiration

</details>

<details>

<summary>This user is already a member of this workspace</summary>

**Problem:** The email address belongs to an existing member.

**Solution:**

* Check the "Current Members" table
* If you want to change their access, use **Change Role** instead
* If you need to re-add them, remove them first, then invite again

</details>

<details>

<summary>Cannot remove the workspace owner</summary>

**Problem:** You're trying to remove the workspace owner.

**Solution:**

* Workspace owners cannot be removed
* Only the owner can transfer ownership or delete the workspace
* If you need to change ownership, contact support

</details>

<details>

<summary>Team management is not available on your current plan</summary>

**Problem:** You're on the Indie plan which doesn't include team management.

**Solution:**

* Upgrade to the Agency plan
* Go to **Settings** → **Billing** → Select **Agency** plan
* Complete payment to unlock team management

</details>

<details>

<summary>Invitation email not received</summary>

**Problem:** Invited member didn't receive the email.

**Solution:**

1. Check their spam/junk folder
2. Verify you entered the correct email address
3. Click **Resend** to send another copy
4. If still not received, contact support

</details>


# Products & Services

### What are Products & Services?

The Products & Services catalog is your pricing menu that powers AI-driven deal value estimation. By maintaining a catalog of what you offer and how much it costs, Ring Tonic's AI can analyze customer calls and automatically estimate potential revenue for each lead.

<figure><img src="/files/DxIY4Q5qdMyCDo1Gr5pO" alt=""><figcaption></figcaption></figure>

### How It Works

When a customer calls and discusses specific needs, Ring Tonic will:

1. **Send the conversation to OpenAI API** (via the transcription)
2. **Identifies mentioned products/services** from your catalog
3. **Understands the context** (repair vs replacement, urgency, scope)
4. **Estimates the deal value** based on your pricing ranges
5. **Displays the estimate** in your call log for quick prioritization

**Example:**

**Your Catalog:**

* Water Heater Repair: $150 - $400
* Water Heater Replacement: $1,200 - $3,500
* Emergency Service Call: $150

**Customer says:**

> "My 15-year-old water heater just died and I need a new one installed today. Can someone come out this afternoon?"

**AI estimates:** $1,500 - $3,650 (replacement + emergency service)

Now you know this is a high-value lead that needs immediate attention.

{% hint style="info" %}
**Requirements:** Deal value estimation requires:

1. "Automatically estimate deal value" field enabled in your workspace settings under AI Automation tab
2. Calls must be transcribed (transcription must be enabled)
3. Products & Services catalog is **optional** but highly recommended for accurate estimates
   {% endhint %}

{% hint style="warning" %}
**Without a Catalog:** The AI can still estimate deal values if customers explicitly mention budgets or prices (e.g., "I have a $3,000 budget"). However, these estimates are less reliable and depend on customers volunteering pricing information. For best results, set up your Products & Services catalog.
{% endhint %}

### How to Add Products & Services

**Step 1: Navigate to Products & Services**

1. Click **Products & Services** in the left sidebar
2. Click the **Add Product/Service** button

<figure><img src="/files/CapFbDxbCN4NMm4esQ5P" alt=""><figcaption><p>The Products &#x26; Services catalog page</p></figcaption></figure>

**Step 2: Fill Out the Product/Service Details**

You'll need to provide the following information:

**Name (Required)**

The name of your product or service. Be specific and descriptive.

**Good Examples:**

* "Roof Inspection & Estimate"
* "Full Roof Replacement (Asphalt Shingles)"
* "Emergency Leak Repair"
* "Gutter Installation"

**Avoid:**

* "Service" (too vague)
* "Repair 1" (not descriptive)
* "Thing" (not helpful)

{% hint style="info" %}
Use names that customers would actually say during a phone call. The AI matches based on how people naturally speak.
{% endhint %}

**Description (Optional)**

Add details about what's included, typical duration, or any other relevant information. This helps the AI make more accurate estimations.

**Examples:**

* "Complete tear-off and replacement of existing roof, including underlayment, drip edge, and cleanup"
* "Emergency service call for urgent plumbing issues (24/7 availability)"
* "Comprehensive HVAC system inspection with written report"

**Category (Optional)**

Group related items together for easier organization. Common categories:

* Installation
* Repair
* Maintenance
* Consultation
* Emergency Service
* Inspection
* Upgrade

You can create your own categories that match your business structure.

<figure><img src="/files/ecWfYBVZLL6jvlacUILy" alt=""><figcaption><p>Add a new product or service with pricing details</p></figcaption></figure>

**Price Range (Required)**

Set minimum and maximum prices in your workspace currency. The AI uses this range to estimate deal values based on what the customer describes.

**Minimum Price:** The lowest price you'd typically charge for this service (best-case scenario, simple job)

**Maximum Price:** The highest price you'd typically charge (worst-case scenario, complex job)

**Examples:**

| Product/Service       | Min Price | Max Price | Why the Range?                       |
| --------------------- | --------- | --------- | ------------------------------------ |
| Roof Repair           | $500      | $3,000    | Small patch vs extensive damage      |
| HVAC Installation     | $3,500    | $12,000   | Single unit vs whole-house system    |
| Plumbing Service Call | $150      | $800      | Simple fix vs major repair           |
| Website Design        | $2,000    | $15,000   | Landing page vs full e-commerce site |

{% hint style="success" %}
**Tip:** Use realistic ranges based on your actual past jobs. The AI is smart enough to estimate within the range based on job complexity mentioned in the call.
{% endhint %}

**Status (Optional)**

Toggle whether this product/service is active:

* **Active (default):** Included in AI deal value estimation
* **Inactive:** Excluded from estimation but kept in your catalog

Use inactive status for seasonal services or products you're phasing out.

**Step 3: Save Your Product/Service**

Click **Create Product/Service** (or **Update Product/Service** if editing)

You'll see a success message and return to the catalog page.

### When Deal Values Are (and Aren't) Estimated

**The AI WILL estimate a deal value when:**

**With a Products & Services Catalog:**

✅ Customer discusses specific products/services from your catalog

✅ Customer mentions needs that clearly match your offerings

✅ Customer asks for quotes, pricing, or estimates

✅ Conversation includes enough context to make an educated guess

**Without a Products & Services Catalog:**

✅ Customer explicitly mentions budget amounts (e.g., "I have $5,000 to spend")

✅ Customer states how much they're willing to pay

✅ Customer references specific dollar amounts for their project

**The AI WON'T estimate a deal value when:**

❌ Call is too general ("just gathering information")

❌ Customer doesn't mention specific services OR pricing/budget

❌ Wrong number or misdirected call

❌ Complaint call without service discussion

❌ No Products & Services catalog AND customer doesn't mention prices/budget

❌ Transcription quality is too poor to analyze

{% hint style="success" %}
**Best Practice:** While the AI can work without a catalog, you'll get far more accurate and consistent deal value estimates by maintaining a Products & Services catalog. The catalog allows the AI to estimate based on your actual pricing structure, even when customers don't mention specific dollar amounts.
{% endhint %}

### Enabling Deal Value Estimation

To activate automatic deal value estimation:

1. Navigate to **Workspace Settings**
2. Go to the **AI Automation** tab
3. Make sure you have an OpenAI API key configured
4. Find "Automatically estimate deal value"
5. Toggle the switch to enable it
6. Click **Save** or **Update Workspace**

Once enabled, the AI will automatically estimate values for all new transcribed calls where customers discuss your products or services.

See the [AI Automation Setup Guide](https://help.ringtonic.app/guides/pages/crg7tMxXMDacQLAiSpgl#id-3.-set-up-ai-automation-with-openai) for complete details on enabling AI features.

{% hint style="success" %}
**What's Next?** After setting up your Products & Services catalog and enabling AI automation, Ring Tonic will automatically estimate deal values for every qualified call. Use these estimates to prioritize follow-ups, forecast revenue, and close more high-value deals.
{% endhint %}


# Campaigns

### What are Campaigns?

<figure><img src="/files/RyHYAQTvMhWjPSieM2OJ" alt=""><figcaption></figcaption></figure>

Campaigns help you track conversions from different marketing sources. Ring Tonic offers two types of campaigns to suit different marketing needs:

* **Website Tracker:** Tracks website visitors with form attribution and phone calls. Automatically swaps phone numbers and/or injects attribution data into forms based on visitor source. Perfect for tracking which online channels (organic search, paid ads, social media) drive conversions.
* **Static:** Uses one or more dedicated tracking numbers. Ideal for offline marketing like billboards, print ads, radio spots, or regional advertising campaigns. If your fixed number also sits on a website, you can add **Form Tracking** to capture that site's form leads too.

{% hint style="info" %}
Most businesses use Website Tracker campaigns for their website and Static campaigns for offline marketing materials. You can create as many campaigns as needed to track different marketing channels.
{% endhint %}

***

### When to Use Website Tracker vs Static

**Use** [**Website Tracker**](#id-1.-create-a-website-tracker-campaign) **when:**

* You want to track website visitors from different sources (Google Ads, Facebook Ads, organic search)
* You need to know which online marketing channel drove each call or form submission
* You want automatic phone number swapping based on visitor source
* You want to capture marketing attribution data (GCLID, UTM params) in your website forms

**Use** [**Static Campaigns**](#id-2.-create-a-static-campaign) **when:**

* You're running offline marketing (billboards, flyers, radio ads, TV commercials)
* You need one or more dedicated numbers for a specific campaign
* You want to track regional campaigns with different local numbers under one campaign
* You're tracking calls from a dedicated source that doesn't change (like a newsletter or email signature)
* You display a single fixed number on a website and want to capture that site's form leads, without phone-number swapping

***

### 1. Create a Website Tracker Campaign

Website Tracker campaigns let you track website conversions using phone calls, form submissions, or both.

{% hint style="info" %}
**New campaigns start without routing.** The Create form only asks for the basics — campaign name, tracking type, swap target, and number pool. After creating the campaign, you'll land on the campaign page where you can pick how calls reach you (forward to a number, attach a call flow, or build a new flow). See the [Call Flow Builder](/guides/call-flow-builder) for routing options.
{% endhint %}

#### Step 1: Configure Basic Information

1. Go to **Campaigns** → **Create Website Tracker**
2. Fill in the campaign details:
   * **Campaign name:** Choose a descriptive name (e.g., "Summer Website Campaign" or "2024 Google Ads")

#### Step 2: Choose What to Track

Select one, two, or all three tracking methods. The three are independent — enable whichever combination fits your use case.

* **Phone Calls** — Dynamically swaps phone numbers on your website to track call sources. Requires a pool of at least 2 tracking numbers.
* **Form Attribution** — Injects attribution data (GCLID, UTM params, etc.) into the customer's existing forms as hidden fields, so the customer's own backend keeps the attribution.
* **Form Submissions** *(Agency plan)* — Captures form submissions as leads in Ring Tonic itself: the moment a user clicks Submit, a beacon ships a copy of the form data to your Ring Tonic workspace as a [Contact](/guides/contacts), even if the customer's backend errors out. See [Form Submissions](/guides/form-submissions) for setup details.

{% hint style="info" %}
You must enable at least one tracking method. The three are independent — Form Attribution writes *into* the customer's form, Form Submissions sends a copy *out* to Ring Tonic, and Phone Calls swaps phone numbers on the page.
{% endhint %}

<figure><img src="/files/HkXijuGC03N2QhBNVwYF" alt=""><figcaption><p>Choose what to track: Phone Calls, Form Attribution, Form Submissions, or any combination</p></figcaption></figure>

**When Phone Calls is enabled**, the **Swap target** field appears:

* **Swap target:** Enter the phone number currently displayed on your website

{% hint style="info" %}
The swap target is the phone number visitors currently see on your site. Ring Tonic will automatically replace this number with tracking numbers from your pool. The forwarding number, voicemail, recording, and other routing settings are configured on the campaign page after creation.
{% endhint %}

<figure><img src="/files/fAu7XOJROmOrHBWQaTAh" alt=""><figcaption><p>Configure your Website Tracker campaign's basic information</p></figcaption></figure>

#### Step 3: Configure Number Pool (Phone Calls only)

This step only appears when **Phone Calls** tracking is enabled.

1. **Area code:** Enter a 3-digit area code (e.g., 206 for Seattle)
2. **Pool size:** Choose how many tracking numbers to create (2, 4, 8, 12, 16, or 20 numbers)

{% hint style="success" %}
**Best Practice:** Ring Tonic recommends 4 numbers per 100 daily website visitors. For example, if you get 500 visitors per day, choose a pool size of 20 numbers.
{% endhint %}

<figure><img src="/files/nrPdUI6QcUOIYxw4XGZ0" alt=""><figcaption><p>Configure your number pool size based on website traffic</p></figcaption></figure>

#### Step 4: Advanced Configuration (Phone Calls only)

This section only appears when **Phone Calls** tracking is enabled.

**CSS Selector** - If you want the script to only swap numbers in specific elements on your website:

1. Enter a CSS selector (e.g., `.phone-number` or `#contact-phone`)
2. Leave empty to swap all instances of your swap target number

**Common CSS selectors:**

* `.phone-number` - Elements with class "phone-number"
* `#contact-phone` - Element with ID "contact-phone"
* `.header .phone` - Elements with class "phone" inside header elements

<figure><img src="/files/OitgWkel0wDqcWOuR1uf" alt=""><figcaption><p>Use CSS selectors to target specific elements on your website</p></figcaption></figure>

#### Step 5: Configure Security

Add the domains where your tracking script should run:

1. Enter your domain (e.g., `example.com`)
2. Add additional domains if needed (e.g., `www.example.com`, `shop.example.com`)
3. Press Enter after each domain

{% hint style="warning" %}
**Security Notice:** The tracking script will only execute on domains you specify here. This prevents unauthorized use of your tracking numbers on other websites.
{% endhint %}

<figure><img src="/files/urG5LKGxtb3qN4Y7mThl" alt=""><figcaption><p>Specify which domains are allowed to use your tracking script</p></figcaption></figure>

#### Step 6: Configure Conditional Tracking (Phone Calls only)

This section only appears when **Phone Calls** tracking is enabled. Conditional Tracking lets you swap phone numbers only for visitors from specific marketing channels. This is useful when you manage some channels but not others, or when you want to use a smaller number pool for targeted tracking.

{% hint style="info" %}
Conditional Tracking only affects phone number swapping. If you have Form Attribution enabled, form attribution injection always works regardless of this setting.
{% endhint %}

<figure><img src="/files/fmvYSYadNSKfU910d4Sw" alt=""><figcaption><p>Conditional Tracking settings</p></figcaption></figure>

**Enable Conditional Tracking:**

1. Check **Only swap when marketing parameters are present**
2. Choose your parameter mode:

**Any Marketing Parameter Mode:**

* Numbers are swapped when visitors have any common marketing parameter
* Includes: gclid (Google Ads), fbclid (Facebook), msclkid (Microsoft Ads), ttclid (TikTok), utm\_source, utm\_medium, and more
* Best for: Tracking all paid/marketing traffic while ignoring organic visitors

**Specific Parameters Only Mode:**

* Numbers are swapped only for visitors with specific parameters you choose
* Select from a list of common parameters (gclid, fbclid, msclkid, utm\_source, etc.)
* Best for: Tracking specific channels like "Google Ads only" or "Facebook Ads only"

{% hint style="warning" %}
**Important:** Visitors without the required parameters will see your original phone number and won't be tracked for calls. They won't appear in your call analytics. However, form attribution injection still works for these visitors if Form Attribution tracking is enabled.
{% endhint %}

{% hint style="success" %}
**Use Case Example:** You run Google Ads but your client manages their own Facebook Ads. Enable Conditional Tracking with "Specific parameters only" and select just `gclid`. Now only Google Ads visitors get tracked with phone swapping, reducing your number pool needs and keeping tracking focused on what you manage.
{% endhint %}

#### Step 7: Configure Form Attribution (Form Attribution only)

This section only appears when **Form Attribution** tracking is enabled. Form Attribution automatically adds marketing attribution data (GCLID, FBCLID, UTM parameters, Google Analytics IDs) as hidden fields into forms on your website. When visitors submit a form, you capture the same attribution data that's tracked with phone calls.

<figure><img src="/files/5j0FOGsVxyoRTZMmEHNQ" alt=""><figcaption><p>Form Attribution settings</p></figcaption></figure>

**Configure Form Attribution:**

1. Configure optional settings:

**Form Selector (Optional):**

* Enter a CSS selector to target specific forms (e.g., `#contact-form` or `.lead-form`)
* Leave empty to inject into all forms on the page

**Field Name Prefix (Optional):**

* Add a prefix to all injected field names (e.g., `ct_` creates fields like `ct_gclid`, `ct_utm_source`)
* Useful to avoid conflicts with existing form fields
* Must start with a letter or underscore, and contain only letters, numbers, and underscores

**Custom Field Mapping (Optional):**

* Rename specific fields to match your CRM or form processor requirements
* For example, map `gclid` to `google_click_id` if your CRM expects that field name

<figure><img src="/files/q54EyDONwwZboJvh4DuW" alt="" width="563"><figcaption><p>Custom field mapping</p></figcaption></figure>

{% hint style="info" %}
**What data is injected?** Ring Tonic injects the following fields (only when they have values):

* **Click IDs:** gclid, gbraid, wbraid (Google), fbclid (Facebook), msclkid (Microsoft), ttclid (TikTok), li\_fat\_id (LinkedIn)
* **UTM Parameters:** utm\_source, utm\_medium, utm\_campaign, utm\_term, utm\_content
* **Google Analytics:** ga\_client\_id, ga\_session\_id
  {% endhint %}

{% hint style="success" %}
**Debug Mode:** Add `?ct_debug=true` to your URL to make injected fields visible and fetch fresh settings from the server. This bypasses the session cache, so you can test configuration changes immediately without waiting for sessions to expire.
{% endhint %}

<figure><img src="/files/69Agwkl4afY64B6RrCBR" alt="" width="563"><figcaption><p>Form attribution injection with debug mode on</p></figcaption></figure>

#### Step 8: Configure Form Submissions (Form Submissions only — Agency plan)

This section only appears when **Form Submissions** tracking is enabled (Agency plan). Form Submissions captures the customer's form submissions as leads in Ring Tonic, even if the customer's backend errors out.

Configure these settings:

* **Honeypot field name** *(optional)* — name of a hidden form field that bots typically fill (e.g. `rt_website`). Submissions where this field has a value are silently dropped.
* **Field mapping** — tell Ring Tonic which form fields correspond to `name`, `email`, `phone`, `company`, `value`, or any custom field. Selectors can be CSS (`input[name="email"]`) or input names.
* **Origin allowlist override** *(optional)* — restrict the form-submission endpoint to specific hostnames, separate from the tracking script's general Allowed domains.

See the dedicated [Form Submissions](/guides/form-submissions) guide for the full reference, including how submissions flow into the [Contacts](/guides/contacts) pipeline.

{% hint style="info" %}
**Form Submissions vs. Form Attribution:** Form Attribution writes data *into* the customer's existing form so the customer's backend keeps the attribution. Form Submissions sends a copy of the submission *out* to Ring Tonic so you have the lead regardless of the customer's backend. Enable both for full coverage.
{% endhint %}

#### Step 9: Bot Detection (Phone Calls only)

This section only appears when **Phone Calls** tracking is enabled.

1. **Bot detection** is enabled by default for all Website Tracker campaigns
2. Uncheck to disable if you want bots and crawlers to receive tracking numbers

{% hint style="info" %}
**What is bot detection?** Bot detection automatically identifies web crawlers and bots (like Googlebot, Bingbot, and other search engine crawlers) and prevents them from being assigned tracking numbers. This preserves your number pool for real visitors and ensures accurate analytics.
{% endhint %}

{% hint style="success" %}
**Why keep bot detection enabled?** Search engine crawlers regularly visit your website to index content. Without bot detection, these automated visits would consume tracking numbers from your pool, reducing availability for real visitors and skewing your analytics data.
{% endhint %}

#### Step 10: Create Campaign

Click **Create Campaign** to provision your tracking numbers and create the campaign.

{% hint style="success" %}
Ring Tonic will automatically search for available numbers in your chosen area code and create your number pool. This process takes just a few seconds.
{% endhint %}

#### Step 11: Pick Routing on the Campaign Page

After creating, you'll land on the campaign page where you can pick how calls reach you. See [Configure Routing](#id-3.-configure-routing) below for full setup details on each mode.

#### Step 12: Install the Tracking Script

After creating your Website Tracker campaign, you need to add the tracking script to your website. This script handles both phone number swapping and form attribution injection depending on your campaign configuration.

**Step 1: Copy the Script**

1. Go to your campaign details page
2. Copy the installation script from the "Installation" section

The script looks like this:

```html
<script id="ct-script" src="https://ringtonic.app/swap.js" data-campaign-id="{campaign-uuid}" defer></script>
```

{% hint style="info" %}
If you only have **Form Attribution** enabled (no phone tracking), the same script is used. It will only inject attribution data into forms without swapping any phone numbers.
{% endhint %}

<figure><img src="/files/n3efIXBwSvsFutM8SZ6A" alt=""><figcaption><p>Copy the tracking script from your campaign details page</p></figcaption></figure>

**Step 2: Add to Your Website**

1. Paste the script before the closing `</body>` tag on every page where you want to track conversions
2. Save and publish your changes

The script will automatically find and swap phone numbers matching your swap target (if phone tracking is enabled) and inject attribution data into forms (if form tracking is enabled).

**Example:**

```html
<!DOCTYPE html>
<html>
<head>
   <title>Your Website</title>
</head>
<body>
<!-- Your website content -->
<h1>Contact Us</h1>
<p>Call us at: <span class="phone-number">+1 (206) 555-0123</span></p>

<!-- Add Ring Tonic script before closing body tag -->
<script id="ct-script" src="https://yourdomain.com/swap.js" data-campaign-id="abc123def456" defer></script>
</body>
</html>
```

{% hint style="info" %}
If you specified a CSS selector, the script will only swap numbers in those specific elements. Otherwise, it swaps all instances of your swap target number.
{% endhint %}

**Step 3: Test Your Installation**

1. Visit your website
2. If phone tracking is enabled, check that phone numbers are being swapped to tracking numbers
3. If form tracking is enabled, add `?ct_debug=true` to your URL to verify hidden fields are being injected into your forms
4. Call one of the tracking numbers to verify calls are forwarding correctly (if applicable)

{% hint style="success" %}
The script only runs on allowed domains you specified during setup. If testing on localhost or a staging domain, make sure to add it to your allowed domains list.
{% endhint %}

#### GDPR Privacy Compliance (Optional)

If your website serves visitors from the EU or California, you may need to delay tracking until visitors accept your cookie consent banner. Ring Tonic supports GDPR-compliant installation by allowing you to manually start tracking after consent is given.

<figure><img src="/files/XOgbN7m3CxPuGG24u8KW" alt=""><figcaption><p>GDPR Privacy Compliance Instruction in the Campaign Detail Page</p></figcaption></figure>

**Step 1: Use the Deferred Script**

Add `data-auto-start="false"` to prevent automatic tracking when the page loads:

```html
<script id="ct-script" src="https://ringtonic.app/swap.js" data-campaign-id="{campaign-uuid}" data-auto-start="false" defer></script>
```

{% hint style="info" %}
With `data-auto-start="false"`, the script loads but does **not** swap phone numbers or inject form data until you explicitly call `window.RingTonic.init()`.
{% endhint %}

**Step 2: Start Tracking After Consent**

Call `window.RingTonic.init()` when the user accepts cookies in your consent manager:

```html
<script>
  // Call this after user accepts cookies
  CookieBanner.on('accept', function() {
      window.RingTonic.init();
  });
</script>
```

{% hint style="warning" %}
Replace `CookieBanner.on('accept', ...)` with the callback from your cookie consent manager (Cookiebot, OneTrust, CookieYes, etc.). Each provider has different callback syntax.
{% endhint %}

**Common Cookie Consent Manager Examples:**

| Provider      | Callback Example                                                                                                                                |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| **Cookiebot** | `window.addEventListener('CookiebotOnAccept', function() { window.RingTonic.init(); });`                                                        |
| **OneTrust**  | `OneTrust.OnConsentChanged(function() { if (OnetrustActiveGroups.includes('C0002')) window.RingTonic.init(); });`                               |
| **CookieYes** | `document.addEventListener('cookieyes_consent_update', function(e) { if (e.detail.accepted.includes('analytics')) window.RingTonic.init(); });` |

{% hint style="success" %}
**How it works:** When visitors arrive without consent, they see your original phone number and forms without attribution fields. After they accept cookies and `window.RingTonic.init()` is called, the script swaps in the tracking number and injects attribution data into forms. This ensures you only track visitors who have explicitly consented.
{% endhint %}

{% hint style="info" %}
**IP Anonymization:** Ring Tonic automatically anonymizes visitor IP addresses for GDPR compliance. The last octet of IPv4 addresses (e.g., `192.168.1.100` → `192.168.1.0`) and the last 64 bits of IPv6 addresses are zeroed before storage.
{% endhint %}

#### Disabling Phone Tracking on an Existing Campaign

If you need to switch an existing Website Tracker campaign from phone + form tracking to form-only:

1. Go to the campaign's **Edit** page
2. Uncheck **Phone Calls** under "What would you like to track?"
3. A confirmation dialog will appear warning you that inbound calls to your tracking numbers will be rejected
4. Click **Disable Phone Tracking** to confirm

{% hint style="info" %}
**Settings are preserved.** When you disable phone tracking, your simple routing settings (forwarding number, call recording, whisper, voicemail, etc.) and any attached call flow are saved. If you re-enable phone tracking later, your previous routing configuration will be restored.
{% endhint %}

{% hint style="warning" %}
**Tracking numbers remain assigned** but inbound calls will be rejected with a busy signal. You cannot assign new tracking numbers to a campaign with phone tracking disabled.
{% endhint %}

{% hint style="info" %}
**Routing config is hidden while phone tracking is off.** Since calls are rejected anyway, the routing card (simple routing summary, attached call flow, or routing picker) is hidden from the campaign page. Re-enabling phone tracking restores the routing card with your previous settings intact.
{% endhint %}

***

### 2. Create a Static Campaign

Static campaigns use one or more dedicated tracking numbers, perfect for offline marketing materials and regional campaigns.

{% hint style="info" %}
**New campaigns start without routing.** The Create form only asks for the basics — campaign name and tracking number(s). After creating the campaign, you'll land on the campaign page where you can pick how calls reach you (forward to a number, attach a call flow, or build a new flow). See the [Call Flow Builder](/guides/call-flow-builder) for routing options.
{% endhint %}

#### Step 1: Configure Basic Information

1. Go to **Campaigns** → **Create Static Campaign**
2. Fill in the campaign details:
   * **Campaign name:** Choose a descriptive name (e.g., "Facebook Ads Campaign" or "Billboard - Highway 101")

<figure><img src="/files/NZX0nLBBwh5RV61NPOPG" alt=""><figcaption><p>Configure your static campaign's basic information</p></figcaption></figure>

#### Step 2: Choose Number Source

Ring Tonic gives you two options for getting tracking numbers. You can select multiple numbers to add to a single campaign.

**Option 1: Purchase New Numbers**

Perfect when you want fresh numbers with specific criteria:

1. Select **Purchase new number**
2. Choose your **Country** (e.g., United States)
3. **Basic Filters:**
   * **City/Locality:** Narrow down to specific cities (e.g., Phoenix, Scottsdale)
   * **Area Code:** Enter a 3-digit area code (e.g., 206)
   * **State/Territory:** Select your preferred state or region
   * **ZIP Code:** Search by postal code for local numbers
4. **Advanced Filters** (Optional):
   * **Contains Digits:** Find numbers with specific digit patterns
     * Choose "Starts with" or "Anywhere" for digit position
     * Enter at least 2 digits (e.g., "55" to find numbers like 555-XXXX)
5. Click **Search Numbers** to find available numbers
6. Browse results showing:
   * Phone number with location details
   * Voice/SMS/MMS capabilities
   * Monthly price
7. Click **Select** to add a number to your selection

**Selecting Multiple Numbers:**

You can select multiple numbers from different searches to add to your campaign:

1. Select numbers from the search results by clicking **Select**
2. Selected numbers appear in the **Selected Numbers** panel above the search results
3. Change your search filters (different state, area code, etc.) and search again
4. Select additional numbers - your previous selections are preserved
5. Remove numbers from the selection by clicking the **X** on any selected number
6. Use **Clear all** to remove all selected numbers

{% hint style="info" %}
**Tip:** Only group numbers that belong to the same marketing source. For example, you might add multiple local numbers for the same radio ad campaign running in different cities.
{% endhint %}

{% hint style="success" %}
**Pro Tip:** Use the "Contains Digits" filter to find memorable or vanity numbers. For example, searching for "777" might find numbers like (206) 777-5555.
{% endhint %}

<figure><img src="/files/j1AKJGfj4XHEvksdv9U6" alt=""><figcaption><p>Search for new numbers with advanced filtering options</p></figcaption></figure>

**Option 2: Use Existing Numbers**

Select unassigned phone numbers from your inventory:

1. Select **Use existing number**
2. Ring Tonic displays all unassigned phone numbers from your inventory
3. Browse available numbers showing:
   * Phone number (formatted)
   * Friendly name (if set)
4. Click **Select** on the numbers you want to use
5. Selected numbers appear in the **Selected Numbers** panel
6. Remove numbers by clicking the **X** on any selected number

{% hint style="info" %}
Only unassigned numbers appear in this list. If you need to use a number that's currently assigned to another campaign, you'll need to unassign it first from the [Phone Numbers](/guides/phone-numbers) page.
{% endhint %}

{% hint style="warning" %}
**No Numbers Available?** If you don't have any unassigned numbers in your inventory, you'll need to either:

* Purchase a new number using Option 1 above, or
* [Import existing numbers from Twilio](/guides/phone-numbers#importing-numbers-from-twilio) into your inventory first
  {% endhint %}

<figure><img src="/files/A9Muhr9oQpyoQQG0trXE" alt=""><figcaption><p>Select from unassigned numbers in your inventory</p></figcaption></figure>

#### Step 3: Add Form Tracking (Optional)

If your static number lives on a website, you can capture that site's form leads alongside your calls. In the **Form Tracking** card, enable either or both:

* **Form Attribution** — injects hidden attribution fields (GCLID, UTM parameters, and more) into the website's existing forms, so the marketing data travels with the lead into your own CRM.
* **Form Submissions** *(Agency plan)* — sends a copy of each submission to Ring Tonic as a [Contact](/guides/contacts) the instant the visitor clicks Submit, even if the website's own form fails.

When you enable either option, an **Allowed domains** field appears — add the website's domain there (Form Submissions requires at least one). These are the same options offered on Website Tracker campaigns, just without phone-number swapping. See the [Website Tracker setup](#id-1.-create-a-website-tracker-campaign) for the full Form Attribution reference and the [Form Submissions](/guides/form-submissions) guide for Form Submissions setup.

<figure><img src="/files/0UtTu6a015F3xhbHQV1q" alt=""><figcaption><p>The Form Tracking card on a Static campaign, with Form Attribution and Form Submissions options</p></figcaption></figure>

{% hint style="info" %}
**Calls keep using your static number.** Form Tracking runs alongside your fixed number — it never swaps numbers. After you create the campaign with Form Tracking on, the campaign page shows a tracking-script snippet to install on the website (the same script Website Tracker campaigns use).
{% endhint %}

#### Step 4: Create Campaign

Click **Create Campaign** to purchase the tracking numbers and create your campaign. The button will show the number of selected numbers (e.g., "Create Campaign with 3 Numbers").

{% hint style="success" %}
Your tracking numbers are now active! You can use them immediately in your marketing materials. All calls to these numbers will be logged in Ring Tonic with full tracking and analytics under this single campaign.
{% endhint %}

<figure><img src="/files/uHX0mG6qWlUvJjBBorYK" alt=""><figcaption><p>Your static campaign is created and ready to use</p></figcaption></figure>

#### Step 5: Pick Routing on the Campaign Page

After creating, you'll land on the campaign page where you can pick how calls reach you. See [Configure Routing](#id-3.-configure-routing) below for full setup details on each mode.

#### Step 6: Set Ad Locations (Optional)

For billboards, print ads, and other physical marketing, you can set the exact location where your ad is placed. This enables the **Billboard Rule** on [Money Map](https://help.ringtonic.app/guides/pages/FqrMOC4HeyPH7W0Eqtdm#id-4.-money-map)—showing calls at your ad placement instead of caller locations.

<figure><img src="/files/iZFLxpWAb2WBp6TWlDZk" alt=""><figcaption><p>Set Ad Locations for a Tracking Number</p></figcaption></figure>

**How to Set an Ad Location:**

1. Go to your static campaign's **Edit** page
2. Find the tracking number in the **Tracking Numbers** section
3. Click the **Set Location button** next to the number
4. Search for an address or move the pin on the map to set the location
5. Optionally add a **Location Label** (e.g., "Highway 101 Billboard")
6. Click **Save Location**

{% hint style="info" %}
**When to use Ad Locations:** Billboards, print ads, flyers, vehicle wraps, trade show booths—any physical marketing with a known location.
{% endhint %}

{% hint style="warning" %}
**No ad location set?** Calls will appear on Money Map at the caller's location (based on their phone number). This works fine for tracking call volume, but won't show where your physical ad is placed.
{% endhint %}

#### Step 7: Report Google Ads Call Asset Calls (Optional)

If this number is the destination of a **Google Ads call asset**, you can report qualified calls back to Google Ads as conversions — so Smart Bidding learns which keywords produce calls worth having.

Open the campaign's **Edit** page and tick **This number receives calls forwarded from a Google Ads call asset** in the **Google Ads Call Assets** card, then click **Update Campaign**.

<figure><img src="/files/LyTGQCeBnEkLWsaRudU2" alt=""><figcaption><p>The Google Ads Call Assets card on a static campaign's Edit page</p></figcaption></figure>

{% hint style="info" %}
This also needs **call reporting** enabled in your Google Ads account and a conversion action for imported calls. See [Calls from Google Ads Call Assets](/guides/google-ads-integration#calls-from-google-a-ds-call-assets) for the full setup.
{% endhint %}

***

### 3. Configure Routing

After creating a campaign, you'll land on the campaign page where you decide how incoming calls reach you. Ring Tonic offers three routing modes:

* **Forward to a number** — Send calls straight to a single business line. Includes optional voicemail, call recording, whisper messages, call screening, spam filter, and transcription keyword spotting. Best for solo operators or single-destination routing.
* **Attach a call flow** — Use a published [call flow](/guides/call-flow-builder) for IVR menus, business hours, multi-destination ring groups, tags, conditional branching, and SMS follow-ups. Best for teams or multi-step intake.
* **Build a new flow** — Open the [call flow builder](/guides/call-flow-builder) right from the campaign page and design routing from scratch. Publishing the new flow auto-attaches it to this campaign — no return trip required.

<figure><img src="/files/cDvIy14gqD3W5AHhAXj0" alt=""><figcaption><p>Routing picker on the campaign page with three mode cards</p></figcaption></figure>

{% hint style="warning" %}
**Until you pick a routing mode, inbound calls fail.** A campaign with phone tracking enabled but no forward number and no attached call flow rejects callers with an error message. The campaign page shows a red **"Routing not configured"** alert above the picker, and the **Campaigns** index lists the campaign with a yellow **"Setup required"** badge — both as reminders to finish setup.
{% endhint %}

{% hint style="info" %}
**You can switch modes anytime.** Once a routing mode is configured, the campaign page shows a **Switch routing mode** button that lets you swap between simple routing and a call flow without recreating the campaign. Your existing settings are preserved across switches — going from simple to a call flow doesn't delete your forward number, and detaching a flow brings back any saved simple routing config. See [Switching Routing Modes](#switching-routing-modes) below.
{% endhint %}

#### Configure Simple Routing

Pick **Forward to a number** on the routing picker to open the simple routing dialog.

{% stepper %}
{% step %}
**Forward to**

Enter the phone number where calls should be forwarded — your business line, mobile, or call center.
{% endstep %}

{% step %}
**Voicemail (Optional)**

Choose how unanswered calls are handled:

* **Off** — Calls disconnect after the forward number rings out
* **Record** — Plays a greeting then records the caller's message (with transcription)
* **Greeting only** — Plays a message and hangs up (good for after-hours)

For Record and Greeting-only modes:

* **Greeting type:** Text-to-speech or upload an MP3
* **Greeting text/file:** Your message
* **Voice and language:** Used when greeting type is Text
  {% endstep %}

{% step %}
**Call Recording (Optional)**

Toggle on to record forwarded calls. Recordings appear in Call History with playback, transcription, and AI-powered call summaries.

{% hint style="warning" %}
**Two-party consent:** Some US states (California, Florida, Washington) require both parties to consent to recording. Combine recording with a Whisper or Greeting that informs callers the call is being recorded.
{% endhint %}
{% endstep %}

{% step %}
**Whisper Message (Optional)**

Plays a short message to the answering agent before connecting the caller. Templates support variables like `{{caller_number}}` and `{{campaign_name}}`.

Example: `Incoming call from {{caller_number}} via the {{campaign_name}} campaign.`

{% hint style="success" %}
**Why use whisper?** Even a one-line whisper dramatically improves agent context and pickup speed. Combine with **Call Screening** (below) to prevent carrier voicemail from stealing calls.
{% endhint %}
{% endstep %}

{% step %}
**Call Screening (Optional)**

Adds a "press 1 to accept" prompt on **your** end — the phone the call is forwarded to — before the caller is connected. When your phone answers, you hear a short prompt and press 1 to take the call.

Its purpose is to stop **carrier voicemail from answering on your behalf**. A voicemail system can't press a key, so if your mobile or desk voicemail picks up, Ring Tonic treats the call as unanswered and hands it to your Ring Tonic voicemail instead — meaning the greeting your callers hear, and the message you receive, are the ones you set up here rather than your personal voicemail.

{% hint style="warning" %}
With Call Screening on, every forwarded call asks the person answering to press 1 before connecting. That's the trade-off for keeping carrier voicemail out. The caller just hears normal ringing while this happens.
{% endhint %}
{% endstep %}

{% step %}
**Spam Filter (Optional)**

Toggle on to add a "press 1 to connect" gate before the call rings your forward number. This filters out 80%+ of robocaller traffic — silent bots can't press a digit.

{% hint style="info" %}
**Spam Filter vs. Call Screening.** Both use a "press 1" prompt, but on opposite ends of the call:

* **Spam Filter** screens the **caller** — before your phone even rings, so robocallers never reach you.
* **Call Screening** screens the **answering phone** — so a carrier voicemail picking up doesn't get counted as an answered call.

You can turn on either, both, or neither.
{% endhint %}
{% endstep %}

{% step %}
**Transcription Keywords (Optional)**

Add keywords or phrases to highlight in call transcriptions (e.g., "appointment", "quote", "unsubscribe"). Hits appear in Call History and trigger optional notifications.
{% endstep %}

{% step %}
**Save**

Click **Save**. The campaign page now shows the simple routing summary card with **Edit** and **Switch routing mode** buttons.

<figure><img src="/files/lQgEtL6iVNxBrOZvFAvj" alt=""><figcaption><p>Simple routing summary card after configuration</p></figcaption></figure>
{% endstep %}
{% endstepper %}

#### Editing Simple Routing

Click **Edit** on the routing summary card to reopen the dialog and update any field. Changes apply to the next inbound call.

#### Switching Routing Modes

To switch from simple routing to a call flow (or vice versa), click **Switch routing mode** on the active routing card.

{% stepper %}
{% step %}
**Confirm the switch**

A dialog summarises what will happen. Your existing settings are preserved either way — your simple routing config stays saved on the campaign while a flow is attached, and detaching a flow brings back those saved values.
{% endstep %}

{% step %}
**Set up the new mode**

After confirming, the next mode's setup dialog opens automatically:

* Switching from **simple → flow** opens the **Attach a Call Flow** picker
* Switching from **flow → simple** opens the **Forward to a number** dialog (pre-filled with your previous values, if any)

You can configure the new mode immediately without returning to the routing picker.
{% endstep %}
{% endstepper %}

{% hint style="success" %}
**Switching is non-destructive.** Detaching a call flow only removes the link to the flow; the flow itself isn't deleted and can be re-attached to this or any other campaign. Your simple routing settings are preserved across switches — they go inactive while a flow is handling calls, and become active again when you switch back.
{% endhint %}

***

### 4. Campaign Timezone

By default, every campaign reports its call times in your **workspace timezone**. On the **Agency plan**, you can give an individual campaign its own timezone — useful when you run campaigns for clients in different regions and want each one's call times shown in that client's local time.

{% hint style="info" %}
**Agency plan feature.** Per-campaign timezones are available on the Agency plan. On other plans the setting is visible but locked, with an option to upgrade. Every campaign still reports in your workspace timezone by default.
{% endhint %}

#### Set a Campaign Timezone

{% stepper %}
{% step %}
**Open the campaign**

Go to **Campaigns** and click the campaign you want to configure. The **Timezone** card is near the top of the campaign page.
{% endstep %}

{% step %}
**Choose a timezone**

Open the dropdown and pick a timezone, or type a city to search (e.g. "New York"). To keep the default, leave **Inherit from workspace** selected.
{% endstep %}

{% step %}
**Save**

Click **Save timezone**. The card updates to "Currently showing times in …", and a **Times shown in …** label appears at the top of the campaign so the active timezone is always clear.

<figure><img src="/files/zvPDr8hZbGJwuXQtDJWx" alt=""><figcaption><p>The Timezone card on the campaign page with a custom timezone selected</p></figcaption></figure>
{% endstep %}
{% endstepper %}

#### Where the Campaign Timezone Applies

Once a campaign has its own timezone, that timezone is used everywhere the campaign's call times appear:

| Surface                          | What you'll see                                                                                                                                                                                                              |
| -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Shared & white-label reports** | The client-facing report for the campaign shows all times in the campaign timezone, labelled in the header.                                                                                                                  |
| **Call detail**                  | A call's times — including the Lead and Timeline tabs — display in its campaign's timezone, with a **Times shown in …** label.                                                                                               |
| **Call Activity list**           | Each call appears in its own campaign's timezone, tagged with the zone (for example "EDT") when it differs from your workspace. Filtering the list to a single campaign switches the whole view to that campaign's timezone. |

{% hint style="info" %}
**The "Times shown in …" label.** Whenever times appear in a campaign timezone that differs from your workspace timezone, Ring Tonic adds a small **Times shown in …** label — so you and your clients are never unsure which timezone you're reading, even when several campaigns run in different regions.
{% endhint %}

#### Reset to the Workspace Timezone

To return a campaign to your workspace timezone, open the **Timezone** card, choose **Inherit from workspace**, and click **Save timezone**.

{% hint style="info" %}
Your **workspace timezone** is set under **Settings → Workspace**. See [Configure Currency, Language & Branding, Timezone](/guides/setup-workspace#timezone). Changing it updates every campaign that inherits the workspace timezone.
{% endhint %}

#### What Happens If You Downgrade

If you move from the Agency plan to another plan, any custom campaign timezones are **paused, not lost**:

* Saved timezones are kept, but call times revert to your workspace timezone everywhere.
* The campaign's **Timezone** card shows the saved timezone with a note that it's paused.
* Upgrading back to the Agency plan automatically resumes your campaign timezones.
* You can also reset a paused campaign to **Inherit from workspace** at any time.

***

### 5. Delete Campaigns

If you no longer need a campaign, you can delete it to stop tracking and release the phone numbers.

#### How to Delete a Campaign

1. Go to **Campaigns**
2. Find the campaign you want to delete
3. Click **Delete** (trash icon)
4. Read the confirmation message carefully
5. Click **Delete** to confirm

{% hint style="danger" %}
**Warning:** Deleting a campaign will permanently delete:

* All associated call logs
* All tracking numbers (released back to Twilio)
* All campaign analytics data
* This action cannot be undone

Make sure to export any important data before deleting a campaign.
{% endhint %}

<figure><img src="/files/2ZwNIz6oZFulmgkZ8PCG" alt="" width="563"><figcaption><p>Confirm campaign deletion - this action is permanent</p></figcaption></figure>

***

### 6. Share Campaigns

Share campaign analytics with clients via a secure public link—no Ring Tonic account required.

1. Select a campaign → Click **Share**
2. Toggle **Enable sharing** to generate your link
3. Optionally add password protection

Clients get read-only access to call activity, attribution, tracking number performance, and money map with your workspace branding.

{% hint style="info" %}
See [Share Campaign](/guides/share-campaign) for full details on password protection, white-label branding, and link management.
{% endhint %}

***

### 7. Voicemail Features

When voicemail is enabled, Ring Tonic provides the same AI-powered features for voicemails as live calls.

#### Call Status

| Status        | When Used                                                  |
| ------------- | ---------------------------------------------------------- |
| **Voicemail** | Caller left a message (Record mode)                        |
| **No Answer** | Play greeting only mode, or ghost voicemails (< 3 seconds) |

#### AI Features for Voicemails

<figure><img src="/files/6psYVbOZRQjm6676jaqS" alt=""><figcaption><p>AI features for voicemails</p></figcaption></figure>

All voicemail features require **Transcribe voicemails** to be enabled:

* **Transcription** - Voicemails are automatically transcribed using your configured provider (Deepgram/AssemblyAI)
* **Keyword spotting** - Campaign keywords are detected and highlighted in voicemail transcriptions
* **AI lead qualification** - Voicemails are auto-qualified using your workspace's qualification guidelines, just like live calls
* **Deal value estimation** - AI estimates potential deal value from voicemail content (if enabled)

{% hint style="success" %}
**Voicemails in analytics:** Voicemail metrics appear in Call Activity, Tracking Number Performance, and Attribution reports—helping you track which sources drive voicemails.
{% endhint %}


# Call Flow Builder

### What is the Call Flow Builder?

The Call Flow Builder is a visual, drag-and-drop editor for designing how incoming calls are routed, greeted, and qualified — without writing a single line of code. Instead of a single "forward to this number, else voicemail" rule, you can build a tree of decisions: greet the caller, ask them to press a key, check business hours, route to a team, tag the call, send a follow-up SMS, and more.

<figure><img src="/files/yigUWRUR52EUuTFs3HZr" alt=""><figcaption><p>The flow builder canvas with a published IVR flow</p></figcaption></figure>

{% hint style="info" %}
**Use cases at a glance:** Press-1-to-connect spam filters, time-of-day routing (open vs. closed), multi-agent ring groups, VIP repeat-caller lanes, consent-driven SMS follow-ups, and mid-call CRM lookups with dynamic branching.
{% endhint %}

{% hint style="warning" %}
**Plan availability:** All plans can use every node type **except** Agent Queue and Webhook, which require **Agency** because they depend on Agency-only infrastructure (the browser dialer for Agent Queue, API + webhook access for Webhook).

Templates, simulation mode, and full Flow Analytics are available on every plan.
{% endhint %}

***

### Before You Start

{% hint style="info" %}
**New campaigns start without routing.** When you create a new campaign, you'll land on the campaign page with a routing picker. Pick "Use a call flow" and attach the flow you just published — that's how a freshly-created campaign gets connected to a flow.
{% endhint %}

{% stepper %}
{% step %}
**Confirm your Twilio setup is working**

Calls can only be routed through flows if your tracking numbers are already receiving calls. If you haven't imported numbers yet, do that first — see the [Phone Numbers guide](/guides/phone-numbers).
{% endstep %}

{% step %}
**Decide which campaign will use the flow**

Flows are **reusable** — one flow can power many campaigns. Pick the campaign you want to upgrade from a simple forward rule to a full IVR, or create a new campaign for it.
{% endstep %}

{% step %}
**(Optional) Set up ElevenLabs for AI voices**

If you want natural-sounding AI voices instead of Twilio's built-in voices, add your ElevenLabs API key to your workspace. See [Voice and audio (ElevenLabs voices)](https://help.ringtonic.app/guides/setup-workspace#voice-and-audio-elevenlabs-voices-optional) in the Setup Workspace guide.
{% endstep %}

{% step %}
**(US only, required for SMS) Register for A2P 10DLC**

If your flow uses **SMS** or **Opt-In / Consent** nodes and your sending number is a US 10-digit long code, you must register the number for A2P 10DLC before any text messages will deliver. US carriers silently block messages from unregistered 10DLC numbers — Twilio reports the send as accepted but the message never reaches the recipient.

* Register via the [Twilio Console A2P 10DLC flow](https://console.twilio.com/us1/develop/sms/regulatory-compliance/a2p-onboarding?activeStep=usA2POnboarding:customerProfileRegistration:businessProfileNeeds) — brand registration takes \~1 business day, campaign approval \~1–3 business days.
* Toll-free numbers have a simpler [verification path](https://www.twilio.com/docs/messaging/compliance/toll-free/console-onboarding) and are a good alternative for low-volume use cases.
* See the [Twilio A2P 10DLC guide](https://www.twilio.com/docs/messaging/compliance/a2p-10dlc) for the full process.

{% hint style="warning" %}
Carrier filtering blocks unregistered 10DLC traffic with Twilio error code **30034**. Ring Tonic surfaces this in the call's **Timeline** tab so you can see exactly which messages were blocked and why.
{% endhint %}
{% endstep %}
{% endstepper %}

***

### Creating Your First Flow

{% stepper %}
{% step %}
**Open the Call Flows page**

Go to **Call Flows** in the sidebar and click **Create Flow**. Give it a name (e.g., "Main Inbound IVR") and an optional description.

<figure><img src="/files/uZkmfYjHlhq2wn7StJBi" alt=""><figcaption><p>Create Flow dialog with name and description</p></figcaption></figure>
{% endstep %}

{% step %}
**Pick a starting point: Blank or template**

The Create Flow dialog has a tabbed picker on the left:

* **Templates** — Built-in starting points: Simple Forwarding, IVR Menu, Business Hours, Sales Team, Spam Filter + Forward, Multi-Location, Simultaneous Ring, Voicemail Only, VIP Tag Routing, and Webhook Smart Routing — plus five AI-powered templates built around the AI Agent node: AI Receptionist, After-Hours AI Answering, AI Missed-Call Rescue, AI Appointment Booking, and AI Lead Qualifier (see [AI Call Answering](/guides/ai-call-answering#start-from-a-template)). Each pre-fills a working flow with all fallback edges already wired, so you only need to swap in your own phone numbers and prompts before publishing.
* **My Templates** — Custom templates you've saved from your own flows. See [Saving a flow as a custom template](#saving-a-flow-as-a-custom-template) below.
* **Blank Flow** — Start from an empty canvas with just a Start node.

Picking a template pre-fills the name field; you can override it before clicking **Create Flow**.
{% endstep %}

{% step %}
**Land on the canvas**

You'll see your starting graph — either a blank canvas with a single **Start** node, or the template's pre-built nodes ready to customize. Every flow has exactly one Start — it's your caller's entry point.
{% endstep %}

{% step %}
**Add your first node**

Click the **+** button on the Start node to open the node picker. Pick a node type (e.g., "Greeting") — Ring Tonic automatically places and connects it to Start.

<figure><img src="/files/AtJ4kksF9h4okci3UPN5" alt=""><figcaption><p>Node picker showing all available node types grouped by category</p></figcaption></figure>

{% hint style="success" %}
**Auto-layout:** Ring Tonic lays out nodes for you automatically using a top-down tree. You don't need to drag nodes around — just click to add, and the canvas organizes itself.
{% endhint %}
{% endstep %}

{% step %}
**Configure the node**

Click any node to open its configuration panel on the right. Each node has different settings — for example, a Greeting node lets you pick an audio provider, type the message, and choose a voice.

<figure><img src="/files/kq1sQMcBximFTxrYrFd6" alt=""><figcaption><p>Node configuration panel on the right side of the canvas</p></figcaption></figure>
{% endstep %}

{% step %}
**Keep adding nodes**

Repeat for each step your flow needs: a Menu for keypress options, Dial to forward, Voicemail as a fallback, and a Hangup at the end. Each node's output ports (the small handles under it) auto-connect to the next node you add.
{% endstep %}

{% step %}
**Publish the flow**

Click **Publish** in the top-right. Ring Tonic validates the flow — no orphan nodes, every path leads to a terminal, all required configs are set — and snapshots it as version 1. Only published versions answer real calls.

<figure><img src="/files/ymwxByyOIyqVaUWq1b4B" alt=""><figcaption><p>Publish dialog with version note and strict validation results</p></figcaption></figure>
{% endstep %}
{% endstepper %}

#### Saving a flow as a custom template

Once you've built a flow you'd like to reuse — e.g., a polished intake pattern your agency uses across many client campaigns — save it as a custom template so it appears under **My Templates** in the Create Flow dialog for future flows.

{% stepper %}
{% step %}
**Open the flow's card menu**

On the **Call Flows** index, click the **⋯** menu on the flow's card and pick **Save as template**.
{% endstep %}

{% step %}
**Name and describe the template**

Give the template a clear name (e.g., "Lead-gen intake with VIP lane") and a short description explaining what it's for. The current flow's nodes and edges become the template's starting graph.
{% endstep %}

{% step %}
**Reuse it in any future flow**

The next time you click **Create Flow**, your saved template appears under the **My Templates** tab. Pick it to start a new flow pre-populated with the saved graph.
{% endstep %}
{% endstepper %}

{% hint style="info" %}
**Custom templates are workspace-scoped.** A template saved in one workspace isn't visible to other workspaces. Built-in templates are visible everywhere.
{% endhint %}

***

### Understanding the Canvas

The canvas has a few core areas:

| Area                          | What it does                                                                 |
| ----------------------------- | ---------------------------------------------------------------------------- |
| **Toolbar (top)**             | Save indicator, zoom controls, Simulate, Publish, Version History, Analytics |
| **Canvas (center)**           | Your flow graph — nodes, edges, and output port connections                  |
| **Node picker (left panel)**  | All available node types, grouped by category                                |
| **Config panel (right side)** | Appears when you select a node; all its settings live here                   |
| **Minimap (bottom-right)**    | Bird's-eye view of the whole flow for quick navigation                       |

{% hint style="info" %}
**Auto-save:** Every change you make is saved to the draft automatically. You only need to click **Publish** when you're ready to put the changes live. Real calls continue to use the previously published version until you publish again.
{% endhint %}

***

### Node Types

Every flow is built from nodes. Here's what each one does:

#### Call flow basics

These are available on all plans and form the core of any flow.

| Node               | What it does                                                             |
| ------------------ | ------------------------------------------------------------------------ |
| **Start** ▶        | Entry point. Required. Holds flow-level settings like timezone.          |
| **Greeting** 🔊    | Plays an audio message — typed text (TTS) or an uploaded MP3.            |
| **Menu** ⌨         | "Press 1 for Sales, press 2 for Support." Branches on the digit pressed. |
| **Dial** 📞        | Forwards the call to a single phone number, with optional whisper.       |
| **Voicemail** 📧   | Plays a greeting then records the caller's message (with transcription). |
| **Hangup** ✋       | Ends the call, with an optional farewell message.                        |
| **Spam Filter** 🛡 | Pre-configured "Press 1 to connect" Menu — blocks silent robocallers.    |

#### Team and time routing

Available on all plans.

| Node                       | What it does                                                                                                         |
| -------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| **Business Hours** 🕐      | Routes based on time: open hours → one path, closed → another, with optional holiday override.                       |
| **Simultaneous Ring** 📱📱 | Rings several phone numbers at once; first to answer wins. Supports "whisper confirm" to prevent voicemail stealing. |
| **Round Robin** 🔄         | Rotates through a list of destinations. Least-recent or weighted distribution.                                       |

{% hint style="warning" %}
**Sim Ring and Round Robin are PSTN-only today.** They ring phone numbers, not browser agents. To route to online dialer agents, use the **Agent Queue** node (Agency). Browser-agent support in Sim Ring and Round Robin is planned — see the product roadmap.
{% endhint %}

#### Data and logic

Available on all plans.

| Node                   | What it does                                                                                                                                            |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Condition** ❓        | Branches on caller attributes — first-time vs. repeat, area code, known contact, custom metadata. First rule that matches wins.                         |
| **Tag / Label** 🏷     | Attaches workspace tags and/or key-value metadata to the call. Tags show up in Call History, webhooks, and reports.                                     |
| **SMS** 💬             | Sends a text message, with template variables like `{{caller_number}}` and `{{campaign_name}}` resolved. Non-blocking — the call continues immediately. |
| **Opt-In / Consent** ✅ | Asks the caller to press 1 to accept (or 2 to decline) a consent prompt. Stores the decision on the call for compliance.                                |

#### AI answering

Available on all plans (bring your own OpenAI key).

| Node           | What it does                                                                                                                                                                                                                 |
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **AI Agent** ✨ | An AI receptionist answers the call: greets, qualifies, answers questions, captures details, books appointments — then routes to a typed outcome port (Qualified, Wants Human, Spam, …) that you wire like any other branch. |

{% content-ref url="/pages/zPRsePZujXkPkJKoj7jR" %}
[AI Call Answering](/guides/ai-call-answering)
{% endcontent-ref %}

#### Flow composition

Available on all plans.

| Node                 | What it does                                                                                    |
| -------------------- | ----------------------------------------------------------------------------------------------- |
| **Go-To Sub-Flow** ↗ | Jumps into a different published flow. Useful for sharing common intake logic across campaigns. |

#### Sub-flows in depth

A **Go-To Sub-Flow** node hands the call off to another published flow. There are two ways it can behave:

| `Return on completion` setting | What happens when the sub-flow finishes                                                                                                                                                     |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Off** (default)              | The sub-flow's terminal node ends the call. The Go-To is effectively a hand-off — the parent flow is done.                                                                                  |
| **On**                         | When the sub-flow reaches a terminal node, the engine pops back into the parent and continues from the Go-To node's **Return** output port. This is how you build reusable building blocks. |

{% hint style="info" %}
**Use sub-flows to share logic.** Build an "After-Hours Voicemail" sub-flow once, then have every campaign's main flow Go-To it from the closed branch of Business Hours. Update the sub-flow once and every campaign that uses it picks up the change on next publish.
{% endhint %}

{% hint style="warning" %}
**Recursion is capped.** A flow can include up to 5 nested Go-To hops in one call. Beyond that, the engine ends the call to prevent infinite loops. If you hit the limit, the chain is too deep — flatten or refactor.
{% endhint %}

**Analytics for sub-flows:** Each flow's analytics counts only the nodes the call traversed in that flow. A parent flow with a Go-To shows the parent's path up to (and including) the Go-To node; the sub-flow's analytics shows the slice the call took inside the sub-flow. The Go-To's row in the parent's Node Metrics has a `→ Sub-flow name` link that takes you straight to the sub-flow's analytics for the same window.

{% hint style="success" %}
**Test the round-trip in the simulator.** When you step through a Go-To node with **Return on completion** turned on, the canvas swaps to the sub-flow with an amber "Now in sub-flow" pill, then snaps back to the parent when the sub-flow's terminal pops the stack. Verify both halves of the path before placing a real call.
{% endhint %}

#### Agency-only nodes

These nodes depend on Agency-only infrastructure and aren't available on the Indie plan.

| Node               | Why it's Agency-only                                                                                                                                                                                                            |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Agent Queue** 🎧 | Routes the caller to a browser dialer agent currently online. Requires the **Dialer** feature, which is included in the Agency plan. Use this when your team uses the Ring Tonic dialer instead of forwarding to PSTN numbers.  |
| **Webhook** 🔗     | Calls an external URL mid-flow. Two modes: **async** (fire-and-forget) for logging/notifications, **sync** for external routing decisions where your API returns which branch to take. Requires the **API & Webhooks** feature. |

{% hint style="info" %}
**Template variables:** Text fields on Greeting, Menu, Dial whisper, SMS, Webhook, and Voicemail support `{{placeholders}}` that resolve at call time. Common ones: `{{caller_number}}`, `{{caller_name}}`, `{{campaign_name}}`, `{{tracking_number}}`, `{{is_repeat_caller}}`. Use the insert button in each text field to pick one without typing.
{% endhint %}

{% hint style="info" %}
**Want `{{caller_name}}` to be populated?** Caller names come from the carrier's CNAM database, which is an opt-in lookup ($0.01 per call). Turn it on per tracking number under [Phone Numbers → Toggle CNAM Lookup](/guides/phone-numbers#toggling-cnam-lookup). Without it, `{{caller_name}}` resolves empty. Caller location fields (`{{caller_city}}`, `{{caller_state}}`) are free but only populate when the carrier provides them — cell-phone callers often arrive without geo data.
{% endhint %}

#### Editing the webhook payload

The Webhook node and the SMS node use a smart JSON editor for the request body and message text:

* **Live syntax check.** A red marker in the gutter highlights any line where the JSON isn't valid — for example, a missing comma or an unclosed brace — so you can fix it before saving instead of finding out after a test call.
* **Template variables in amber.** Placeholders like `{{caller_number}}` and `{{campaign_name}}` are coloured in italic amber so you can see at a glance which values resolve at call time.
* **Format button.** Click **Format** to pretty-print your JSON with consistent indentation. Template variables are preserved exactly as you wrote them.

<figure><img src="/files/JwxBBOiI5qQOx7I4aXFe" alt="" width="563"><figcaption><p>Webhook payload editor with template variables highlighted and the Format button visible</p></figcaption></figure>

#### Verifying the request came from Ring Tonic (HMAC signing)

When your Webhook node hits an endpoint you control, you may want the receiver to confirm the request actually came from Ring Tonic — not a spoofed call. Toggle **Sign with HMAC** on the Webhook node, paste a secret of your choice, and Ring Tonic adds two headers to every outgoing request:

| Header                  | What it contains                                                                                               |
| ----------------------- | -------------------------------------------------------------------------------------------------------------- |
| `X-Ringtonic-Signature` | `sha256=<hex>` — an HMAC of the request body, signed with your secret                                          |
| `X-Ringtonic-Timestamp` | Unix timestamp at the moment the request was sent (used as part of the signed value to prevent replay attacks) |

To verify on the receiving side, recompute `HMAC-SHA256(secret, "{timestamp}.{body}")` and compare it to the value in `X-Ringtonic-Signature`. Reject the request if they don't match or the timestamp is older than your tolerance window (5 minutes is a reasonable default).

{% hint style="info" %}
**Per-node secrets.** Each Webhook node has its own secret, so you can use different secrets for different endpoints (CRM vs. Slack vs. internal API). Share the same value with the receiver and keep it out of public source control.
{% endhint %}

{% hint style="warning" %}
**Signing is opt-in.** The toggle defaults to off so existing flows behave the same way they always did. Turn it on only when your receiver knows how to verify — otherwise the verification will silently fail and the receiver may reject legitimate requests.
{% endhint %}

***

### Attaching a Flow to a Campaign

A flow doesn't do anything until a campaign is pointed at it. Attachment lives on the campaign's detail page — not the edit form — so you can swap flows without re-saving the whole campaign.

{% stepper %}
{% step %}
**Open the campaign**

Go to **Campaigns** and click the campaign you want to upgrade.
{% endstep %}

{% step %}
**Pick "Attach a call flow" on the routing picker**

If the campaign has no routing yet, you'll see the **routing picker** with three mode cards: **Forward to a number**, **Attach a call flow**, and **Build a new flow**. Click the middle card.

If the campaign is already on simple routing, click **Switch routing mode** on the routing summary card and confirm — the picker opens automatically. See [Configure Routing](https://help.ringtonic.app/guides/pages/VdOTbPSa6hi12UUj6ZLp#id-3.-configure-routing) in the Campaigns guide for the full workflow.

<figure><img src="/files/cDvIy14gqD3W5AHhAXj0" alt=""><figcaption><p>Routing picker on the campaign page — three mode cards</p></figcaption></figure>
{% endstep %}

{% step %}
**Pick a flow from the picker**

A picker dialog opens listing every call flow in your workspace. Published flows are selectable; unpublished flows are shown greyed-out with a tooltip explaining they must be published first.

<figure><img src="/files/KU4HOIB9Uo6tfiEtuKC4" alt=""><figcaption><p>Attach Call Flow dialog showing workspace's published flows</p></figcaption></figure>
{% endstep %}

{% step %}
**Confirm**

Select the flow you want, then click **Attach**. The campaign page switches to the **Call Flow card** showing the flow name, version number, and publication date. Real calls to this campaign's tracking numbers immediately start going through the flow.

<figure><img src="/files/i7GISFpeTXh0TdCKcUor" alt=""><figcaption><p>Call Flow card in its attached state with Edit, Change, and Switch routing mode actions</p></figcaption></figure>
{% endstep %}

{% step %}
**Call the tracking number to test**

Call any tracking number attached to the campaign. Your flow answers the call — you should hear your greeting, menu prompts, or whatever the first non-logic node generates.
{% endstep %}
{% endstepper %}

#### Build a new flow from the campaign page

If you don't have a flow built yet, you don't need to leave the campaign page. Pick **Build a new flow** on the routing picker — the Create Flow dialog opens directly.

{% stepper %}
{% step %}
**Pick a template (optional)**

Choose **Blank Flow** or one of the built-in templates (Simple forward, IVR menu, Business hours, etc.). Custom templates from your workspace appear under **My Templates**.
{% endstep %}

{% step %}
**Name your flow and click "Create Flow"**

Ring Tonic creates the flow and redirects you straight to the editor canvas — pre-marked to auto-attach to this campaign on publish.
{% endstep %}

{% step %}
**See the auto-attach banner**

A blue banner at the top of the editor confirms: **"Publishing this flow will attach it to {campaign name}"** — so you know exactly which campaign the flow will land on.

<figure><img src="/files/ZyhagrbOsDyDz5WHZq6d" alt=""><figcaption><p>Editor with the auto-attach banner pinned to the top of the canvas</p></figcaption></figure>
{% endstep %}

{% step %}
**Build, publish, done**

Configure your nodes and click **Publish**. As soon as the version goes live, Ring Tonic links it to the campaign and sends you back to the campaign page. No need to navigate back and re-attach.
{% endstep %}
{% endstepper %}

{% hint style="info" %}
**Cancelling out:** If you close the Create Flow dialog or back out of the editor without publishing, the campaign stays on the routing picker — nothing is changed.
{% endhint %}

#### Changing or removing the flow

Once a flow is attached, the Call Flow card shows these actions:

| Action                  | What it does                                                                                                                                                                                          |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Edit Flow**           | Jumps to the flow canvas so you can update the graph and re-publish                                                                                                                                   |
| **Change**              | Re-opens the picker so you can swap in a different flow without detaching first                                                                                                                       |
| **Switch routing mode** | Detaches the flow and opens the **Forward to a number** dialog so you can configure simple routing in one step. The detached flow itself isn't deleted — it can still be attached to other campaigns. |

After detaching (without picking a new mode), the campaign returns to the **routing picker** so you can pick a different mode or attach a different flow.

{% hint style="success" %}
**Zero-disruption switchover:** Attaching a flow takes effect on the next inbound call — no need to redeploy tracking numbers. Switching back to simple routing is equally instant.
{% endhint %}

{% hint style="info" %}
**Many-to-one:** A single flow can serve multiple campaigns. Agencies often build one well-tested "Main Intake" flow and point every campaign at it, then override with custom flows only where needed.
{% endhint %}

{% hint style="warning" %}
**Only published flows can be attached from the picker.** If you just created a flow and haven't clicked Publish yet, it appears disabled in the picker. Either open the flow canvas and publish it, or use the **Build a new flow** path above which auto-attaches on first publish.
{% endhint %}

***

### Publishing and Versioning

Every published flow is an immutable snapshot. Editing the flow always creates a draft — real calls keep using the previously published version until you re-publish.

#### The publish lifecycle

```
   DRAFT (your edits)  ──── Publish ────▶  VERSION N (frozen)
                                                │
                                                │  Set as active
                                                ▼
                                          LIVE (answers real calls)
```

#### Publishing

1. Click **Publish** in the top-right of the canvas
2. Add an optional publish note (e.g., "Added VIP lane for repeat callers")
3. Ring Tonic runs strict validation:
   * Every node reachable from Start
   * No orphan outputs
   * Every Dial has a valid phone number
   * Every Menu has a no-input path
   * Every sync Webhook has a timeout/error port
4. If validation passes, the new version becomes active and real calls immediately start using it

<figure><img src="/files/B8CUFQbQdr15zz1emlR5" alt=""><figcaption><p>Publish validation showing strict rule checks</p></figcaption></figure>

{% hint style="warning" %}
**ElevenLabs flows publish asynchronously.** If your flow uses ElevenLabs voices, publishing starts a background job that generates MP3s via the ElevenLabs API and uploads them to storage. This takes 10–30 seconds. You'll see a green "Published Successfully" toast when it's done. If something fails (bad API key, quota exceeded), the previous version stays live — your traffic is never disrupted.
{% endhint %}

{% hint style="info" %}
**Auto-attach on first publish:** If you opened this editor from a campaign's "Build a new flow" card, you'll see a blue banner at the top of the canvas. The first time you publish, Ring Tonic links the new version to that campaign automatically and returns you to the campaign page — no manual attach step needed.
{% endhint %}

#### Version history and rollback

Click **Version History** on the canvas toolbar to see every version ever published.

| Field          | What it shows                                       |
| -------------- | --------------------------------------------------- |
| Version number | v1, v2, v3…                                         |
| Status         | Active, publishing, failed, rolled back, superseded |
| Published by   | The user who published it                           |
| Published at   | Absolute date + relative time ("2 days ago")        |
| Publish note   | The note you wrote when publishing                  |

Hover any row to reveal the **Rollback** button. Rolling back copies that version's graph back into your draft so you can review, tweak, and re-publish. The currently active version has no Rollback button (you can't roll back to yourself).

<figure><img src="/files/ZzVapwbtWdVPoc2PH0UV" alt=""><figcaption><p>Version history sheet showing timeline of published versions</p></figcaption></figure>

{% hint style="info" %}
**Version retention by plan:** Indie keeps the last 5 versions; Agency keeps the last 50. Older versions are compacted but the active version is always preserved.
{% endhint %}

***

### Testing Before You Publish

#### Simulation mode

Click **Simulate** on the canvas toolbar to open the simulation panel at the bottom of the page and walk through your flow step-by-step without placing a real call. The simulator:

* **Highlights the active node on the canvas** — the current step gets a pulsing amber ring; nodes the simulation has already visited get a dimmed amber ring, so the path you've taken is visible at a glance.
* **Shows the actual TwiML** that would be returned to Twilio at each interactive step (Greeting, Dial, Menu, Opt-In, Voicemail, Spam Filter, etc.) — handy for verifying voice IDs, dial timeouts, and template-variable substitution.
* **Branches at decision points** — click the lane you want to take at Menu, Condition, Opt-In / Consent, Business Hours, and sync Webhook nodes. Single-output nodes show one **Next → {NextNodeType}** button (e.g., "Next → Greeting", "Next → Opt In") so you always know what's coming.
* **Auto-advances logic-only nodes** — Tag, Condition, Go-To Sub-Flow, and the Start node have no caller-facing output, so the simulator skips them silently and shows the next interactive node.
* **Tracks accumulated call state** — applied tags, metadata key/value pairs, and consent decisions are surfaced under "Accumulated state" at the next interactive step, then again in the final summary.
* **Ends with "Flow Complete"** showing the full path taken (every node visited, including the silent ones), the complete tag list, and the final metadata payload.

<figure><img src="/files/ETwHbbWH7VR9usAjwliK" alt=""><figcaption><p>Simulation panel walking through a test call, showing the current step's TwiML and accumulated state</p></figcaption></figure>

{% hint style="success" %}
**Best Practice:** Always simulate before publishing. The simulator catches logic mistakes (unreachable nodes, wrong keypress targets, missing branch edges) in seconds — faster than placing a real test call.
{% endhint %}

{% hint style="info" %}
**Reading the path:** the final "Path taken" line lists every node the engine visited, including the auto-advanced ones (e.g., `start → condition → tag → dial → hangup` is 5 nodes even though you only clicked through 2 interactive screens). If a step count looks higher than the screens you saw, that's why.
{% endhint %}

#### Real test call

After simulation passes, publish the flow and call your tracking number. You'll hear the caller-side experience directly. The simulator covers **logic**; a real call is the only way to validate **audio quality, whisper timing, and recording**.

{% hint style="info" %}
**Flows with an AI Agent node have a dedicated test-call tool.** The **Test call** button on the toolbar places a real browser call straight into the AI conversation — live transcript, outcome-port highlighting on the canvas, and a saveable passing scenario — without publishing or dialing your tracking number. See [AI Call Answering → Testing with a Real AI Call](/guides/ai-call-answering#testing-with-a-real-ai-call).
{% endhint %}

***

### Flow Analytics

Once your flow is published and receiving calls, open **Flow Analytics** from the toolbar to see how callers move through it.

<figure><img src="/files/kkwKj9EeGECEE6Jz2MQt" alt="" width="563"><figcaption><p>Flow Analytics panel with calls, paths, node metrics, and drop-off funnel</p></figcaption></figure>

#### What you'll see

| Section             | What it tells you                                                                      |
| ------------------- | -------------------------------------------------------------------------------------- |
| **Calls**           | Total calls that entered the flow in the selected range                                |
| **Avg Duration**    | Average total call duration                                                            |
| **Completion %**    | Percentage of calls that reached a terminal node (Hangup, Voicemail, or answered Dial) |
| **Top Paths**       | The most-common routes callers took through the flow                                   |
| **Node Metrics**    | Per-node: calls entered, average time spent there, drop-off rate                       |
| **Drop-off Funnel** | Stage-by-stage funnel showing where callers leave — or reach a terminal                |

{% hint style="info" %}
**Reading drop-off correctly:** A node's drop-off percentage means "% of calls that entered this node and did NOT continue to any outgoing port." Terminal nodes (Hangup, Voicemail) are successful completions, not drops. The funnel shows a `+N completed here` chip at stages where terminal splits exist.
{% endhint %}

#### Using analytics to improve flows

* **High drop-off at a Menu:** Your prompt is unclear or the options don't match caller intent. Rewrite the prompt.
* **Long average time at a Greeting:** The message may be too long. Trim it, or split into a shorter intro.
* **Low Dial answer rate:** Your whisper is too long or your team isn't online. Simplify the whisper or review agent availability.
* **Spam Filter catching 30% of calls:** That's robocaller traffic being filtered out correctly. Usually a good sign.

***

### Recipes — Real-World Flow Patterns

These are the patterns we see most often in production. Each one starts from a built-in template, then layers on the nodes you need.

<details>

<summary>Recipe 1 — Robocall-resistant business inbound</summary>

**Goal:** filter out auto-dialers, route to your team during business hours, take a voicemail otherwise.

Start from the **Spam Filter + Forward** template, then insert a Business Hours node between the Spam Filter and the Dial.

```
Start → Spam Filter → Business Hours
                        ├── open  → Dial → (answered: Hangup, else: Voicemail)
                        └── closed/holiday → Voicemail (after-hours greeting)
```

{% hint style="success" %}
**Why this works:** the Spam Filter eliminates \~80% of robocaller volume before the Business Hours node ever evaluates. Your team only ever rings on real, human-verified calls.
{% endhint %}

</details>

<details>

<summary>Recipe 2 — VIP lane for repeat callers</summary>

**Goal:** known repeat callers skip the menu and ring a senior rep directly; new callers get the standard IVR.

Start from the **VIP Tag Routing** template. The Condition node already branches on `is_repeat_caller`. Tweak the dial numbers and the IVR menu options for your team.

```
Start → Condition
          ├── is_repeat_caller=true → Tag (VIP, Returning) → Dial (senior rep)
          └── default                 → Menu → Sales / Support / Voicemail
```

{% hint style="info" %}
**Want to branch on more than just repeat-vs-new?** Open the Condition node's **Rules** panel and add another rule (e.g., `caller_number starts_with +1206` for a Seattle local lane). The first rule that matches wins; everything else falls through to the default port.
{% endhint %}

</details>

<details>

<summary>Recipe 3 — CRM-driven smart routing</summary>

**Goal:** look up the caller in your CRM during the call, then route based on their tier (VIP / Standard / Lost lead).

Start from the **Webhook Smart Routing** template. Replace the placeholder URL `https://example.com/api/lookup` with your CRM endpoint. Tune the response rules to match your API contract — e.g., if your API returns `{"tier": "vip", "owner": "..."}`, leave the rule as `json.tier equals vip → vip`.

```
Start → Greeting ("Please hold while we look up your account")
        → Webhook (POST {{caller_number}})
            ├── vip      → VIP greeting → VIP rep dial
            ├── standard → Standard greeting → Round Robin team dial
            └── timeout  → Voicemail (graceful fallback)
```

{% hint style="warning" %}
**Always wire `timeout_error`.** A sync Webhook holds the call until your endpoint replies. If your API is slow or down, the `timeout_error` port is what saves the call from dead air. The template wires this for you — don't delete it.
{% endhint %}

{% hint style="info" %}
**Verify the request came from Ring Tonic.** Toggle **Sign with HMAC** on the Webhook node and verify `X-Ringtonic-Signature` on your endpoint. See [Verifying the request came from Ring Tonic](#verifying-the-request-came-from-ring-tonic-hmac-signing) above.
{% endhint %}

</details>

<details>

<summary>Recipe 4 — Reusable after-hours sub-flow</summary>

**Goal:** one after-hours flow shared by every campaign, instead of duplicating the same Voicemail + SMS confirmation in 20 different campaign flows.

1. Build the sub-flow first: a small flow with `Start → Voicemail → SMS → Hangup` that takes a message and texts the caller a confirmation. Publish it as **"After-Hours Sub-Flow"**.
2. In each campaign's main flow, on the Business Hours **closed** branch, drop a **Go-To Sub-Flow** node and point it at the after-hours flow. Leave **Return on completion** off — the sub-flow ends the call.

```
Main flow:   Start → Business Hours
                       ├── open   → Dial → Voicemail
                       └── closed → Go-To "After-Hours Sub-Flow"

Sub-flow:    Start → Voicemail → SMS ("Got your message, we'll call you back") → Hangup
```

Update the sub-flow once and every campaign picks up the change on the next publish — no need to edit 20 separate flows.

{% hint style="success" %}
**This is the biggest agency win.** Build a "Standard Intake", "After-Hours", and "Spam Filter" sub-flow once, then compose them into every campaign's main flow with Go-To. Every campaign stays consistent without copy-paste drift.
{% endhint %}

</details>

<details>

<summary>Recipe 5 — Team rotation with sequential fallback</summary>

**Goal:** ring three reps at once for the first 25 seconds; if no one picks up, fall through to the next-most-recent agent (round-robin) for another retry; only then voicemail.

Start from the **Sales Team** (Round Robin) template. Insert a **Simultaneous Ring** node before it.

```
Start → Greeting → Simultaneous Ring (3 phones, 25s)
            ├── answered → Hangup
            └── no_answer → Round Robin (least-recent, max 2 retries)
                                ├── answered → Hangup
                                └── no_answer/error → Voicemail
```

{% hint style="info" %}
**Sim Ring vs. Round Robin:** Sim Ring rings everyone at once for the first attempt — fastest pickup, best for in-office teams that are usually free. Round Robin rings one at a time with retries — better for distributed teams where calls should be balanced fairly across agents over time. Combining them gives you the best of both.
{% endhint %}

</details>

***

### Power Tips

{% hint style="success" %}
**Wire every Dial's failure ports.** A bare `dial` with only the **answered** edge connected leaves callers in dead air on busy / no-answer / error. The built-in templates wire all four ports for you — copy that pattern in custom flows.
{% endhint %}

{% hint style="success" %}
**Always end with a Hangup.** Even when the previous node is a Voicemail, an explicit Hangup makes the flow's intent clear in the canvas and triggers the optional farewell message. Drop-off analytics treats Hangup as a successful completion, not a drop.
{% endhint %}

{% hint style="success" %}
**Use SMS to recover lost calls.** On the Voicemail or no-answer path, drop an **SMS** node ("Sorry we missed your call — we'll call you back within an hour. Reply STOP to opt out."). SMS is non-blocking — the call continues immediately — and dramatically improves callback conversion.
{% endhint %}

{% hint style="success" %}
**Save your polished flow as a template.** Once a flow is working well, save it as a custom template (see [Saving a flow as a custom template](#saving-a-flow-as-a-custom-template)). The next time you build a similar flow you'll start from your battle-tested baseline instead of from scratch.
{% endhint %}

{% hint style="warning" %}
**Don't forget the Menu's `no_input` and `invalid_input` edges.** A caller who doesn't press anything (silence) or hits a non-configured digit needs a path. Without those edges, the call drops. Wire both to a Voicemail or back to the menu for a retry.
{% endhint %}

{% hint style="warning" %}
**Replace the placeholder phone numbers before publishing.** Templates ship with `+1XXXXXXXXXX` placeholders so you remember to fill them in. Publish validation will surface any unfilled fields, but it's faster to scan the canvas yourself first.
{% endhint %}

***

### Upgrading from Simple Routing to a Call Flow

Simple routing (Forward to a number with optional voicemail, recording, whisper, and spam filter) is a fully supported routing mode — it isn't deprecated, and you don't have to upgrade. Move to a call flow when you outgrow what simple routing can express: IVR menus, business-hours branching, multiple destinations, tags, conditions, or SMS follow-ups.

{% stepper %}
{% step %}
**Open the campaign and switch routing mode**

On the campaign page, click **Switch routing mode** on the simple routing card, confirm, then pick **Build a new flow** from the routing picker.
{% endstep %}

{% step %}
**Pick a starting template**

The **Simple Forwarding** template is the closest match to your existing setup — it gives you a Start → Dial → Voicemail flow you can tweak. Or start blank if you want to build from scratch.
{% endstep %}

{% step %}
**Carry over your settings**

Fill in the Dial node with your forward number, whisper, and recording. Add a Voicemail node if your simple routing had voicemail. Add a Spam Filter node before the Dial if you had spam filter on. Click **Publish** — Ring Tonic auto-attaches the flow to your campaign, so you don't have to navigate back.
{% endstep %}
{% endstepper %}

{% hint style="info" %}
**Your simple routing settings stay saved.** They go inactive while the flow handles calls, and reactivate automatically if you ever detach the flow.
{% endhint %}

{% hint style="success" %}
**You're never forced to upgrade.** Campaigns on simple routing keep working forever. The flow only activates on a campaign when you explicitly attach (or build + auto-attach) one. If you have many campaigns to convert at once, contact Ring Tonic support and we'll help you do it in one go.
{% endhint %}

***

### Troubleshooting

<details>

<summary>Caller hears dead air or disconnects mid-flow</summary>

**Possible causes:**

* A Dial node's forwarding number is wrong or unreachable — verify the E.164 number and that the destination actually answers
* A Webhook node is pointed at an unreachable URL — check the URL with curl and add a `timeout_error` edge as a fallback
* The flow has a Go-To pointing at an unpublished sub-flow — publish the sub-flow first

**Fix:** Use Simulation mode to walk through each branch. Any node that can't produce output will be obvious. Also check the call's **Timeline** tab in Call History for the exact node where the call stopped.

</details>

<details>

<summary>Menu keypresses aren't routing correctly</summary>

**Possible causes:**

* The output ports on the Menu aren't connected to the right downstream nodes — open the Menu, confirm each keypress has an edge to the intended target
* The caller is pressing a digit you didn't configure — add a `no_input` and `invalid_input` edge to handle those cases (usually pointing to voicemail or a retry)

**Fix:** Simulation mode lets you test every keypress path in seconds.

</details>

<details>

<summary>Published flow shows "failed" status</summary>

**Problem:** The publish job couldn't finish — usually an ElevenLabs API error when generating voice audio.

**Fix:** Click the failed version in Version History to see the exact error message (e.g., "ElevenLabs API returned 401 — check your API key"). Verify your ElevenLabs API key in [Workspace Settings](https://help.ringtonic.app/guides/setup-workspace#voice-and-audio-elevenlabs-voices-optional), then retry the publish from the version history row.

</details>

<details>

<summary>My flow-set tags aren't showing in Call History</summary>

**Check:** Open the call's detail sheet → Timeline tab. You should see the Tag node's tags listed alongside AI-applied tags. If they're missing, re-publish the flow and place a new test call — tags are captured at call time, not retroactively.

</details>

<details>

<summary>SMS node reports "delivered" but recipient didn't get the text</summary>

**Most common cause:** A2P 10DLC registration. US carriers silently block SMS from unregistered 10DLC numbers, even though Twilio reports the send as accepted. Ring Tonic surfaces the true delivery status in the call's **Timeline** tab — look for "SMS Failed" with error code 30034.

**Fix:** Register your Twilio number for A2P 10DLC via the Twilio Console. Alternatively, use a toll-free number, which has a simpler verification path. See the [Twilio A2P guide](https://www.twilio.com/docs/messaging/compliance/a2p-10dlc) for details.

</details>

<details>

<summary>Can't find a node I need</summary>

**Check your plan:** every node is available on every plan **except Agent Queue and Webhook**, which require **Agency** because they depend on Agency-only infrastructure (the browser dialer for Agent Queue, API + webhook access for Webhook). The node picker shows these two gated nodes with a lock icon — clicking one opens an upgrade prompt.

If a node you expected (Business Hours, Sim Ring, Round Robin, Tag, Condition, SMS, Opt-In, Go-To Sub-Flow) is missing from the picker, scroll the picker — it groups nodes by category. They're available on all plans.

</details>

<details>

<summary>Rollback button is missing on my active version</summary>

**Expected behavior:** You can't roll back to the version that's already active. If you want to revert recent edits, either roll back to the previous version, or clear your draft and re-publish the active version to reset the draft state.

</details>

***

### Best Practices

{% hint style="success" %}
**Start small, iterate.** Publish a simple version 1 (Greeting → Dial → Voicemail), then add complexity (menus, business hours, tags) in subsequent versions. Version history lets you roll back instantly if a change breaks something.
{% endhint %}

{% hint style="success" %}
**Always add a Spam Filter for US inbound.** A one-step "Press 1 to connect" before your real flow kicks in eliminates 80%+ of robocaller volume. Use the Spam Filter preset for a pre-configured Menu.
{% endhint %}

{% hint style="success" %}
**Whisper is your agent's best friend.** Even a one-line whisper like "Incoming call from {{caller\_number}} via the Google Ads campaign" dramatically improves pickup speed and call quality. Combine with screening (press 1 to accept) to prevent carrier voicemail from stealing calls.
{% endhint %}

{% hint style="success" %}
**Use Tag nodes on important branches.** Any caller who takes an interesting path (pressed 1 for sales, passed the spam filter, entered the VIP lane) should be tagged so they're filterable and reportable later. Tag nodes are free in the flow and light-weight at runtime.
{% endhint %}

{% hint style="success" %}
**Route by caller attributes with the Condition node.** First-time callers and repeat callers deserve different experiences. Use Condition to detect `is_repeat_caller` or caller area code, and branch into VIP / local / generic lanes with different whispers and routing targets.
{% endhint %}

***

### Related Guides

{% content-ref url="/pages/VdOTbPSa6hi12UUj6ZLp" %}
[Campaigns](/guides/campaigns)
{% endcontent-ref %}

{% content-ref url="/pages/RsUXxl71vSxWd0PsQfwr" %}
[Browser Dialer](/guides/browser-dialer)
{% endcontent-ref %}

{% content-ref url="/pages/crg7tMxXMDacQLAiSpgl" %}
[Setup Workspace](/guides/setup-workspace)
{% endcontent-ref %}

{% content-ref url="/pages/FqrMOC4HeyPH7W0Eqtdm" %}
[Analytics](/guides/analytics)
{% endcontent-ref %}


# AI Call Answering

### What is AI Call Answering?

AI Call Answering adds an **AI Agent** node to the Call Flow Builder. The agent picks up the call, greets the caller in a natural voice, answers questions from your business knowledge, qualifies the lead, captures details like name and budget — and then routes the call back into your flow: book an appointment, transfer to a human, send an SMS, or end politely.

Unlike standalone AI receptionists, the agent is **one node among many**. It composes with everything else in your flow — Business Hours, Menu, Dial, Round Robin, Voicemail — and every AI outcome is a real branch on the canvas that you wire yourself.

<figure><img src="/files/cvxDmKX53qt8JfkuIC7i" alt=""><figcaption><p>An AI Agent node on the canvas with its outcome ports wired to downstream nodes</p></figcaption></figure>

{% hint style="info" %}
**Use cases at a glance:** A 24/7 receptionist that qualifies leads before your team picks up, after-hours booking on your real calendar, spam screening that never creates junk contacts, and qualified-lead conversions reported straight to Google Ads.
{% endhint %}

{% hint style="success" %}
**Available on all plans — bring your own keys.** The AI Agent runs on your own Twilio account and your own OpenAI API key (plus an optional ElevenLabs key for premium voices). Ring Tonic doesn't meter or mark up AI minutes; usage bills directly to your provider accounts.
{% endhint %}

***

### Before You Start

The agent needs a few workspace-level credentials before it can take a call.

{% stepper %}
{% step %}

#### Twilio credentials

Your workspace must already be receiving calls through Twilio. Check **Settings > Workspaces > Twilio Credentials** — if your tracking numbers work today, you're set. See [Setup Workspace](https://help.ringtonic.app/guides/pages/crg7tMxXMDacQLAiSpgl#1.-set-up-twilio-for-tracking-calls).
{% endstep %}

{% step %}

#### OpenAI API key

The agent's brain. Add your key under **Settings > Workspaces >** your workspace **> AI Automation**.

See [Set up AI Automation with OpenAI](https://help.ringtonic.app/guides/pages/crg7tMxXMDacQLAiSpgl#4.-set-up-ai-automation-with-openai) for how to create a key.
{% endstep %}

{% step %}

#### ElevenLabs API key (recommended)

Powers the agent's natural-sounding voice and lets you pick from your own ElevenLabs voices. Add it under the **Voice & Audio** section of the same workspace settings page.

Without it, the Voice tab of the AI node shows: *"No ElevenLabs voices found. Add an ElevenLabs API key in Settings → Integrations to load your voices."*
{% endstep %}

{% step %}

#### Google Calendar (only for appointment booking)

If you want the agent to book real appointments, connect your calendar first under **Settings > Integrations > Google Calendar**. See [Appointment Booking](#appointment-booking) below.
{% endstep %}

{% step %}

#### Live speech-to-text engine (optional)

Under the workspace **Transcription** tab, the **AI call transcription (live)** section controls which speech-to-text engine transcribes the caller during live AI calls. It runs on your Twilio account — no separate API key.

Leave it on **Automatic — let Twilio pick the default (recommended)** unless you have a reason to force Google or Deepgram.
{% endstep %}
{% endstepper %}

***

### Start from a Template

The fastest way to a working AI flow is one of the five built-in AI templates. Each ships fully wired — every outcome port connected, fallbacks in place — with a working persona you edit instead of writing from scratch.

Click **Create Flow** in the Call Flow Builder and pick one from the **Templates** tab:

| Template                     | What it does                                                                                                                               |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| **AI Receptionist**          | The AI answers every call: handles FAQs, captures the caller's name and number, and transfers insistent callers to your team.              |
| **After-Hours AI Answering** | Business hours ring your team as usual; nights, weekends, and holidays the AI answers and takes a complete message with a callback number. |
| **AI Missed-Call Rescue**    | Rings your team first — if nobody picks up, the AI answers instead of voicemail and captures who called and why.                           |
| **AI Appointment Booking**   | Booking-first: the AI finds a time with the caller and books it straight onto your Google Calendar.                                        |
| **AI Lead Qualifier**        | Built for ad campaigns: screens spam, asks your qualifying questions, and bridges qualified callers live to your sales line.               |

<figure><img src="/files/EPuS1uEKY2GGdMCJ5tpB" alt=""><figcaption><p>The Create Flow dialog with the five AI templates on the Templates tab</p></figcaption></figure>

Each template comes with a realistic sample business (a plumbing company, a dental office, …) so you can place a test call immediately. Before publishing:

* Replace the **sample persona, business info, and FAQs** on the AI node with your own.
* Swap the **placeholder phone numbers** on the Dial nodes.
* For **AI Appointment Booking**, connect Google Calendar first — see [Appointment Booking](#appointment-booking).

{% hint style="success" %}
**The template personas encode behaviors that survive real calls** — the agent confirms the caller's name and number back to them before transferring, never transfers or hangs up silently, and speaks a confirmation after booking. Keep those instructions when you customize the prompt.
{% endhint %}

***

### Adding the AI Agent Node

{% stepper %}
{% step %}

#### Drag the node onto the canvas

Open your flow in the Call Flow Builder and drag **AI Agent** ("AI answers, qualifies, and routes the caller") from the node palette. Connect your **Start** node (or any upstream node) into it.
{% endstep %}

{% step %}

#### Configure the agent

Click the node to open its panel. It's organized into six tabs — **Persona, Goals, Knowledge, Voice, Actions, Safety** — covered section by section below.
{% endstep %}

{% step %}

#### Wire the outcome ports

Every conversation ends on exactly one outcome port. Wire each port you use to a downstream node — see [Output Ports](#output-ports-and-how-to-wire-them) for recommendations.
{% endstep %}

{% step %}

#### Test, then publish

Run a real **Test call** from the toolbar before publishing — see [Testing with a Real AI Call](#testing-with-a-real-ai-call).
{% endstep %}
{% endstepper %}

***

### Configuring the Agent

<figure><img src="/files/NVQFSRkJcN5OGu0M1fsW" alt="" width="375"><figcaption><p>The AI Agent configuration panel with its six tabs: Persona, Goals, Knowledge, Voice, Actions, Safety</p></figcaption></figure>

#### Persona

Who the agent is and how it behaves.

| Field             | What it does                                                                    |
| ----------------- | ------------------------------------------------------------------------------- |
| **Agent name**    | The name the agent uses for itself (e.g., "Riley").                             |
| **Business name** | Your business, referenced naturally during the conversation.                    |
| **Tone**          | A short style hint, e.g., "warm, professional".                                 |
| **System prompt** | The core instructions for how the agent should behave. **Required to publish.** |

#### Goals

What the agent is trying to accomplish on every call.

* **Objectives** — ordered sub-goals the agent works through, e.g., *"Get the caller's name and reason for calling."* Each objective can list the capture-field keys it must collect (comma-separated).
* **Capture fields** — the structured data the agent extracts: a key (e.g., `budget`), a display label, a type (Text, Number, Yes/No, Date), and a **Required** toggle.

{% hint style="warning" %}
**Every required capture field must be referenced by an objective.** If you mark a field required but no objective asks for it, publishing fails with a clear error — the agent would never know to collect it.
{% endhint %}

#### Knowledge

What the agent is allowed to know and say.

* **Business info** — free-text background: service area, pricing approach, anything the agent should reference.
* **Services** — a short list of what you offer.
* **FAQs** — question/answer pairs the agent answers verbatim from.
* **Answer from knowledge only** — keep this on. The agent escalates ("let me connect you") instead of inventing answers it doesn't have.

#### Voice

How the agent sounds.

| Field                    | What it does                                                                                                                             |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
| **Language**             | A curated list — each language uses a hand-picked, natural-sounding voice.                                                               |
| **AI model**             | The brain behind the agent. Leave it on **Use account default** unless a flow needs something specific — see **Choosing a model** below. |
| **Voice**                | The ElevenLabs voice the agent speaks in (defaults to the language's curated voice). Loads from your own key.                            |
| **Barge-in sensitivity** | How easily the caller can interrupt the agent mid-sentence (Low / Medium / High).                                                        |
| **Welcome greeting**     | The agent's opening line. The AI disclosure is automatically spoken **before** this greeting.                                            |

{% hint style="info" %}
**Choosing a model.** Leave it on **Use account default** unless a flow needs something specific. Otherwise pick by use case — faster models start speaking sooner, smarter ones handle complexity better:

* **Fast & Cheap** — simple, scripted calls: FAQs, basic reception, high volume.
* **Balanced** *(Recommended)* — the everyday all-rounder: booking, qualifying, and most support calls.
* **Smart & Snappy** — objections and light troubleshooting, while staying responsive.
* **Smartest** — complex or regulated calls where accuracy matters most (a touch slower to respond).
  {% endhint %}

#### Actions

What the agent is allowed to do. Branch-producing actions add their output port on the canvas automatically.

| Action                | What it does                                                         | Port it adds                     |
| --------------------- | -------------------------------------------------------------------- | -------------------------------- |
| **Set outcome**       | Lets the agent qualify or disqualify the lead, or flag spam.         | Qualified / Not Qualified / Spam |
| **Book appointment**  | Books a real slot on your connected calendar.                        | Booked                           |
| **Transfer to human** | Hands the call to your team with a spoken context summary.           | Wants Human                      |
| **Capture field**     | Saves extracted details (name, budget, …) onto the call and contact. | —                                |
| **Add tag**           | Tags the call, visible in Call History, webhooks, and reports.       | —                                |
| **Send SMS**          | Fires a text mid-call (e.g., a booking link).                        | —                                |
| **End call**          | Ends the conversation politely.                                      | —                                |

Two related sections live on this tab:

* **Transfer** — choose **Connected node (wire the Wants Human port)** to route transfers through your flow (recommended), or **Specific number** to dial a fixed number. Turn on **Speak context summary to the agent** so your team hears a short AI-generated whisper ("Caller wants a roof estimate, budget $8k") before being connected.
* **Attribution context** — inject the campaign, ad source, and keyword into the agent's awareness so it can acknowledge what the caller responded to ("Thanks for calling about the summer promo").

#### Safety

Guardrails and compliance.

| Setting                  | What it does                                                                                                                                           |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Confidence threshold** | If the agent qualifies a lead with confidence **below** this number, the call routes to the **Low Confidence** port instead — and no conversion fires. |
| **Max turns**            | Hard cap on conversation length.                                                                                                                       |
| **Wants-human phrases**  | Comma-separated phrases ("talk to a person, human") that immediately trigger a transfer.                                                               |
| **Spam screening**       | Detects robocallers and routes them to the **Spam** port — without ever creating a contact.                                                            |
| **AI disclosure**        | The legally-important opener telling callers they're speaking with AI. **Always on — cannot be disabled.** The wording is editable.                    |
| **Recording**            | **Inherit from flow** (default) or **Off**.                                                                                                            |

{% hint style="danger" %}
**The AI disclosure is mandatory.** The FCC treats AI voices as "artificial or prerecorded", so every AI call opens with your disclosure text, spoken in the agent's own voice as the first sentence of the greeting. You can edit the wording, but you can't remove it — publishing enforces it.
{% endhint %}

***

### Output Ports — and How to Wire Them

Every AI conversation ends on exactly one port. Three are **required** before you can publish; the rest are recommended.

| Port               | When it fires                                                       | Wire it to…                         | Required?                 |
| ------------------ | ------------------------------------------------------------------- | ----------------------------------- | ------------------------- |
| **Qualified**      | The agent qualified the lead at or above your confidence threshold. | Hangup with a farewell, or a Dial   | ✅ Required                |
| **Wants Human**    | The caller asked for a person, or the agent decided to transfer.    | Dial, Round Robin, or Agent Queue   | ✅ Required                |
| **Error**          | Something went wrong mid-conversation.                              | Dial or Voicemail (a safe fallback) | ✅ Required                |
| **Booked**         | An appointment was actually created on your calendar.               | Hangup with a confirmation message  | ✅ When booking is enabled |
| **Not Qualified**  | The agent determined the lead isn't a fit.                          | Hangup                              | Recommended               |
| **Spam**           | Spam screening caught a robocaller.                                 | Hangup                              | Recommended               |
| **Low Confidence** | Qualified, but below your confidence threshold.                     | Dial or Voicemail for human review  | Recommended               |
| **No Input**       | The caller never spoke.                                             | Voicemail or Hangup                 | Recommended               |

{% hint style="info" %}
**Errors block publishing; recommendations don't.** Leaving a required port unwired shows a red **"AI Agent is incomplete"** toast and blocks the publish. Leaving a recommended port unwired publishes fine, but you'll see a **"Published — AI Agent has recommendations"** notice — an unwired recommended port ends the call with a plain hangup, which usually isn't what you want.
{% endhint %}

***

### Appointment Booking

The agent can book real appointments during the call — and it only ever confirms a time **after** the event is actually created on your calendar, so it can't promise slots that don't exist.

{% hint style="info" %}
**How booking works on a call.** The agent reads the date and time back to the caller and waits for a clear "yes" before it books anything — so a misheard time never lands on your calendar. If the requested slot is already taken, it says so and offers another time. Appointments are created in your **workspace's timezone**, so make sure that's set to your local zone for times to land correctly.
{% endhint %}

#### Connect Google Calendar

{% stepper %}
{% step %}

#### Open the Integrations hub

Go to **Settings > Integrations**. Find the **Google Calendar** card — *"Let the AI agent book real appointments on your calendar during a call."*
{% endstep %}

{% step %}

#### Connect with Google

Click **Connect with Google** and approve calendar access. Once connected, the page shows **"Connection is healthy"** with the Google account and calendar in use (your **primary** calendar by default).
{% endstep %}
{% endstepper %}

<figure><img src="/files/Wj5VplhjVUbLYncSnfd1" alt=""><figcaption><p>The Google Calendar card in Settings → Integrations, connected and healthy</p></figcaption></figure>

#### Enable booking on the node

{% stepper %}
{% step %}

#### Turn on the action

In the AI node's **Actions** tab, enable **Book appointment**. This adds the **Booked** port to the node.
{% endstep %}

{% step %}

#### Configure the Booking section

* **Provider** — Google Calendar
* **Calendar ID** — leave blank for your primary calendar, or paste a specific calendar's ID
* **Duration (minutes)** — the slot length the agent offers
* **Confirm via SMS** — text the caller a confirmation after booking
  {% endstep %}

{% step %}

#### Wire the Booked port

Booking enabled = **Booked port required**. Wire it to a Hangup with a confirmation farewell. Publishing fails until both the calendar is connected and the port is wired.
{% endstep %}
{% endstepper %}

{% hint style="warning" %}
**Calendly appears in the provider list but isn't available yet.** Selecting it currently blocks publishing — use Google Calendar.
{% endhint %}

{% hint style="success" %}
**Booked appointments count as conversions.** A successful booking records a conversion the same way a qualified lead does — including the Google Ads upload when your [Google Ads integration](/guides/google-ads-integration) is connected.
{% endhint %}

***

### Testing with a Real AI Call

Simulation mode covers flow logic, but an AI conversation needs a **real call**. The **Test call** button on the toolbar places one — from your browser, no phone needed.

{% stepper %}
{% step %}

#### Start the test

Click **Test call** (next to Simulate). The **AI test call** panel opens — *"Placing the test call — allow microphone access if prompted…"*. Allow the microphone and wait for the status badge to switch to **Live**.
{% endstep %}

{% step %}

#### Talk to your agent

Speak normally through your browser. The panel shows the **live transcript** (Agent / Caller turns, with the agent's per-reply response time), and the canvas highlights the AI node while the conversation runs.
{% endstep %}

{% step %}

#### Review the result

When the call ends, the chosen outcome port lights up on the canvas and the panel shows the full result: **Outcome** (with confidence), **Captured** fields, and the **Tool calls** the agent made.
{% endstep %}

{% step %}

#### Save it as your passing scenario

Click **Save as scenario** to record this run as the flow's "last green" test. The editor badge flips from **Not test-verified** to **Test-verified** — and to **Edited since last test** if you change the flow afterwards, reminding you to re-test.
{% endstep %}
{% endstepper %}

<figure><img src="/files/gdJcUyy1eXab2BaSCHFi" alt=""><figcaption><p>The AI test call panel with a live transcript and the post-test outcome summary</p></figcaption></figure>

{% hint style="info" %}
**Test calls are invisible to your data.** They never create contacts, never fire conversions, and are excluded from every analytics surface and the public status page. They do use real Twilio/OpenAI minutes on your own accounts (a few cents per test).
{% endhint %}

<details>

<summary>Strict mode — require a passing test before every publish</summary>

For regulated teams (or during your rollout), workspace admins can turn on strict mode so AI flows can't be published without a saved passing test:

1. With strict mode on, publishing an AI flow without a fresh saved scenario fails with: *"Strict mode is on for this workspace: run a passing test call and save it before publishing this AI flow."*
2. "Fresh" means the saved test matches the current draft — any edit after the test puts the badge into **Edited since last test** and re-blocks publishing until you re-test and re-save.
3. The publish check never places a call by itself; it only reads your last saved scenario, so provider hiccups can't block a publish on their own.

</details>

***

### What Happens on a Live Call

1. **The agent answers** — disclosure first, then your welcome greeting, in your chosen voice.
2. **The conversation runs** — the agent works through your objectives, answers from your knowledge, and captures fields as the caller volunteers them. Callers can interrupt mid-sentence.
3. **Spam never pollutes your CRM** — a screened robocall routes to the Spam port and **no contact is created**.
4. **Real callers become contacts** — once the conversation ends on a real outcome, the contact is created (or matched) and the AI-captured details are saved on it, kept separate from fields your team entered by hand.
5. **Qualified means conversions** — a qualified outcome (at or above your confidence threshold) marks the call qualified and feeds the same conversion pipeline as manual qualification, including [Google Ads conversion uploads](/guides/google-ads-integration).
6. **The flow continues** — whatever node you wired to the outcome port takes over: dial your team with a context whisper, send the SMS, or hang up politely.

***

### Where AI Shows Up in Your Data

#### Call History

On **Analytics > Call Activity**, every AI-handled call gets an **AI Agent** badge column showing its outcome (Qualified, Wants human, Spam, …). Two filters slice the list:

* **AI Handled** — yes/no: only AI calls, or only human-handled calls.
* **AI Outcome** — pick one or more specific outcomes (e.g., just Spam and Error).

<figure><img src="/files/ln8VXUyFrPhehFslY9uC" alt=""><figcaption><p>Call Activity filtered to AI-handled calls, with the AI Agent outcome column</p></figcaption></figure>

Open any call's details:

* The **Details** tab gains an **AI Agent** section — the outcome with its confidence, every captured field (name, budget, reason…), and the agent's one-line call summary.
* The **Recording** tab shows the full **AI Conversation** — every Agent/Caller turn with the agent's response time — even when no audio was recorded.

<figure><img src="/files/YEikDIREFDHpeeuIDgYx" alt=""><figcaption><p>The AI Agent section in a call's details: outcome, captured fields, and summary</p></figcaption></figure>

#### Flow Analytics (per flow)

The **Flow Analytics** panel in the editor gains an **AI Agent** section with a card per AI node:

| Metric                 | What it tells you                                                                      |
| ---------------------- | -------------------------------------------------------------------------------------- |
| **Resolution**         | Share of conversations the agent fully handled without a human or an error             |
| **Qualified / Booked** | Qualification and booking rates                                                        |
| **Transfer**           | How often callers were handed to a human                                               |
| **Spam blocked**       | Robocalls screened out                                                                 |
| **Outcome bar**        | Every outcome with its count — including escalations (Low confidence, No input, Error) |
| **Avg turns**          | Average conversation length in agent replies                                           |
| **Avg / P95 latency**  | How fast the agent responds; flagged amber above 1s and red above 1.4s                 |
| **Confidence**         | Average qualification confidence with a distribution chart                             |

<figure><img src="/files/CA1qqjtTxGLlt2ASpdAN" alt=""><figcaption><p>The AI Agent section of the Flow Analytics panel: rates, outcome distribution, turns, latency, and confidence per node</p></figcaption></figure>

#### Analytics → AI Agent (whole workspace)

The **AI Agent** page under Analytics rolls the same metrics up across **every flow**: summary cards (with period-over-period change when comparison is on), then a table with one row per flow — click a row to expand its per-node cards. Flows with an AI node that received no AI calls in the range still appear with a *"No AI sessions in this range"* note, so a freshly published flow is never invisible. Date, campaign, source, and medium filters work like every other analytics page.

<figure><img src="/files/WX2i06QW6XLBGOyzIjBB" alt=""><figcaption><p>The Analytics → AI Agent page: summary cards and the per-flow breakdown table</p></figcaption></figure>

***

### Monitoring & Alerts

Ring Tonic watches your agent's response speed continuously. If the 95th-percentile response gap degrades past \~1.4 seconds over the recent window, workspace admins receive an email — **"AI Agent Response Time Degraded"** — with the measured latency and what to check:

* Your OpenAI account status and rate limits
* The model selected on the AI node (a faster model improves latency)
* Very large knowledge/FAQ blocks, which slow every reply

Alerts are throttled to at most one per hour per workspace.

***

### Troubleshooting

| Problem                                       | Fix                                                                                                                                                                                                                     |
| --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| "No ElevenLabs voices found" on the Voice tab | Add your ElevenLabs API key in the workspace's **Voice & Audio** settings, then reopen the panel.                                                                                                                       |
| **"AI Agent is incomplete"** when publishing  | A required port (Qualified, Wants Human, Error — plus Booked if booking is on) is unwired, or the system prompt / disclosure text is empty. The toast lists exactly what's missing; click **Open** to jump to the node. |
| Publish blocked mentioning a calendar         | **Book appointment** is enabled but no Google Calendar is connected — connect it under **Settings > Integrations**, or disable the action.                                                                              |
| Publish blocked by strict mode                | Run a **Test call**, get a passing result, click **Save as scenario**, then publish.                                                                                                                                    |
| Test call stuck on "Connecting…"              | Allow microphone access in your browser, and confirm your Twilio credentials are valid in workspace settings.                                                                                                           |
| Every call routes to the Error port           | Usually a missing or invalid OpenAI API key — verify it under **AI Automation** in workspace settings, then place a test call.                                                                                          |
| "AI Agent Response Time Degraded" email       | See [Monitoring & Alerts](#monitoring-and-alerts) above.                                                                                                                                                                |

***

### Best Practices

* **Write the system prompt like a job description** — who the agent is, what success looks like, what it must never do.
* **Keep the knowledge tight.** Short, factual business info and FAQs beat long pasted pages — both for accuracy and response speed.
* **Wire every recommended port.** Spam → Hangup and Low Confidence → a human reviewer turn "lost" calls into handled ones.
* **Test after every meaningful edit.** The **Edited since last test** badge exists for a reason — conversations are sensitive to prompt changes.
* **Start with transfer generous, tighten later.** Early on, let borderline calls reach your team; raise the confidence threshold once you trust the agent's judgment.
* **Watch the AI Agent analytics weekly.** A rising transfer rate or falling resolution rate is your earliest signal that the prompt or knowledge needs attention.

***

### Related Guides

{% content-ref url="/pages/nn3YnO9ibI1GirGOq05c" %}
[Call Flow Builder](/guides/call-flow-builder)
{% endcontent-ref %}

{% content-ref url="/pages/crg7tMxXMDacQLAiSpgl" %}
[Setup Workspace](/guides/setup-workspace)
{% endcontent-ref %}

{% content-ref url="/pages/tr9a9To8aNSbRTTJ3u8R" %}
[Google Ads Integration](/guides/google-ads-integration)
{% endcontent-ref %}

{% content-ref url="/pages/FqrMOC4HeyPH7W0Eqtdm" %}
[Analytics](/guides/analytics)
{% endcontent-ref %}


# Share Campaign

<figure><img src="/files/whi3w9pXit2cdwnwUEWI" alt=""><figcaption><p>Public campaign link with your custom branding</p></figcaption></figure>

Share campaign analytics with clients via a secure public link. Perfect for agencies who want to give clients visibility into call performance without requiring a Ring Tonic account.

{% hint style="info" %}
Shareable analytics is available on the **Agency plan** only.
{% endhint %}

***

### What Gets Shared?

When you share a campaign, clients can view:

| Page                                                                                                                   | What's Included                                   |
| ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- |
| [**Call Activity**](https://help.ringtonic.app/guides/pages/FqrMOC4HeyPH7W0Eqtdm#id-1.-call-activity-analytics)        | Stats, call volume chart, and call logs table     |
| [**Attribution**](https://help.ringtonic.app/guides/pages/FqrMOC4HeyPH7W0Eqtdm#id-2.-attribution-analytics)            | Source/medium performance breakdown               |
| [**Tracking Numbers**](https://help.ringtonic.app/guides/pages/FqrMOC4HeyPH7W0Eqtdm#id-3.-tracking-number-performance) | Individual number performance metrics             |
| [**Money Map**](https://help.ringtonic.app/guides/pages/FqrMOC4HeyPH7W0Eqtdm#id-4.-money-map)                          | Interactive heatmap of visitor and call locations |

By default clients see everything above. You can hide any report tab — or individual cards, charts, and tables within a tab — so each client sees only what's relevant. See [Choose What Clients See](#choose-what-clients-see).

{% hint style="info" %}
**Website Tracker campaigns** can track phone calls, website forms, or both. The shared analytics page reflects the campaign's enabled tracking methods — for example, a form-only campaign will show form submission data without call activity.
{% endhint %}

Clients can view call details (duration, status, transcription, recording) but cannot edit anything—all data is read-only.

{% hint style="success" %}
**Live Data:** Share links show real-time data, not a snapshot. Clients always see the latest call activity.
{% endhint %}

{% hint style="info" %}
**Timezone:** Times on the shared report are shown in the campaign's timezone. By default that's your workspace timezone, but on the Agency plan you can set a per-campaign timezone so clients see call times in their own local time — see [Campaign Timezone](https://help.ringtonic.app/guides/pages/VdOTbPSa6hi12UUj6ZLp#id-4.-campaign-timezone).
{% endhint %}

***

### Enable Sharing

<figure><img src="/files/OR5wQjQI7MHVTRFBuXdo" alt=""><figcaption><p>Enable sharing for a campaign</p></figcaption></figure>

1. Go to **Campaigns** and select the campaign you want to share
2. Click the **Share** button in the campaign header
3. Toggle **Enable sharing** to generate your share link
4. Copy the link and send it to your client

***

### Password Protection (Optional)

Add a password to restrict access:

1. In the Share modal, enter a password in the **Password** field
2. Click **Save** to apply protection
3. Clients will need to enter this password before viewing analytics

To remove password protection, clear the password field and save.

***

### Choose What Clients See

By default a shared link shows every report and widget. You can curate it — hide whole report tabs, or hide the individual cards, charts, and tables within a tab — so each client sees only what's relevant to them.

<figure><img src="/files/LyTGQCeBnEkLWsaRudU2" alt=""><figcaption><p>The Visible sections panel in the Share modal, with per-tab and per-widget toggles</p></figcaption></figure>

{% stepper %}
{% step %}

#### Open the Visible sections panel

In the campaign's Share modal, turn on **Enable sharing**. The **Visible sections** panel appears below the password option.
{% endstep %}

{% step %}

#### Toggle what to show

Switch any report tab on or off. Within a tab, switch its individual widgets — metric cards, charts, and tables — on or off. Turning a tab off hides everything inside it.
{% endstep %}

{% step %}

#### Save

Click **Save**. The shared link updates immediately for anyone who opens it.
{% endstep %}
{% endstepper %}

Here's what you can show or hide on each tab:

| Report tab           | Widgets you can toggle                                      |
| -------------------- | ----------------------------------------------------------- |
| **Call Activity**    | Metric cards · Activity chart · **Individual call records** |
| **Attribution**      | Metric cards · Source performance table · Attribution chart |
| **Tracking Numbers** | Metric cards · Performance table                            |
| **Money Map**        | Metric cards · Interactive map · Top cities                 |

{% hint style="warning" %}
**Hiding caller details:** The **Individual call records** toggle controls the per-call table — caller phone numbers, recordings, and transcripts. Turn it off to share call volume and trends while keeping individual caller information private. The aggregate metric cards and chart stay visible.
{% endhint %}

{% hint style="success" %}
**Truly private, not just hidden.** When you hide a report or the call-records table, the information behind it isn't sent to the client's browser — so it can't be read from the page either.
{% endhint %}

{% hint style="info" %}
At least one report tab must stay visible. The shared link always opens on the first visible tab, and hidden tabs don't appear in the navigation.
{% endhint %}

***

### White-Label Branding

Share pages automatically use your workspace branding:

| Configuration                        | What Clients See        |
| ------------------------------------ | ----------------------- |
| **White-label with logo**            | Your custom logo        |
| **White-label with brand name only** | Your brand name as text |
| **Workspace logo uploaded**          | Your workspace logo     |
| **No branding configured**           | Ring Tonic logo         |

{% hint style="info" %}
Configure your workspace logo in **Settings** → **Workspace**, or set up a white-label domain in **Settings** → **White Label** for full customization including brand name and logo.
{% endhint %}

***

### Disable Sharing

To revoke access:

1. Open the campaign's Share modal
2. Toggle **Enable sharing** off
3. The share link immediately stops working

{% hint style="danger" %}
**Instant revocation:** Disabling sharing invalidates the link immediately. Anyone with the old link will see a "not found" error.
{% endhint %}

***

### Regenerate Link

If you need a new share URL (e.g., the link was shared with the wrong person):

1. Open the Share modal
2. Click **Regenerate Link**
3. Confirm the action
4. Copy and share the new link

{% hint style="warning" %}
**Old links stop working.** Regenerating creates a new URL and invalidates the previous one. Make sure to send the new link to your client.
{% endhint %}

***

### Common Questions

<details>

<summary>Can I hide caller phone numbers or specific reports from clients?</summary>

Yes. In the Share modal's **Visible sections** panel you can hide whole report tabs or individual widgets. To share performance without exposing caller details, turn off **Individual call records** on the Call Activity tab — clients still see call volume and trends, but not phone numbers, recordings, or transcripts. See [Choose What Clients See](#choose-what-clients-see).

</details>

<details>

<summary>Do share links expire?</summary>

No, share links remain active indefinitely until you disable sharing or regenerate the link.

</details>

<details>

<summary>Can clients download or export data?</summary>

No, shared analytics are view-only. Clients cannot export call logs or download recordings.

</details>

<details>

<summary>Will clients see my other campaigns?</summary>

No, each share link is scoped to a single campaign. Clients only see data for the specific campaign you shared.

</details>

<details>

<summary>Can I share multiple campaigns with the same client?</summary>

Yes, enable sharing on each campaign and send the client multiple links. Each campaign has its own unique share URL.

</details>

<details>

<summary>What happens if I downgrade from Agency plan?</summary>

Existing share links will show an "unavailable" page. Re-upgrading to Agency plan restores access without needing to regenerate links.

</details>


# Phone Numbers

### What are Phone Numbers?

Phone numbers in Ring Tonic are your inventory of tracking numbers that can be assigned to campaigns. Think of them as a pool of resources that you manage centrally and allocate to different marketing initiatives.

{% hint style="info" %}
All phone numbers in Ring Tonic are actual Twilio phone numbers. Ring Tonic manages the webhook configuration and routing automatically based on campaign assignments.
{% endhint %}

***

### Understanding Phone Number Status

Phone numbers in your inventory can be in one of two states:

* **Assigned:** Currently linked to a campaign and actively tracking calls
* **Unassigned:** Available in your inventory but not linked to any campaign

{% hint style="success" %}
**Best Practice:** Keep a few unassigned numbers in your inventory as reserves. This makes it faster to launch new campaigns since you can skip the number purchasing step.
{% endhint %}

***

### Managing Your Phone Numbers

#### Viewing Your Inventory

1. Go to **Phone Numbers** in the main navigation
2. View your complete inventory with:
   * **Total Numbers:** All tracking numbers in your account
   * **Active Campaigns:** Numbers currently assigned to campaigns
   * **Unassigned:** Numbers available for assignment

<figure><img src="/files/U3Z5vVewUBuEBYdPaJde" alt=""><figcaption><p>Phone numbers inventory dashboard</p></figcaption></figure>

The phone numbers table shows:

* **Phone Number:** The actual phone number (formatted for readability)
* **Friendly Name:** Optional custom label for easy identification
* **CNAM:** Caller Name lookup status (On/Off) - shows whether CNAM is enabled for this number
* **Calls:** Call control status (On/Off) - shows whether calling is enabled or disabled for this number (Agency plan)
* **Campaign:** Which campaign the number is assigned to (or "Unassigned")
* **Type:** Campaign type (Website Tracker or Static)
* **Forwarding To:** The business number where calls are routed
* **Last Call:** When the number last received a call

#### Filtering and Searching

Use the built-in filters to find specific numbers:

**Status Filter:**

* **Assigned:** Show only numbers linked to campaigns
* **Unassigned:** Show only available numbers

**Campaign Filter:**

* Filter by specific campaign to see all numbers assigned to it

**Search:**

* Search by phone number to quickly locate a specific number
* Search by friendly name to find numbers by your custom labels

***

### Importing Numbers from Twilio

If you already own phone numbers in your Twilio account, you can import them into Ring Tonic's inventory.

#### How to Import Numbers

1. Go to **Phone Numbers** → **Import Numbers**
2. Ring Tonic automatically loads all phone numbers from your Twilio account
3. Browse your numbers showing:
   * Phone number and friendly name
   * Voice/SMS/MMS capabilities
   * Current webhook configuration
   * Import status (whether already imported)
4. Select the numbers you want to import:
   * Click individual checkboxes to select specific numbers
   * Multiple selection allows bulk importing
5. Click **Import** to add them to your inventory

{% hint style="success" %}
**Important:** Ring Tonic does not override the Voice URL when you import a number. It keeps working with its existing setup until you assign a campaign, ensuring zero call downtime during migration.
{% endhint %}

<figure><img src="/files/8NP64hxYyzztJxqByNTC" alt=""><figcaption><p>Import existing numbers from your Twilio account</p></figcaption></figure>

***

### Editing Friendly Names

Friendly names help you identify numbers at a glance without memorizing phone numbers.

#### How to Set a Friendly Name

1. Go to **Phone Numbers**
2. Find the number you want to label
3. Click the **Edit** (pencil) icon
4. Enter a friendly name (e.g., "Downtown Billboard", "Facebook Ads Reserve", "VIP Hotline")
5. Click **Update**

{% hint style="success" %}
**Pro Tip:** Use descriptive friendly names that indicate the number's purpose or source. For example: "Q4 Radio Campaign" or "LinkedIn Ads - Tech Audience"
{% endhint %}

<figure><img src="/files/a3IE6Lhm0DnmRJBBPpke" alt=""><figcaption><p>Set custom friendly names for easy identification</p></figcaption></figure>

{% hint style="info" %}
The friendly name is also synced to Twilio, so it appears in your Twilio console as well.
{% endhint %}

***

### Toggling CNAM Lookup

CNAM (Caller Name) lookup retrieves the caller's name from the phone carrier database when a call comes in. This can help identify callers before you answer.

<figure><img src="/files/ejJB9ogOAzGgHI0MfWem" alt=""><figcaption><p>Toggle CNAM Lookup Action</p></figcaption></figure>

#### How to Toggle CNAM Lookup

1. Go to **Phone Numbers**
2. Find the number you want to configure
3. Click the **Toggle CNAM** (user) icon
4. The CNAM status will toggle between On and Off

The CNAM column in the table shows the current status:

* **On** (green badge): CNAM lookup is enabled for this number
* **Off** (gray badge): CNAM lookup is disabled

{% hint style="warning" %}
**Cost:** CNAM lookup costs $0.01 per call. Only enable it on numbers where caller identification is valuable to your business.
{% endhint %}

{% hint style="info" %}
**How it works with AI:** If you have "Automatically detect caller name" enabled in your workspace AI settings, the AI will extract caller names from call transcriptions. When both CNAM and AI detection are enabled, AI will only override the CNAM-provided name if it has high confidence (above 80%) in its detection.
{% endhint %}

***

### Per-Number Call Control (Agency Plan)

{% hint style="info" %}
This feature is available exclusively on the **Agency plan**. If you're on the Indie plan, you'll see the action but will be prompted to upgrade.
{% endhint %}

While the workspace-level [Call Control](https://help.ringtonic.app/guides/pages/crg7tMxXMDacQLAiSpgl#id-2.-call-control-disable-calls-for-a-workspace-agency-plan) disables **all** calling for a workspace, per-number call control lets you disable calling for **individual phone numbers**. This is useful when you need to suspend a specific line while keeping the rest of the workspace active—for example, pausing a single campaign number that's under review or temporarily suspending service for a specific client line.

#### How It Works

When a number has calling disabled:

* **Inbound calls** to that specific number are rejected (busy signal or custom message)
* **Outbound dialer** cannot use that number as a caller ID
* **No call logs** are created for rejected inbound calls
* **Other numbers** in the workspace continue to work normally

{% hint style="warning" %}
**Workspace takes precedence:** If workspace-level calling is disabled, all numbers are rejected regardless of their individual settings.
{% endhint %}

#### Identifying Disabled Numbers

The phone numbers table includes a **Calls** column that shows the current status of each number:

* **On** (green badge): Calling is enabled — the number accepts inbound calls and can be used for outbound dialing
* **Off** (red badge): Calling is disabled — inbound calls are rejected and the number is unavailable for outbound dialing

You can also use the **Calls** filter to quickly find all enabled or disabled numbers in your inventory.

<figure><img src="/files/LyTGQCeBnEkLWsaRudU2" alt=""><figcaption><p>The Calls badge column shows On/Off status for each number, with a filter to show only enabled or disabled numbers</p></figcaption></figure>

#### How to Disable Calls for a Number

1. Go to **Phone Numbers**
2. Find the number you want to disable
3. Click the **Call Control** (phone-off) icon in the actions dropdown
4. Toggle **"Accept Calls"** off
5. Choose a rejection method:

| Method             | What Callers Hear                           | Twilio Cost      | Best For                                             |
| ------------------ | ------------------------------------------- | ---------------- | ---------------------------------------------------- |
| **Busy Signal**    | A standard busy tone, then the call ends    | $0 (no charge)   | Temporary suspensions where you don't need a message |
| **Custom Message** | Your custom message, then the call hangs up | \~$0.01 per call | Professional communication with callers              |

6. If you chose **Custom Message**, enter your message (up to 500 characters)
7. Click **"Disable Calls"** to save

<figure><img src="/files/sRdeAJwSheEjhvhh4367" alt=""><figcaption><p>The Call Control modal with options to disable calls using a busy signal or custom message</p></figcaption></figure>

#### Re-enabling Calls for a Number

1. Click the **Call Control** icon on the disabled number
2. Toggle **"Accept Calls"** back on
3. Click **"Save"**

The number will immediately start accepting inbound calls and become available for outbound dialing again.

{% hint style="info" %}
**Plan downgrade:** If you downgrade from the Agency plan, all individually disabled numbers are automatically re-enabled to ensure no numbers are stuck in a disabled state.
{% endhint %}

***

### Assigning Numbers to Campaigns

You can assign or reassign numbers to campaigns directly from the phone numbers page.

#### How to Assign a Number

1. Go to **Phone Numbers**
2. Find the number you want to assign
3. Click the **Assign** (link) icon
4. Select a campaign from the dropdown
   * Shows all campaigns in your workspace
   * Organized alphabetically for easy browsing
5. Review any warnings (if applicable)
6. Click **Assign** to confirm

<figure><img src="/files/MNzIqHXx25aQ0GN5H8xY" alt="" width="563"><figcaption><p>Assign phone number to a campaign</p></figcaption></figure>

#### Assignment Warnings

Ring Tonic shows warnings when an assignment could impact existing campaigns or active calls:

**Warning 1: Moving Between Campaigns**

<figure><img src="/files/JNsY71x17WzfmmDYicqM" alt="" width="563"><figcaption><p>Warning 1: Moving Between Campaigns</p></figcaption></figure>

If the number is already assigned to another campaign:

* **Type:** Warning
* **Message:** "This number will be removed from \[Campaign Name]. That campaign may stop working if it's a static campaign."
* **Impact:** The origin campaign loses this number

{% hint style="danger" %}
**Critical for Static Campaigns:** Static campaigns typically use a single number. Moving that number to another campaign will break the static campaign's call routing.
{% endhint %}

**Warning 2: Active Visitor Session**

If the number is currently displayed to a visitor on your website (Website Tracker campaigns):

* **Type:** Danger
* **Message:** "This number is currently displayed to a visitor on your website. Unassigning it now may cause a failed call for that visitor."
* **Impact:** Active website visitors may see an error if they call

**Warning 3: Empty Campaign**

If removing this number would leave the campaign with no numbers:

* **Type:** Warning
* **Message:** "Removing this number will leave \[Campaign Name] with no numbers. Calls to this campaign will stop."
* **Impact:** The campaign can't receive any calls

<figure><img src="/files/BKO5Dw834JUbOUs5zxNW" alt="" width="563"><figcaption><p>Ring Tonic warns you about potential impacts before reassignment</p></figcaption></figure>

#### Unassigning Numbers

You can also unassign a number to return it to your available inventory:

1. Click the **Assign** (link) icon on the number
2. Select **"Unassigned"** from the dropdown
3. Review warnings (same warnings apply as above)
4. Click **Unassign** to confirm

{% hint style="info" %}
The number is returned to your inventory and available for future use.
{% endhint %}

<figure><img src="/files/GtQz1ZmjEhS4ZWVfQcKV" alt="" width="563"><figcaption><p>Unassign number from a campaign</p></figcaption></figure>

***

### Deleting Numbers

When you no longer need a phone number in Ring Tonic, you can delete it from your inventory. You have the option to also release the number from your Twilio account.

<figure><img src="/files/dDHiByVx5kP9HlHJOEMP" alt="" width="563"><figcaption><p>Delete phone number modal</p></figcaption></figure>

#### How to Delete a Number

1. Go to **Phone Numbers**
2. Find the number you want to delete
3. Click the **Delete** (trash) icon
4. Choose whether to also release from Twilio:
   * **Keep in Twilio (default):** The number is removed from Ring Tonic but remains in your Twilio account. You can re-import it later.
   * **Also release from Twilio:** The number is permanently deleted from both Ring Tonic and your Twilio account.
5. Click **Delete** to confirm

{% hint style="info" %}
**Default behavior:** By default, deleting a number only removes it from Ring Tonic. The number stays in your Twilio account and you continue to pay for it. This allows you to re-import it later if needed.
{% endhint %}

{% hint style="danger" %}
**Warning:** If you enable "Also release from Twilio", the action is permanent and cannot be undone. The number will be:

* Deleted from Ring Tonic
* Released from your Twilio account
* No longer associated with your account
* Potentially reassigned to another Twilio customer

Make sure you really want to release the number before enabling this option.
{% endhint %}

{% hint style="success" %}
**Tip:** If you're unsure, keep the default option (don't release from Twilio). You can always release the number from your Twilio console later.
{% endhint %}

***

### Transferring Numbers Between Workspaces

If you own multiple workspaces that share the same Twilio account, you can transfer phone numbers between them.

<figure><img src="/files/wudjmfCiE7r7co65R7wZ" alt="" width="563"><figcaption><p>Transfer phone number modal</p></figcaption></figure>

#### Requirements for Transfer

* You must be the **owner** of both workspaces
* Both workspaces must use the **same Twilio account** (the phone number must exist in the destination workspace's Twilio account)

#### How to Transfer a Number

1. Go to **Phone Numbers**
2. Find the number you want to transfer
3. Click the **Transfer** (arrow) icon
4. Select the destination workspace from the dropdown
5. Click **Transfer** to confirm

#### What Happens During Transfer

When you transfer a phone number:

* The number is **unassigned** from any campaign in the current workspace
* The Twilio webhook is set to **parking** (calls won't be routed until assigned to a new campaign)
* The number appears as **unassigned** in the destination workspace
* All call history remains associated with the original workspace

{% hint style="warning" %}
**Important:** After transfer, you'll need to assign the number to a campaign in the destination workspace before it can receive calls.
{% endhint %}

{% hint style="info" %}
**Why same Twilio account?** Ring Tonic verifies that the phone number exists in the destination workspace's Twilio account before allowing the transfer. This ensures the number can be properly managed in the new workspace.
{% endhint %}

***

### Common Questions

<details>

<summary>What happens when I import a number?</summary>

The number is added to your Ring Tonic inventory without changing its existing webhook configuration. This means the number continues working exactly as before until you assign it to a campaign. This ensures zero downtime during migration.

</details>

<details>

<summary>Can I import the same number twice?</summary>

You cannot import a number that's already in your inventory - it will be marked as "imported" and disabled in the import interface. However, if you delete a number from Ring Tonic (without releasing from Twilio), you can re-import it later.

</details>

<details>

<summary>Will deleting a number delete its call history?</summary>

No, call logs are preserved even after deleting a number. However, you won't be able to use that number for new campaigns unless you re-import it.

</details>

<details>

<summary>What's the difference between deleting and releasing from Twilio?</summary>

Deleting removes the number from Ring Tonic only - the number stays in your Twilio account and you can re-import it later. Releasing from Twilio permanently removes the number from both Ring Tonic and your Twilio account.

</details>

<details>

<summary>Can I reassign a number from a Website Tracker campaign to a Static campaign?</summary>

Yes, but be careful. Removing numbers from Website Tracker campaigns reduces the pool size, which could cause number exhaustion if you have high traffic.

</details>

<details>

<summary>What's the difference between unassigning and deleting?</summary>

Unassigning keeps the number in your Ring Tonic inventory but makes it available for other campaigns. Deleting removes it from Ring Tonic entirely (optionally from Twilio too).

</details>

<details>

<summary>Can I transfer a number to any workspace?</summary>

No, you can only transfer numbers to workspaces you own that share the same Twilio account. Ring Tonic verifies the number exists in the destination workspace's Twilio account before allowing the transfer.

</details>

<details>

<summary>What happens to call history when I transfer a number?</summary>

Call history stays with the original workspace. The transferred number starts fresh in the destination workspace with no prior call data.

</details>

<details>

<summary>Why can't I see the transfer option?</summary>

The transfer option only appears if you own multiple workspaces. Only workspace owners can transfer numbers - team members with manager or member roles cannot transfer.

</details>

<details>

<summary>What is CNAM and should I enable it?</summary>

CNAM (Caller Name) is a phone carrier service that looks up the caller's name when they call. It costs $0.01 per lookup. Enable it on numbers where knowing the caller's identity is valuable (e.g., sales lines), but you can leave it off for high-volume or marketing numbers to save costs.

</details>

<details>

<summary>How does CNAM work with AI caller name detection?</summary>

If both CNAM and AI caller name detection are enabled, Ring Tonic uses CNAM data first (from the phone carrier). The AI will only override the CNAM-provided name if it detects a name in the transcription with high confidence (above 80%). This gives you the best of both: immediate caller ID from CNAM and more accurate names extracted from the actual conversation.

</details>

<details>

<summary>What's the difference between workspace call control and per-number call control?</summary>

Workspace call control (in workspace settings) is a master switch that disables ALL calling for every number in the workspace. Per-number call control lets you disable individual numbers while keeping the rest active. Workspace-level always takes precedence — if the workspace is disabled, individual number settings don't matter.

</details>

<details>

<summary>What happens to disabled numbers if I downgrade from the Agency plan?</summary>

All individually disabled numbers are automatically re-enabled when you downgrade. This ensures no numbers are stuck in a disabled state that you can no longer manage. Your previous call control settings (busy signal vs. custom message) are preserved in case you upgrade again.

</details>


# Blocked Numbers

<figure><img src="/files/MvWrSjXQjLz6poWRrXdt" alt=""><figcaption><p>Blocked numbers management page</p></figcaption></figure>

Blocked numbers let you prevent specific phone numbers from calling your tracking numbers. When a blocked number calls, it is silently rejected — no ring, no charge, no call log clutter.

{% hint style="info" %}
Blocked numbers are available on **all plans** (Indie and Agency). There is no limit on how many numbers you can block.
{% endhint %}

***

## How It Works

When someone calls your tracking number, Ring Tonic checks the block list **before** connecting the call. If the caller is blocked, the call is instantly rejected and logged as a blocked attempt. The caller hears nothing — no ringing, no voicemail.

Blocked calls:

* Do **not** appear in your call logs
* Do **not** count toward your call usage
* Are logged separately as blocked attempts (retained for 90 days)
* Trigger a `call.blocked` webhook if configured

***

## Two-Tier Block Lists

Ring Tonic supports two levels of blocking:

| Level         | Scope                                          | Who can manage       |
| ------------- | ---------------------------------------------- | -------------------- |
| **Workspace** | Blocks a number in the current workspace only  | Any workspace member |
| **Account**   | Blocks a number across **all** your workspaces | Workspace owner only |

{% hint style="info" %}
The **Account Block List** tab only appears if you own more than one workspace. If you have a single workspace, only the workspace-level list is shown.
{% endhint %}

When a call comes in, Ring Tonic checks **both** lists. If the caller appears on either the workspace block list or the account block list, the call is rejected.

***

## Blocking a Number

{% stepper %}
{% step %}
**Open Blocked Numbers**

Navigate to **Blocked Numbers** in the sidebar.

<figure><img src="/files/fgKD77rDIwI1JITM0nvt" alt=""><figcaption><p>Blocked numbers page with Block Number button</p></figcaption></figure>
{% endstep %}

{% step %}
**Click Block Number**

Click the **Block Number** button in the top-right corner.
{% endstep %}

{% step %}
**Fill In the Details**

* **Phone Number** — Enter the number to block
* **Reason** — Select a reason (Spam, Harassment, Wrong Number, Telemarketer, Competitor, or Other)
* **Note** (optional) — Add context about why you're blocking this number
* **Mark as Junk** — Toggle this on to automatically mark all existing **pending** calls from this number as Junk. Calls that have already been qualified will not be affected.

Click **Block Number** to confirm.

<figure><img src="/files/CCsjKOY2f6myzyBRoDTU" alt="" width="563"><figcaption><p>Block number dialog with phone number, reason, and note fields</p></figcaption></figure>
{% endstep %}
{% endstepper %}

### Block Reasons

| Reason          | Description                                      |
| --------------- | ------------------------------------------------ |
| Spam / Robocall | Automated or junk calls                          |
| Harassment      | Threatening or abusive callers                   |
| Wrong Number    | Persistent misdials                              |
| Telemarketer    | Unwanted sales calls                             |
| Competitor      | Suspected competitor calling your tracking lines |
| Other           | Any other reason                                 |

***

## Blocking from Call Logs

You can block a caller directly from the call logs table without navigating to the Blocked Numbers page.

1. Find the call in your call logs
2. Click the row actions menu (three dots)
3. Select **Block Caller**
4. The block dialog opens pre-filled with the caller's phone number

{% hint style="success" %}
When blocking from a spam-filtered call, the reason is automatically pre-selected as "Spam" to save you time. You can also toggle **Mark as Junk** to clean up all pending calls from that number at the same time.
{% endhint %}

***

## Importing Blocked Numbers

If you have a list of numbers to block, you can import them in bulk via CSV.

{% stepper %}
{% step %}
**Download the Template**

Click **Import CSV** on the Blocked Numbers page, then click **Download template** to get a pre-formatted CSV file.

The template has three columns:

```
phone_number,reason,note
+14155551234,spam,Known robocaller
+14155559876,telemarketer,
```

{% endstep %}

{% step %}
**Fill In Your Numbers**

* **phone\_number** (required) — The number to block in E.164 format
* **reason** (optional) — One of: `spam`, `harassment`, `wrong_number`, `telemarketer`, `competitor`, `other`. Defaults to `other` if left blank.
* **note** (optional) — Free-text note, up to 500 characters
  {% endstep %}

{% step %}
**Upload the File**

Click **Import CSV**, select your file, and click **Import**. Ring Tonic will process the file and report:

* How many numbers were imported
* How many duplicates were skipped
* Any rows with errors
  {% endstep %}
  {% endstepper %}

{% hint style="warning" %}
The CSV file must be under 2MB. Duplicate numbers (already on the block list) are automatically skipped.
{% endhint %}

***

## Exporting Blocked Numbers

You can export your blocked numbers list to Excel or CSV.

1. On the Blocked Numbers page, click the **Export** button in the table toolbar
2. Choose **Export to Excel** (.xlsx) or **Export to CSV** (.csv)
3. The export is processed in the background — you'll receive an email with a download link when it's ready

The export includes: phone number, reason, note, blocked by, and date blocked.

***

## Viewing Blocked Call Attempts

Click any row in the blocked numbers table to open the **Blocked Call Attempts** panel. This shows a timeline of every call attempt from that number in the last 90 days, including:

* **Date and time** of each blocked call
* **Tracking number** that was called
* **Campaign** associated with the tracking number
* **Caller name** (if available)
* **Caller location** (city and state)
* **Block list type** — whether the call was blocked by the workspace or account list

<figure><img src="/files/1qeAB89OUd4zMvZZRly7" alt="" width="563"><figcaption><p>Blocked call attempts timeline showing recent call attempts</p></figcaption></figure>

{% hint style="info" %}
Blocked call attempt records are retained for **90 days**. Older records are automatically purged.
{% endhint %}

***

## Unblocking a Number

To remove a number from the block list:

1. Find the number in the blocked numbers table
2. Click the **Unblock** button (shield icon) on the row
3. Confirm by clicking **Unblock** in the confirmation dialog

The number will immediately be able to call your tracking numbers again. Future calls from that number will be processed normally and appear in your call logs.

{% hint style="warning" %}
**Permissions:** Only workspace owners and admins can unblock numbers from the workspace list. Only the workspace owner can unblock numbers from the account list.
{% endhint %}

***

## Outbound Call Blocking

Blocked numbers also affect outbound calls made through the browser dialer. If an agent tries to dial a blocked number, the call will be prevented and an error message is shown with the block reason.

***

## Webhooks

If you have webhooks configured, Ring Tonic fires a `call.blocked` event whenever a blocked call is rejected. This is useful for tracking blocked call volume in external systems.

{% content-ref url="/pages/cYbBeg8dB6cXyXveMyCZ" %}
[Webhooks](/guides/webhooks)
{% endcontent-ref %}

***

## Common Questions

<details>

<summary>Does blocking a number cost anything?</summary>

No. Blocked calls are silently rejected before the call connects, so there is no Twilio charge and no impact on your call usage.

</details>

<details>

<summary>Will the blocked caller hear anything?</summary>

No. The call is silently rejected. The caller will not hear ringing, a busy signal, or a voicemail greeting.

</details>

<details>

<summary>Can I block area codes or patterns?</summary>

Not currently. Blocking is per individual phone number. Area code and pattern-based blocking may be added in a future update.

</details>

<details>

<summary>What happens if a number is on both the workspace and account block lists?</summary>

The call is blocked either way. Unblocking from one list does not affect the other — the number must be removed from both lists to allow calls through.

</details>

<details>

<summary>How long are blocked call attempts stored?</summary>

Blocked call attempt records are retained for 90 days. Older records are automatically purged.

</details>

<details>

<summary>Is there a limit to how many numbers I can block?</summary>

No. You can block an unlimited number of phone numbers on any plan.

</details>


# Form Submissions

Capture form submissions from your website (or your client's website) as leads in Ring Tonic — without changing the website's own form code. The same tracking script you already install for [Campaigns](/guides/campaigns) sends each submission back to Ring Tonic, matches it to a [Contact](/guides/contacts), and moves it into the **Form Submitted** stage of your pipeline.

{% hint style="info" %}
Form Submissions is available on the **Agency plan** only. Phone Calls and Form Attribution remain available on every plan.
{% endhint %}

***

### Why Form Submissions vs. Form Attribution?

Both features live on the same campaign and use the same script, but they do opposite things:

| Feature              | Direction                       | What it does                                                                                                                                                               | Plan      |
| -------------------- | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
| **Form Attribution** | Ring Tonic → the website's form | Adds hidden tracking details (like the Google click ID and UTM tags) into the website's existing forms, so the attribution travels with the lead into the client's own CRM | All plans |
| **Form Submissions** | The website's form → Ring Tonic | Sends a copy of the submission to Ring Tonic the moment the visitor clicks Submit — even if the website's own form fails                                                   | Agency    |

You can enable either, both, or neither on a campaign — on either a **Website Tracker** or a **Static** campaign. They are independent.

{% hint style="success" %}
**Common combo:** enable both. Form Attribution gives the client's existing CRM the marketing data it needs; Form Submissions gives Ring Tonic a guaranteed lead record even when the website's own form fails.
{% endhint %}

***

### Enabling Form Submissions on a Campaign

1. Open the campaign at **Campaigns** → your campaign → **Edit**
2. Find the tracking options — **What would you like to track?** on a Website Tracker, or **Form Tracking** on a Static campaign — and check **Form Submissions**
3. The configuration card appears below — fill in:
   * **Honeypot field name** *(optional)* — see [Anti-Spam](#anti-spam) below
   * **Field mapping** — see [Field Mapping](#field-mapping) below
   * **Origin allowlist override** — see [Origin Allowlist](#origin-allowlist) below
4. Make sure at least one domain is set under **Security** → **Allowed domains** (Form Submissions requires it)
5. Click **Update Campaign**

<figure><img src="/files/ekDGuYqTz9S3F0UPLpOv" alt=""><figcaption><p>Form Submissions configuration card on a campaign's edit page</p></figcaption></figure>

***

### Field Mapping

Field mapping tells Ring Tonic where each field on the website's form should land on the contact. For every field you want to capture, you fill in two things: which **form field** to read, and which Ring Tonic **destination** it goes to.

**Destinations you can use:**

| Destination (type this) | What it captures                                                      |
| ----------------------- | --------------------------------------------------------------------- |
| `name`                  | The contact's name                                                    |
| `email`                 | The contact's email                                                   |
| `phone`                 | The contact's phone — tidied into a standard format automatically     |
| `company`               | The contact's company                                                 |
| `value`                 | A deal value, e.g. an order total                                     |
| `custom:your_field_key` | Any of your [workspace custom fields](/guides/contacts#custom-fields) |

Custom field values are checked against the field's type — text is trimmed, numbers are parsed, and dropdowns must match one of the allowed options.

**Pointing at a form field:** in most cases, just enter the field's **name** — for example, `email` or `phone`. Not sure what it is? Ask whoever built the website, or check the form. Advanced users can also enter a CSS selector like `input[name="email"]` or `#email-input`.

{% hint style="info" %}
**Phone numbers are tidied automatically.** Whatever the visitor types — `(206) 739-4938`, `206.739.4938`, `+1 206 739 4938` — Ring Tonic converts it to a standard international format (`+12067394938`) based on your workspace's default country. If a submission has only an email and no phone, it's saved for your records but doesn't create a contact yet.
{% endhint %}

***

### Anti-Spam

Form Submissions runs three layers of bot defense — none of which require CAPTCHAs or visible challenges for real visitors.

#### Honeypot field

A hidden field that real people never fill in but bots usually do. Set a **Honeypot field name** (for example, `rt_website`) and have a matching hidden field added to the form:

```html
<input type="text" name="rt_website" tabindex="-1" autocomplete="off"
       style="position:absolute; left:-9999px">
```

{% hint style="info" %}
That snippet is a small piece of code for whoever maintains the website to add — you don't need to understand it. Once it's in place, any submission that fills in the hidden field is silently ignored. Recommended.
{% endhint %}

#### Bot detection

Ring Tonic automatically spots common bot and scraper signatures. Suspected bots are logged for your records but don't create a contact or trigger any automations. On by default; you can turn it off per campaign (see [Troubleshooting](#troubleshooting)).

#### Signed sessions

Every submission carries a short-lived, tamper-proof token that Ring Tonic issues when the page loads. This stops anyone from faking submissions or forging tracking data from outside the page. It's fully automatic — there's nothing for you to set up.

***

### Origin Allowlist

By default, Form Submissions only accepts submissions coming from the domains listed under the campaign's **Security** → **Allowed domains** (the same list that controls where your tracking script runs).

To narrow this further — for example, "run the tracking script everywhere, but only accept form submissions from `forms.acme.com`" — fill in **Origin allowlist override**. When it's not empty, it replaces the allowed-domains list for form submissions only.

{% hint style="warning" %}
Enter **just the domain** — no `https://` and no port number. A leading `www.` is treated the same as without it, so `www.acme.com` and `acme.com` count as the same domain.

* ✅ `acme.com`
* ❌ `https://acme.com`
  {% endhint %}

***

### What Happens When Someone Submits a Form

When a visitor submits a form on your site, Ring Tonic captures a copy of what they typed and saves it as a lead — the instant they click **Submit**, before the website's own form even finishes processing. So you still get the lead even if the website's form has a glitch.

<details>

<summary>Under the hood (for developers)</summary>

1. **On page load**, the tracking script requests a session that includes a short-lived, signed capture token — kept in memory only, never written to `localStorage`, `sessionStorage`, or cookies.
2. **On submit**, the script listens in the capture phase (before the website's own handler), collects the mapped fields, and sends a JSON beacon via `navigator.sendBeacon` (falling back to a keepalive `fetch`) to `POST /api/v1/campaigns/{uuid}/form-submissions`.
3. **The server validates** the HMAC signature, origin, plan, capture flag, honeypot, and bot signals — then writes the submission, creates or updates the contact, and fires the `form.submitted` and `contact.stage_changed` webhooks.
4. **On reload**, the cached session is reused and the token is silently re-issued; any submissions made before it resolves are queued and retried.

</details>

***

### Where the Data Goes

Once a submission lands successfully:

1. It's saved as a submission record, with the captured fields and attribution
2. A new or updated **Contact** appears in **Contacts** → the [Kanban](/guides/contacts#kanban-view)
3. The contact moves to the **Form Submitted** stage (first submission only — later submissions add a timeline entry but don't move the stage again)
4. The `form.submitted` webhook fires, if you've set one up (see [Webhooks](/guides/webhooks))
5. If you've connected Google Ads for this campaign, the submission is queued as an Enhanced Conversions upload

<figure><img src="/files/li5jfx9WSPUiQU2ZBkNs" alt="" width="375"><figcaption><p>A captured submission landing as a Contact in the Form Submitted stage</p></figcaption></figure>

***

### Troubleshooting

<details>

<summary>A form was submitted, but no lead shows up in Contacts</summary>

Start with these quick checks — no technical tools needed:

1. On the campaign's **Edit** page, confirm **Form Submissions** is still checked and you clicked **Update Campaign**.
2. Confirm the website's domain is listed under **Security** → **Allowed domains** (or in your Origin allowlist override).
3. Make sure you mapped at least the **Name**, **Email**, or **Phone** field.
4. If you just changed any of these settings, reload the website page and try again — the tracking script can take up to 30 minutes to pick up changes.
5. Make sure you're on the **Agency plan** (Form Submissions is Agency-only).

**Still stuck?** Hand this to a developer: open the browser's Network tab, find the request to `…/form-submissions`, and check its response code.

* **201** — it worked; refresh **Contacts** and check the **Form Submitted** column.
* **401** (session token mismatch) — clear the cached session and reload. In the DevTools console, run:

  ```js
  Object.keys(localStorage).filter(k => k.startsWith('_ct_session_')).forEach(k => localStorage.removeItem(k));
  location.reload();
  ```
* **403 `form_capture_not_enabled_for_workspace_plan`** — the workspace isn't on the Agency plan.
* **403 `form_capture_disabled`** — the feature was turned off between page load and submit.
* **403 `origin_not_allowed`** — the page's domain isn't on the allowed list.

</details>

<details>

<summary>I see a 403 error on a domain I just added</summary>

The tracking script remembers your settings for up to 30 minutes. Either wait for that to expire, or reload the page with `?ct_debug=true` added to the URL to force an immediate refresh.

</details>

<details>

<summary>Phone numbers aren't being tidied into a standard format</summary>

Phone formatting is based on your workspace's default country. Set the right country at **Settings** → **Workspace** → **Basic**. If a number can't be matched to that country, Ring Tonic keeps it exactly as typed and won't use it to match up duplicate contacts.

</details>

<details>

<summary>The Contact moved to "Form Submitted" but later went to "Qualified" — why?</summary>

That's the call qualification flow doing its job. A later qualified phone call automatically advances the contact's stage. The original form submission stays in the contact's timeline as history.

</details>

<details>

<summary>Some legitimate submissions are being marked as spam</summary>

Bot detection uses browser signals to spot automated traffic. If you have a legitimate case that looks automated (for example, a kiosk), turn it off on the campaign at **Edit** → **Bot Detection**.

</details>

***

### Related Guides

* [Campaigns](/guides/campaigns) — set up a Website Tracker or Static campaign in the first place
* [Contacts](/guides/contacts) — the pipeline view where captured submissions land
* [Webhooks](/guides/webhooks) — subscribe to `form.submitted` events
* [API](/guides/crm-api) — push form-submitted events from external systems instead of using the tracking script


# Contacts

Contacts is Ring Tonic's lightweight CRM. Every phone call and form submission your tracking generates can be matched to a contact, moved through a pipeline of stages, and tracked from first touch to closed-won revenue — without leaving the platform.

{% hint style="info" %}
The Kanban view, contact detail page, custom fields, and stage drag-and-drop are **Agency plan** features. The basic table view and individual contact details remain available on every plan.
{% endhint %}

***

### The Pipeline

Every contact has a **stage** showing where they are in your funnel. Stages are forward-only by default — a contact advances automatically (from phone calls, form submissions, or events sent from other tools), but only owners and admins can move one backward.

| Order | Stage                  | Meaning                                                                                 |
| ----- | ---------------------- | --------------------------------------------------------------------------------------- |
| 0     | **New**                | A contact exists but no event has been recorded                                         |
| 10    | **Contacted**          | An outbound or inbound interaction has happened                                         |
| 20    | **Form Submitted**     | The contact submitted a tracked form (via [Form Submissions](/guides/form-submissions)) |
| 30    | **Qualified**          | AI auto-qualification or manual review marked the lead worth pursuing                   |
| 40    | **Appointment Booked** | A calendar event was created (typically from an outside tool)                           |
| 50    | **Proposal Sent**      | A quote or proposal has been delivered                                                  |
| 100   | **Won** / **Customer** | Closed-won — revenue recognized                                                         |
| 200   | **Lost**               | Closed-lost                                                                             |
| 300   | **Unqualified**        | Excluded from the funnel (spam, wrong fit, etc.)                                        |

The terminal stages (Won, Customer, Lost, Unqualified) are **mutually exclusive** — once a contact lands in one, it stops advancing automatically. (Won and Customer are both "won" outcomes and share the same place in the funnel order.) To move a contact out of a terminal stage you have to drag it there yourself, which only owners and admins can do.

{% hint style="info" %}
**Why fixed stages?** Ring Tonic intentionally ships an opinionated stage set matching the call-tracking industry norm (CallRail, WhatConverts). This keeps funnel analytics consistent across workspaces. Workspace-customizable stages are a planned future enhancement.
{% endhint %}

***

### Kanban View

The default view at **Contacts** is a horizontally-scrolling Kanban board with one column per pipeline stage.

<figure><img src="/files/1lnfNjiucjgIXdoLhRDG" alt=""><figcaption><p>Contacts Kanban board — one column per pipeline stage, with counts and deal value</p></figcaption></figure>

**What each column shows:**

* **Stage label** (e.g. "Form Submitted") with a colored badge
* **Count** of contacts currently in that stage
* **Total deal value** — the combined value of all contacts in the column
* **Up to 50 cards**, most-recently-changed first
* **Load more** at the bottom if more cards exist

**Each card shows:**

* Contact name (or phone number if the name is blank)
* Phone number, formatted for your workspace
* Email, if known
* "About X hours ago" — when the contact last moved into this stage

**Click a card** to open the [Contact Detail](#contact-detail) page.

#### Moving cards between stages

Drag any card onto a different column to change its stage. Three behaviors:

* **Forward move** (e.g. Contacted → Qualified) — instant, no confirmation. Any logged-in user can do this.
* **Backward move** (e.g. Won → Qualified) — owners and admins only, with an **Undo** toast. Other users get a permission error.
* **Same column** — nothing happens.

{% hint style="info" %}
Moving a contact **backward** is recorded in its timeline as a manual change, and moving it out of Won or Lost automatically updates the matching won/lost close date.
{% endhint %}

<details>

<summary>Backward moves — for developers</summary>

Forward and backward moves fire the `contact.stage_changed` webhook. Backward moves use the `force_stage=true` path and are logged with `source: manual`. See the [API guide](/guides/crm-api) and [Webhooks](/guides/webhooks).

</details>

***

### Table View

Click the **Table** toggle (top-right of the Kanban) to switch to a flat, sortable, filterable table — handy for bulk operations or richer filtering.

<figure><img src="/files/r2wVKZtLlD4rgsoebETA" alt=""><figcaption><p>Contacts table view — sortable and filterable, with multi-select bulk actions</p></figcaption></figure>

* Sort by name, phone, last stage change, deal value, and more
* Filter by stage, campaign, source, or date range
* Multi-select for bulk actions (assign owner, archive, export CSV)

Ring Tonic remembers which view you used last.

***

### Contact Detail

Click any card or row to open the full contact detail page.

<figure><img src="/files/WpolHWOJT2rGfeYXRWTJ" alt="" width="563"><figcaption><p>Contact detail page — header, stage, deal value, and the timeline / tabs</p></figcaption></figure>

#### Header

* Contact name as the page title
* Current **Stage** badge
* **Value** — the contact's deal value
* Phone, email, and company (whichever are known)

#### Tabs

* **Timeline** — a chronological feed of everything tied to this contact:
  * Stage changes (showing where each one came from — a manual edit, a call, a form, or an outside tool)
  * Form submissions
  * Calls (with a link to the call detail page)
  * Notes
  * Repeat events that didn't change anything (marked **(ignored)** — see below)
* **Custom fields** — your workspace's custom fields (see [Custom Fields](#custom-fields))
* **Notes** — free-form team notes
* **Calls** — call history for this contact only
* **Forms** — form submissions for this contact, showing everything that was submitted

#### Why some events say "(ignored)"

When the same event happens twice (for example, the same visitor submits a form more than once), the first one moves the contact to the new stage. Later repeats still appear in the timeline but are marked **(ignored)**, because the contact is already at that stage. This keeps a complete history without throwing off your pipeline counts.

***

### Custom Fields

Custom fields are your own typed fields that attach to every contact. They accept values from form submissions, the API, and manual edits.

<figure><img src="/files/1UOHj46atczVUnmX2JKV" alt=""><figcaption><p>Custom fields on a contact — edit each typed field and click Save</p></figcaption></figure>

**Field types you can add:**

| Type              | What it's for                                      |
| ----------------- | -------------------------------------------------- |
| **Text**          | Free-form notes, IDs, statuses                     |
| **Number**        | Lead scores, ticket counts, quantities             |
| **Date**          | Appointment dates, deadlines                       |
| **Single Select** | One choice from a fixed list (lead source, region) |
| **Multi Select**  | Several choices from a list (tags, interests)      |
| **Boolean**       | A simple Yes/No toggle                             |
| **URL**           | A link, e.g. a LinkedIn profile                    |

#### Defining a custom field

1. Go to **Settings** → **Custom Fields**
2. Click **Add custom field**
3. Choose a **key** (a lowercase identifier like `lead_score` — it can't be changed after saving), a display **label**, and a **type**
4. For **Single Select** / **Multi Select**, add the allowed options
5. Mark **Required** if the field must be set on every contact (enforced on manual create/edit only; form submissions and API calls may leave it blank)
6. Save

{% hint style="danger" %}
**The key can't be changed.** Once a custom field is saved, its key is fixed — existing contacts' values are stored under that key. You can rename the **label** any time, and you can archive a whole field (which hides it from forms but keeps the historical values).
{% endhint %}

#### Editing custom field values on a contact

You edit custom fields one at a time, right where you see them. Open a contact — either the quick-view panel (click a card or row) or the full detail page — and go to the **Custom fields** section.

1. Find the field you want to change and click its **Edit** control.
2. An inline editor opens with the right kind of input — a text, number, date, or link box; a dropdown for Single Select; checkboxes for Multi Select; or a Yes/No toggle.
3. Make your change and click **Save**.

Each field saves on its own, so editing one never touches the others. Validation runs the moment you save (type, required, allowed options), and anything that needs fixing shows a message right on that field.

***

### How Stages Get Set Automatically

Most of the time you won't move contacts by hand — events do it for you.

| Event                                                 | Sets stage to                  | Notes                                                       |
| ----------------------------------------------------- | ------------------------------ | ----------------------------------------------------------- |
| Form submission matched by phone or email             | **Form Submitted**             | First submission only; later ones just add timeline entries |
| Phone call auto-qualified by AI                       | **Qualified**                  | Driven by your workspace's AI auto-qualification rules      |
| An event sent via the [Postback API](/guides/crm-api) | Whatever stage was sent        | Used to connect outside tools (CRM, scheduler, automations) |
| Manual drag in the Kanban                             | Whatever column you dropped on | Owners/admins for backward moves                            |

Stage advancement is **forward-only** by default. If a call or an outside event asks to move a contact *backward*, it's recorded in the timeline but the contact doesn't actually move. Only an owner or admin can move a contact backward (or a developer using the API's force option).

***

### Won and Lost Tracking

Ring Tonic tracks Won and Lost separately so your analytics can compute close rates and lost-revenue baselines.

* When a contact moves to **Won**, Ring Tonic records the close date and locks in the deal value — keeping your close-rate and revenue reports accurate.
* When a contact moves to **Lost**, it records the close date and keeps the deal value, so you can see how much potential revenue slipped away.

Funnel analytics in the [Analytics](/guides/analytics) section roll these up by source, campaign, and date range.

***

### Plan Gating

| Feature                                                            | Plan                                                      |
| ------------------------------------------------------------------ | --------------------------------------------------------- |
| Contact detail panel (quick-view)                                  | All plans                                                 |
| Kanban view, full detail page, timeline, custom fields, stage drag | Agency                                                    |
| Auto-creating contacts from form submissions                       | Agency (via [Form Submissions](/guides/form-submissions)) |
| Creating/updating contacts via the API                             | Agency (via [API](/guides/crm-api))                       |

If you open **Contacts** on a non-Agency plan, you'll see a pricing prompt. Existing contact records remain accessible via the table view and individual detail panels.

***

### Common Questions

<details>

<summary>Can I import contacts from a CSV?</summary>

Yes — **Contacts** → **Add contact** → **Import from CSV**. Required columns are `name` and at least one of `phone` or `email`. Custom field columns are matched automatically by their header to a custom field's key.

</details>

<details>

<summary>What happens to a contact's data if I archive a custom field?</summary>

The values are kept on the contact. The field just stops appearing in new contact forms and the Custom Fields tab. To bring it back, un-archive it from **Settings** → **Custom Fields**.

</details>

<details>

<summary>Can two workspaces share contacts?</summary>

No. Contacts are workspace-scoped. The same phone number can exist as a contact in multiple workspaces, but each workspace's funnel is independent.

</details>

<details>

<summary>How do duplicate contacts get merged?</summary>

Automatic merging isn't available yet. When a new call or form comes in, Ring Tonic matches it to an existing contact by checking, in order: a reference ID from your other tools, then phone number, then email. If a match is ambiguous, it doesn't guess — it flags it so you can decide. A manual merge tool is on the roadmap.

</details>

<details>

<summary>Can I create custom stages?</summary>

Not yet — the stages are a fixed set. Workspace-customizable stages are planned but not committed.

</details>

<details>

<summary>How are deleted contacts handled?</summary>

Deleted contacts are moved to the trash — they disappear from the Kanban and table, but their identifiers (reference ID, phone, and email) stay reserved. If the same lead comes in again later, it's restored instead of creating a duplicate.

</details>

***

### Related Guides

* [Form Submissions](/guides/form-submissions) — capture leads from a website
* [API](/guides/crm-api) — push contacts and conversions programmatically
* [Analytics](/guides/analytics) — funnel chart and revenue-by-source reporting
* [Webhooks](/guides/webhooks) — subscribe to `contact.stage_changed` and `conversion.recorded`


# Analytics

Ring Tonic provides powerful analytics to help you understand your call tracking performance and marketing ROI. Get a true bird-eye view of all your calls across every campaign, making it super easy for lead-gen teams to quickly see which areas are generating the most calls and which ones are underperforming.

The platform offers five comprehensive analytics reports:

* [**Call Activity**](#id-1.-call-activity-analytics)**:** Monitor call performance over time with detailed metrics on answered calls, missed calls, and call duration
* [**Attribution**](#id-2.-attribution-analytics)**:** Track which marketing sources drive the most qualified leads and revenue, with full ROI analysis
* [**Tracking Number Performance**](#id-3.-tracking-number-performance)**:** Track call volume across all active numbers with filters for custom date ranges, Yesterday, Last 7 Days, Last 30 Days, and more
* [**Money Map**](#id-4.-money-map)**:** Visualize visitor and call locations on an interactive heatmap to identify geographic hotspots
* [**AI Agent**](#id-5.-ai-agent-analytics)**:** See how your AI call agents perform across every flow — outcomes, qualification and booking rates, transfers, and response latency

<figure><img src="/files/a92QvoDmgU2rP1uwXJb9" alt="" width="375"><figcaption><p>Access Analytics from the left sidebar</p></figcaption></figure>

{% hint style="info" %}
All analytics data updates in real-time as calls come in. You can filter by date range, campaigns, sources, and mediums to drill down into specific segments.
{% endhint %}

***

### 1. Call Activity Analytics

Call Activity helps you monitor and analyze call performance across all your campaigns. This report shows you when calls are coming in, how many are answered vs missed, and how long calls typically last.

<div data-full-width="true"><figure><img src="/files/jtJIwNyaaSeIMmdUFsCz" alt=""><figcaption><p>Call Activity dashboard showing key metrics and trends</p></figcaption></figure></div>

#### What You'll See

**Captured vs Lost (Top of Page):**

The header leads with the two numbers that matter most — the leads you captured and the leads you lost — each shown with its share of your total calls (for example, "76% of 1,292 calls"):

* ✅ **Answered · captured** - Calls your team picked up
* ❌ **Missed · lost** - Calls that reached you but nobody answered — no answer, busy, or the caller hung up first (important to monitor!)

A supporting row beneath them shows where the rest of your calls went:

* **Failed** - Calls that never connected for a technical reason (a carrier error or unreachable destination), kept separate so a configuration problem doesn't hide inside your missed number
* **Spam Filtered** - Robocallers and bots blocked by your [Spam Filter](/guides/campaigns#configure-simple-routing) before they reached you
* **Voicemails** - Calls where the caller left a message
* **Avg Duration** - Average length of answered calls

{% hint style="success" %}
If comparison mode is enabled, you'll see percentage changes comparing your current period to the comparison period. Green indicates improvement, red indicates decline.
{% endhint %}

{% hint style="info" %}
**Every call lands in exactly one category.** Answered, Missed, Failed, Spam Filtered, and Voicemail always add up to your Total — so you can see at a glance where every call went, with nothing unaccounted for.
{% endhint %}

{% hint style="warning" %}
**Your answered rate may look lower than before.** Ring Tonic now separates out calls that were never really answered — a carrier voicemail picking up, a caller hanging up during a menu, or a robocall blocked by the spam filter. Those used to be grouped in with answered calls. Nothing about your calls has changed; the number is simply more accurate, and a better basis for judging real performance.
{% endhint %}

**Performance Chart:**

The chart visualizes your call data over time. You can customize the view:

* **Metric Selection:** Choose which metric to display (Total Calls, Answered Calls, Missed Calls, Failed Calls, Spam Filtered, or Avg Duration)
* **Time Grouping:** Group data by Day, Week, or Month
* **Comparison:** When enabled, overlay comparison period data to spot trends

<figure><img src="/files/27DfUkMHcQ7IHoYoKKrr" alt=""><figcaption><p>Interactive chart showing call trends with comparison mode</p></figcaption></figure>

**Call Logs Table:**

Below the chart, you'll see a detailed table of all calls with:

* Call date and time
* Campaign name
* Caller phone number
* Call duration
* Call status (Answered, Missed, Failed, Spam Filtered, Voicemail)
* Traffic source and medium (for Website Tracker campaigns)
* AI qualification status (if enabled)
* Call recording (if enabled)

{% hint style="info" %}
Click on any call row to view detailed information including transcription, sentiment analysis, keywords, and deal value estimation (if AI features are enabled).
{% endhint %}

{% hint style="info" %}
**Timezones:** Call times appear in each call's campaign timezone. When a campaign uses a timezone different from your workspace, its rows are tagged with the zone (for example "EDT"); filtering the list to a single campaign shows the whole view in that campaign's timezone with a header label. See [Campaign Timezone](https://help.ringtonic.app/guides/pages/VdOTbPSa6hi12UUj6ZLp#id-4.-campaign-timezone).
{% endhint %}

<figure><img src="/files/VmZQcXeKE95S8cCorkwQ" alt=""><figcaption><p>Detailed call logs with filters and search</p></figcaption></figure>

#### How to Use Call Activity

**Step 1: Select Your Date Range**

1. Click the date range selector at the top
2. Choose a preset (Last 7 Days, Last 30 Days, Last 60 Days) or select custom dates
3. Optionally enable comparison mode to compare against a previous period

{% hint style="warning" %}
Date range limits depend on your subscription plan:

* **Indie Plan:** Up to 180 days
* **Agency Plan:** Up to 365 days
  {% endhint %}

<figure><img src="/files/PGnvUKebmeeHSXZjnByT" alt=""><figcaption><p>Select date ranges and enable comparison mode</p></figcaption></figure>

**Step 2: Apply Filters (Optional)**

Filter your data to focus on specific segments:

1. **Campaigns:** Select specific campaigns to analyze
2. **Sources:** Filter by traffic source (Google, Facebook, Direct, etc.)
3. **Mediums:** Filter by medium (organic, cpc, referral, etc.)

Click **Apply** to refresh the data with your filters.

<figure><img src="/files/cofst1DKyXuNR95xrNsb" alt=""><figcaption><p>Filter by campaigns, sources, and mediums</p></figcaption></figure>

**Step 3: Analyze the Data**

Use the metrics and charts to identify:

* Peak call times and days
* Missed call patterns (opportunities to improve coverage)
* Campaign performance trends
* Call duration insights (longer calls might indicate higher engagement)

**Step 4: Review Call Details**

Click on any call in the table to open the Call Details sheet with four tabs:

* **Details** - Call information, caller history, campaign, source/medium, and notes
* **Lead** - AI qualification status, deal value, tags, and manual qualification controls
* **Recording** - Call recording playback, transcription with speaker labels, sentiment analysis, keywords, and AI summary
* **Timeline** - Chronological view of all call events (ring, forward, answer/no-answer, voicemail, etc.)

{% hint style="info" %}
**Timeline Tab:** The Timeline tab shows every event that occurred during the call in chronological order—from when the call started, through forwarding attempts, to voicemail if applicable. This helps you understand exactly what happened during each call.
{% endhint %}

<figure><img src="/files/XRNcKlnlxfRh9VNlqRcY" alt=""><figcaption><p>Detailed call information with transcription and AI insights</p></figcaption></figure>

**Step 5: Export Call Logs**

Need to analyze your call data in Excel or share with your team?

1. Click the **Export** button at the top right of the call logs table
2. Choose your preferred format:
   * **Export to Excel** - Full formatting with .xlsx format
   * **Export to CSV** - Plain text format for importing to other tools

{% hint style="info" %}
Exports respect your current filters and date range. All visible columns are included in the export. If you're filtering by a single campaign, the campaign name will be included in the filename automatically.
{% endhint %}

<figure><img src="/files/7SrsIgPvv32m5nibsMcE" alt=""><figcaption><p>Export call logs to Excel or CSV format</p></figcaption></figure>

**Step 6: Bulk Actions**

Select calls with the row checkboxes — or the header checkbox to select all — then open the **Actions** menu to act on them together:

* **Update Lead Status** — manually set the lead status on the selected calls
* **Add Tags** / **Remove Tags** — tag or untag the selected calls
* **Re-qualify Leads** — re-run AI qualification on the selected calls against your latest criteria

{% hint style="info" %}
Re-qualification re-runs the AI analysis on calls you already received — most useful after you change your qualification criteria. See [Re-qualify Existing Leads](/guides/setup-workspace#re-qualify-existing-leads) for the available options and how it works.
{% endhint %}

***

### 2. Attribution Analytics

Attribution shows you which marketing sources drive the most valuable calls and highest ROI. This report is essential for understanding where to invest your marketing budget.

<div data-full-width="true"><figure><img src="/files/Vx3BiVW0kAvZoBtlay6P" alt=""><figcaption><p>Attribution dashboard with ROI metrics and source performance</p></figcaption></figure></div>

#### What You'll See

**Key Metrics (Top Cards):**

1. **Total Calls** - Total number of calls received
2. **Qualified Leads** - Number of calls qualified as leads by AI (requires AI automation)
3. **Conversion Rate** - Percentage of calls that became qualified leads
4. **Top Source** - Traffic source driving the most calls
5. **Avg Deal Value** - Average estimated deal value across qualified calls (requires AI automation)

**Source Performance Table:**

The table breaks down performance by traffic source with these columns:

* **Source** - Traffic source (Google, Facebook, Direct, etc.)
* **Calls** - Total calls from this source
* **Qualified** - Qualified leads from this source
* **Conv. Rate** - Conversion rate (Qualified ÷ Calls)
* **Avg Duration** - Average call length
* **Cost** - Total marketing cost for this source
* **Revenue** - Total estimated revenue from qualified calls
* **Cost/Call** - Average cost per call (Cost ÷ Calls)
* **ROI** - Return on investment percentage

{% hint style="info" %}
The table is sortable by any column. Click column headers to sort by that metric and identify your best and worst performing sources.
{% endhint %}

<figure><img src="/files/HdKwSkvYr5qrNu3fPwca" alt=""><figcaption><p>Source performance breakdown with ROI calculations</p></figcaption></figure>

**Attribution Chart:**

Visualizes the distribution of calls, qualified leads, and revenue across your traffic sources over time.

<figure><img src="/files/srTnKn2GxzRMlBdsiual" alt=""><figcaption><p>Attribution trends across different marketing sources</p></figcaption></figure>

#### How to Use Attribution Analytics

**Step 1: Select Your Date Range**

1. Click the date range selector
2. Choose your analysis period
3. Enable comparison mode to see how performance changed over time

**Step 2: Apply Filters**

Focus on specific segments:

* **Campaigns:** Analyze specific campaign performance
* **Sources:** Compare different traffic sources
* **Mediums:** Break down by marketing medium

**Step 3: Analyze Source Performance**

Use the table to identify:

* **Highest ROI sources:** Where you're getting the best return
* **Low conversion sources:** Traffic sources that aren't converting
* **Cost efficiency:** Sources with the lowest cost per call
* **Revenue drivers:** Which sources bring the highest value deals

{% hint style="success" %}
**Best Practice:** Focus your budget on sources with high ROI and qualified lead conversion. Consider pausing or optimizing low-performing sources.
{% endhint %}

**Step 4: Export Your Data**

Need to analyze data further or share with your team?

1. Click **Export** button at the top right of the Source Performance table
2. Downloads an Excel file with all source performance data
3. Includes all visible columns and respects your current filters

<figure><img src="/files/TbEOlXBz2IlskaBD0eCE" alt="" width="563"><figcaption><p>Export source performance data to Excel</p></figcaption></figure>

{% hint style="info" %}
The export includes data for ALL sources in your workspace, not just the visible page. Use filters before exporting to narrow down the data.
{% endhint %}

***

### Understanding Marketing Costs & Revenue

To get accurate ROI calculations in Attribution analytics, you need to track marketing costs and revenue.

#### How Ring Tonic Calculates ROI

**Cost Data:** Ring Tonic integrates with your marketing platforms to automatically pull cost data. If not integrated, you can manually track costs by associating UTM parameters with budget amounts.

**Revenue Data:** When AI automation is enabled with deal value estimation:

1. AI analyzes call transcriptions
2. Estimates deal value based on conversation content
3. Sums qualified call values to calculate total revenue
4. Calculates ROI: `(Revenue - Cost) / Cost × 100`

{% hint style="warning" %}
**Important:** AI deal value estimation requires:

* OpenAI API key configured in workspace settings
* Auto estimate deal value enabled
* Optionally, a Products & Services catalog for more accurate estimates
  {% endhint %}

**Example ROI Calculation:**

```
Google Ads Campaign:
- Cost: $1,000
- Calls: 50
- Qualified Calls: 15
- Total Revenue: $7,500 (sum of estimated deal values)
- ROI: ($7,500 - $1,000) / $1,000 × 100 = 650%
```

***

### 3. Tracking Number Performance

Tracking Number Performance helps you monitor call activity across all your active phone numbers. This report identifies which numbers are performing well, which have high missed call rates, and which aren't receiving any calls at all.

<div data-full-width="true"><figure><img src="/files/kcqHYltH1UjOhnjhVqU6" alt=""><figcaption><p>Tracking Number Performance dashboard showing metrics for all active numbers</p></figcaption></figure></div>

#### What You'll See

**Captured vs Lost (Top of Page):**

The header leads with the two numbers that matter most across all your tracking numbers — the leads you captured and the leads you lost — each shown with its share of your total inbound calls:

* ✅ **Answered · captured** - Calls your team picked up
* ❌ **Missed · lost** - Calls that went unanswered (no answer or busy)

A supporting row beneath them covers the rest:

* **Failed** - Calls that never connected for a technical reason (a carrier error or unreachable destination), kept separate so a configuration problem doesn't hide inside your missed number
* **Spam Filtered** - Robocallers and bots blocked by your [Spam Filter](/guides/campaigns#configure-simple-routing) before they reached the number
* **Voicemails** - Calls where the caller left a message
* **Zero-Call Lines** - Active tracking numbers that received zero calls

{% hint style="warning" %}
**Zero-Call Lines** indicate tracking numbers that are active but not receiving any calls. Common causes include:

* **Low Website Traffic (Website Tracker):** There aren't enough visitors to rotate through your entire number pool, so some numbers are never displayed.
* **Script Installation Issue (Website Tracker):** The tracking code isn't installed correctly, so numbers aren't swapping at all.
* **Pending Launch (Static):** Marketing materials (like flyers or billboards) haven't been distributed yet.
* **Ad Issues:** The ad campaign driving traffic to the number is paused or disapproved.
  {% endhint %}

**Tracking Number Performance Table:**

The table shows detailed metrics for each active tracking number:

* **Friendly Name** - Custom label (editable inline by clicking the pencil icon)
* **Number** - The phone number (formatted for readability)
* **Campaign** - Which campaign the number is assigned to (clickable link)
* **Type** - Campaign type (Website Tracker or Static)
* **Calls** - Total calls received by this number
* **Missed** - Missed calls for this number (highlighted if the missed rate is above your threshold)
* **Failed** - Calls that never connected for a technical reason
* **Spam Filtered** - Robocallers and bots blocked before they reached the number
* **Voicemails** - Calls where the caller left a message
* **Avg Duration** - Average call length for answered calls
* **Trend** - Period-over-period percentage change (e.g., 📈 +15%)

<figure><img src="/files/vcv6xclet7ZaL6OOT7aE" alt=""><figcaption><p>Detailed performance metrics for each tracking number with trend indicators</p></figcaption></figure>

{% hint style="info" %}
**How the missed rate is calculated.** A number's missed rate counts only calls that could actually be answered. Spam-filtered and failed calls never reached the business, so they're shown in their own columns and left out of the rate. A number sitting behind the spam filter now shows its true missed rate instead of one diluted by blocked robocalls — so if you compared these figures before, some may read a little higher now. The calls haven't changed, only the way the rate is measured.
{% endhint %}

#### Understanding the Visual Indicators

**Zero-Call Numbers:**

Numbers with zero calls are highlighted with a red background, making them easy to spot. These require immediate attention to understand why they're not receiving calls.

{% hint style="success" %}
**Pro Tip:** Sort the table by "Missed" to quickly identify numbers with the highest missed call rates. These are opportunities to improve your answer rate and capture more leads.
{% endhint %}

#### Common Use Cases

**Website Tracker Campaign Monitoring:**

For Website Tracker campaigns with number pools:

* Verify the script is working (numbers should show activity)
* Identify if pool size is too large (many numbers with 0 calls despite healthy traffic)
* Ensure all active numbers are rotating correctly

**Static Campaign Health Check:**

For static campaigns:

* Confirm the single tracking number is receiving calls
* Monitor missed call rate to ensure good coverage
* Track performance after launching new marketing materials

**High Missed Call Rates:**

Numbers with a missed call rate above your workspace threshold (default: 5%) show a warning indicator:

* Review your forwarding configuration
* Check if your business number has adequate coverage during peak hours
* Consider implementing call routing rules or backup numbers
* Review the call logs to understand when missed calls occur most

{% hint style="info" %}
**Tip:** You can customize the missed call threshold in your **Workspace Settings** → **Analytics & Alerts** tab. Adjust it based on your business needs and call volume patterns.
{% endhint %}

{% hint style="danger" %}
**Critical:** High missed call rates mean you're losing potential leads. Every missed call is a lost opportunity. Use this report to identify and fix coverage gaps quickly.
{% endhint %}

**Number Pool Optimization:**

Use this report to optimize your number pools:

* Too many zero-call numbers? Your pool might be too large for your current traffic volume.
* All numbers heavily used? Your pool might be too small, risking visitor collisions.
* High missed rates across all numbers? Likely a forwarding destination or staffing coverage issue.

**Marketing Material Verification:**

After distributing new marketing materials:

* Check that the tracking number shows activity within expected timeframe
* Zero calls after launch indicates potential issue with materials or distribution
* Compare performance across different campaigns/materials

***

### 4. Money Map

Money Map visualizes where your visitors and callers are located on an interactive heatmap. Identify geographic hotspots, discover underserved areas, and understand the spatial distribution of your leads.

<figure><img src="/files/IkhW51UdINwNnPKR4TDE" alt=""><figcaption><p>Money Map Analytics Page</p></figcaption></figure>

#### What You'll See

**Key Metrics (Top Cards):**

1. **Visitors Tracked** - Number of visitors with location data (shows coverage percentage)
2. **Calls Mapped** - Number of calls with location data (shows coverage percentage)
3. **Top Visitor City** - City with the most visitor sessions
4. **Top Call City** - City generating the most calls

**Interactive Heatmap:**

The map displays two distinct layers:

* **Blue heatmap** - Visitor locations (where website visitors are browsing from)
* **Orange heatmap** - Call locations (where callers are located, or ad location for billboard tracking)

{% hint style="info" %}
**Heatmap Intensity:** Darker colors indicate higher concentrations. The orange call layer displays on top of the blue visitor layer so you can see where visitors convert to calls.
{% endhint %}

{% hint style="success" %}
**Pro Tip:** Zoom into high-activity areas to see detailed count badges. Hover over badges to see both visitor and call counts for that location.
{% endhint %}

**Top Cities Tables:**

Below the map, two tables show your top 10 cities by visitor count and call count, making it easy to identify your strongest geographic markets.

<figure><img src="/files/XSxuu2GMXxtGL98bz1LU" alt=""><figcaption><p>Top Cities Tables</p></figcaption></figure>

#### How to Use Money Map

**Step 1: Select Your Date Range**

1. Click the date range selector
2. Choose your analysis period (up to 365 days on Agency plan)
3. Click **Apply** to refresh the map

**Step 2: Apply Filters (Optional)**

Focus on specific segments:

* **Campaigns:** View locations for specific campaigns
* **Sources:** Filter by traffic source (Google, Facebook, etc.)
* **Mediums:** Filter by medium (organic, cpc, etc.)

**Step 3: Analyze Geographic Patterns**

Use the heatmap to identify:

* **High-converting areas** - Where orange (calls) overlaps with blue (visitors)
* **Underserved markets** - High visitor areas with few calls (opportunity for local targeting)
* **Service area gaps** - Calls coming from areas outside your service region
* **Ad placement validation** - For billboard/static campaigns, verify calls originate near the ad location

{% hint style="warning" %}
**Billboard Rule:** For static campaigns with [ad locations configured](/guides/campaigns#step-6-set-ad-locations-optional), the map shows where the ad is placed (not where the caller is located). This helps validate that calls are coming from your target advertising area. Without an ad location set, calls appear at the caller's location instead.
{% endhint %}

#### Common Use Cases

**Local Service Businesses:**

* Identify neighborhoods generating the most leads
* Discover new service areas with untapped demand
* Verify your local SEO is driving calls from target areas

**Multi-Location Businesses:**

* Compare lead density across different markets
* Identify which locations need more marketing support
* Track expansion opportunities based on call patterns

**Agency Reporting:**

* Show clients geographic ROI for local campaigns
* Demonstrate ad effectiveness with location data
* Identify new market opportunities for clients

***

### 5. AI Agent Analytics

If any of your flows use the [AI Agent node](/guides/ai-call-answering), the **AI Agent** page rolls its performance up across every flow in the workspace.

#### What You'll See

| Section            | What it tells you                                                                                                                              |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| **Summary cards**  | AI sessions, resolution rate, qualified and booked counts, transfers, and response latency — with period-over-period change in comparison mode |
| **Per-flow table** | One row per flow with its key rates; click a row to expand the per-node breakdown                                                              |

AI-handled calls are also labeled throughout **Call Activity** — an **AI Agent** outcome column on the call list, plus **AI Handled** and **AI Outcome** filters.

{% content-ref url="/pages/zPRsePZujXkPkJKoj7jR" %}
[AI Call Answering](/guides/ai-call-answering)
{% endcontent-ref %}

***

### Comparison Mode

All analytic reports support comparison mode to help you track performance over time.

#### How to Use Comparison Mode

**Step 1: Enable Comparison**

1. Click the date range selector
2. Toggle **Compare** switch
3. Select your comparison period

**Step 2: View Comparison Data**

* **Metric Cards:** Show percentage changes with colored indicators (green = improvement, red = decline)
* **Charts:** Overlay comparison period data as a lighter line
* **Tables:** Some tables show period-over-period changes

<figure><img src="/files/XIeq8m7iF1T8IivgwkYr" alt=""><figcaption><p>Comparison mode showing period-over-period changes</p></figcaption></figure>

**Common Comparison Scenarios:**

* **Previous Period:** Compare your selected date range to the immediately preceding period of equal length
* **Year over Year:** Compare your selected date range to the same period last year

{% hint style="success" %}
Use comparison mode to:

* Identify seasonal trends
* Measure campaign impact
* Track improvement over time
* Spot performance issues early
  {% endhint %}

***

### Best Practices

Here are some tips to get the most value from Ring Tonic analytics:

#### Daily Monitoring

**Check Call Activity daily to:**

* Monitor missed calls (respond quickly to improve conversion)
* Identify peak call times (ensure adequate staffing)
* Track campaign performance in real-time

#### Weekly Analysis

**Review Attribution weekly to:**

* Identify top performing sources
* Calculate ROI for each marketing channel
* Adjust budget allocation based on performance
* Export data for team meetings

#### Monthly Reporting

**Use comparison mode monthly to:**

* Track month-over-month growth
* Identify seasonal patterns
* Measure impact of marketing changes
* Report to stakeholders with data exports

#### Campaign Optimization

**Optimize campaigns by:**

* Pausing low-converting sources
* Increasing budget on high-ROI sources
* Testing different messaging for low-qualified sources
* Adjusting coverage hours based on peak call times


# Lead Overview

<figure><img src="/files/6JIE0naiZRQp3Gw2DAs4" alt=""><figcaption><p>The Lead Overview roll-up showing every client's leads, quotas, and status in one table</p></figcaption></figure>

Lead Overview gives you a single, account-wide table of the leads delivered across **every client and campaign** — so you never have to click into each workspace to see how a client is doing. Set a weekly or monthly quota per campaign and Lead Overview flags at a glance who's ahead of pace and who needs attention.

{% hint style="info" %}
Lead Overview is available on the **Agency plan**. It rolls up data across all the workspaces you own. On other plans, opening the page shows a preview of the feature with an option to upgrade.
{% endhint %}

Open the workspace switcher at the top of the left sidebar and choose **Lead Overview** — it's listed under **Agency**, above your workspaces. This takes you into the Agency area: the sidebar switches to agency-wide pages, with a **Workspaces** list for jumping straight into any client.

***

### How Leads Are Counted

A **lead** is a real, non-spam contact — combining both channels into one number:

* ✅ **Phone calls** — every tracked inbound call (a missed call still counts as a lead; the client can call back)
* ✅ **Web forms** — every non-spam form submission

Spam and junk are **removed from the lead count** and reported separately, so the number you see is business you actually delivered.

{% hint style="info" %}
**Robocallers don't count as leads.** Calls blocked by your [Spam Filter](/guides/campaigns#configure-simple-routing), and calls you've marked as junk, are excluded from the lead count and added to the **Spam filtered** figure instead. A single call that is both is only counted once.
{% endhint %}

{% hint style="info" %}
Times and day boundaries follow each campaign's timezone where possible. See [Campaign Timezone](https://help.ringtonic.app/guides/pages/VdOTbPSa6hi12UUj6ZLp#id-4.-campaign-timezone).
{% endhint %}

***

### Portfolio Scorecards

The cards at the top summarise your whole portfolio for the selected period:

| Card                  | What It Shows                                                           |
| --------------------- | ----------------------------------------------------------------------- |
| **Portfolio leads**   | Total leads across every client, with the change vs the previous period |
| **Clients on target** | How many campaigns are meeting or beating their pace (e.g. "7 of 12")   |
| **Spam filtered**     | Total spam kept out of your reports — proof of the value you add        |
| **Revenue**           | Attributed deal value, when lead values are recorded                    |

***

### The Roll-Up Table

Each row is one campaign. Click a column header to sort; by default the campaigns furthest behind their goal appear first, so the ones needing attention rise to the top.

| Column        | What It Shows                                                                 |
| ------------- | ----------------------------------------------------------------------------- |
| **Client**    | Campaign name and the client workspace it belongs to                          |
| **Leads**     | Combined phone calls + web forms for the period                               |
| **Δ vs prev** | Change compared to the previous period, up or down                            |
| **Trend**     | A sparkline of the last several periods so you can see the shape of the trend |
| **Goal**      | A progress bar with the count and percentage (e.g. "34 / 50 · 68%")           |
| **Status**    | A colour-coded pace flag (see [Status Explained](#status-explained))          |
| **Spam**      | The share of contacts that were filtered as spam                              |

**Drill into a row:** click the arrow on the left of any campaign to expand it and see the split — **Phone calls**, **Web forms**, and **Spam filtered** — plus a shortcut to set the quota.

***

### Setting Quotas

Quotas are the delivery targets you've agreed with a client. Once set, the campaign's **Goal** and **Status** are calculated automatically.

{% stepper %}
{% step %}

#### Open the quota editor

On any campaign row, click **Set quota** in the Goal column (or expand the row and click it there).

<figure><img src="/files/aZGLD2lrHTDIMis97tij" alt="" width="563"><figcaption><p>Setting a weekly and monthly lead quota inline from the table</p></figcaption></figure>
{% endstep %}

{% step %}

#### Enter your targets

* **Weekly target** — the number of leads expected per week
* **Monthly target** — the number of leads expected per month

Set either or both. The overview uses whichever matches the period you're viewing (weekly targets for "This week", monthly for "This month").
{% endstep %}

{% step %}

#### Save

Click **Save**. The Goal bar and Status update immediately.
{% endstep %}
{% endstepper %}

{% hint style="success" %}
You can also set quotas from the campaign's own settings page, or update several at once — whichever is quicker for you.
{% endhint %}

***

### Status Explained

Status is **pace-aware**: it compares leads delivered so far against what should have been delivered *by this point* in the period — not the full-period target. That way a campaign three days into the month isn't unfairly marked "behind."

| Status            | Meaning                                                             |
| ----------------- | ------------------------------------------------------------------- |
| ▲ **Over target** | Comfortably ahead of pace — a candidate for an upsell or case study |
| ● **On track**    | Meeting or beating the expected pace                                |
| ◆ **At risk**     | Slightly behind pace — worth a look                                 |
| ▼ **Behind**      | Well behind pace — needs attention                                  |
| **No quota**      | No target set yet, so pace can't be measured                        |

Each status pairs a colour with an icon and label, so it stays clear even at a glance.

***

### Filtering & Grouping

Use the toolbar above the table to focus the view:

* **Period** — switch between **This week**, **This month**, and **This quarter**
* **Status filter** — choose **All statuses**, or narrow to just **Off-target only** (Behind + At risk) to get a short action list
* **Group by client** — group campaigns under their client workspace, handy when a client has several campaigns

{% hint style="info" %}
The status filter and grouping update instantly without reloading. Changing the period refreshes the figures.
{% endhint %}

***

### On Mobile

On a phone, the table becomes a stack of cards — one per client — showing the lead number, trend, goal progress, and status, so you can check performance on the go.

***

<details>

<summary>How Lead Overview relates to Scheduled Reports</summary>

Lead Overview is your **internal, at-a-glance** view for managing the whole portfolio.

To send those numbers **to your clients** automatically as a branded email, use Scheduled Lead Reports — they use the same lead definition and quota pacing.

1. Set your quotas in Lead Overview.
2. Create a scheduled report per client so they receive a weekly or monthly snapshot.

</details>

{% content-ref url="/pages/vl07skrvEHJqpF1xlTda" %}
[Scheduled Lead Reports](/guides/scheduled-reports)
{% endcontent-ref %}

{% content-ref url="/pages/FqrMOC4HeyPH7W0Eqtdm" %}
[Analytics](/guides/analytics)
{% endcontent-ref %}


# Scheduled Lead Reports

<figure><img src="/files/mOgdPjLHigAjoLcQsNbZ" alt=""><figcaption><p>A branded lead report email delivered automatically to a client</p></figcaption></figure>

Scheduled Lead Reports email your clients a beautiful, branded snapshot of the leads you delivered — automatically, on the schedule you choose. The report **is** the email (no attachment to open), and every recipient gets a one-click link to a live, no-login version.

{% hint style="info" %}
Scheduled Lead Reports are available on the **Agency plan**. On other plans, opening the page shows a preview of the feature with an option to upgrade.
{% endhint %}

You'll find them in the Agency area: open the workspace switcher at the top of the left sidebar, choose **Lead Overview** under **Agency**, then click **Scheduled Reports** in the sidebar.

***

### What's In a Report

Every report leads with the numbers clients care about and shows the value you add:

* **Headline** — valid leads (calls + web forms), with the change vs the previous period
* **Spam-filtered line** — e.g. "47 real leads · 15 spam filtered", so clients see what you kept out
* **Goal pacing** — a progress bar toward the quota you set, with an on-track / at-risk / behind status
* **Top sources** — where the leads came from (monthly digest only)
* **A call-to-action button** — takes the client to their full report
* **Your branding** — logo, colours, and sender address on the [White Label](/guides/white-label) plan

{% hint style="info" %}
Quotas and pacing come straight from [Lead Overview](/guides/lead-overview) — set a campaign's quota once and it drives both the dashboard and the report.
{% endhint %}

***

### Weekly Pulse vs Monthly Digest

Choose the style that fits the cadence:

| Email style        | What's included                                                                    | Best for                       |
| ------------------ | ---------------------------------------------------------------------------------- | ------------------------------ |
| **Weekly Pulse**   | Lean and at-a-glance: the headline number, key figures, spam line, and goal pacing | A quick weekly check-in        |
| **Monthly Digest** | The full report — everything in the pulse **plus** the top-source breakdown        | A monthly or quarterly wrap-up |

***

### Creating a Scheduled Report

{% stepper %}
{% step %}

#### Start a new report

Go to **Agency → Scheduled Reports** and click **New report**.

<figure><img src="/files/oaKyORoOevcHlPrvALjJ" alt="" width="563"><figcaption><p>The New Scheduled Report form.</p></figcaption></figure>
{% endstep %}

{% step %}

#### Basics

* Give the report a **name** (for your reference)
* Choose the **email style** — Weekly Pulse or Monthly Digest
* Leave it **Active** to send on schedule, or pause it anytime
  {% endstep %}

{% step %}

#### What to report

* **Scope** — report on **a single campaign** or **a whole client (workspace)**
* Select the campaign or client
* **Sections to include** — tick the blocks each client should see (spam line, goal pacing, top sources, revenue); untick anything a particular client shouldn't

<figure><img src="/files/6hOXEb9YlVTqRESVMd8t" alt="" width="563"><figcaption><p>Choosing the report scope and which sections to include</p></figcaption></figure>
{% endstep %}

{% step %}

#### When to send

* **Cadence** — Daily, Weekly, Monthly, or Quarterly
* **Day** — pick the day of the week (weekly) or day of the month (monthly / quarterly)
* **Send at** — the hour to send
* **Timezone** — defaults to the selected campaign's timezone so the report lands at the right local time

{% hint style="info" %}
Reports always cover the **just-completed** period — a Monday weekly report summarises last week, a monthly report on the 1st summarises last month.
{% endhint %}
{% endstep %}

{% step %}

#### Who receives it

* **Client email addresses** — type an address and press Enter to add it. Recipients **don't need a Ring Tonic account**.
* **Team members by role** — optionally tick Admins, Managers, Clients, or Members to include them too
* **Call-to-action link** — where the report button points:

| CTA option              | Where it links                                                            |
| ----------------------- | ------------------------------------------------------------------------- |
| **Auto**                | The campaign's share page if sharing is on, otherwise the no-login report |
| **Campaign share page** | The live [shared analytics](/guides/share-campaign) page                  |
| **Their login**         | The client's Ring Tonic dashboard                                         |
| **No button**           | Omits the button entirely                                                 |
| {% endstep %}           |                                                                           |

{% step %}

#### Save

Click **Create report**. It will now send automatically on the schedule you set.
{% endstep %}
{% endstepper %}

***

### Preview & Test Send

When editing a report you'll see a **live preview** of exactly what recipients will get. Click **Send test to me** to email the report to your own address first.

<figure><img src="/files/gqgk88qlN5mcHFL7t4lQ" alt=""><figcaption><p>Live email preview with the Send test to me button</p></figcaption></figure>

***

### The No-Login Report Link

Every report includes a link to a **live, read-only version** the client can open in a browser — no login, no account. It's a fixed snapshot of the period the email covered, so the link always matches the numbers the client received.

{% hint style="success" %}
This is a great fit for forwarding to stakeholders who don't have access to your dashboard.
{% endhint %}

***

### Your Branding

On the [White Label](/guides/white-label) plan, reports are sent with your agency's logo, colours, sender name, and (when configured) your own sending domain — so the whole experience looks like it came from you.

Without white-label configured, reports are sent from Ring Tonic's own authenticated address with your workspace name, which keeps deliverability high.

***

### Managing Reports

From the **Scheduled Reports** list you can:

| Action               | What It Does                                        |
| -------------------- | --------------------------------------------------- |
| **Edit**             | Change the schedule, recipients, scope, or sections |
| **Pause / Activate** | Stop or resume sending without deleting the report  |
| **Delete**           | Remove the report permanently                       |

The list also shows each report's cadence, recipient count, and status at a glance.

***

### Unsubscribing

Every email includes an **unsubscribe** link in the footer. If a recipient unsubscribes, they're removed from that report's future sends automatically — no action needed from you.

***

{% content-ref url="/pages/ckGB7dvFdyXkgLzaaMGq" %}
[Lead Overview](/guides/lead-overview)
{% endcontent-ref %}

{% content-ref url="/pages/gBorBBHg8RUiXvpYLWJX" %}
[Share Campaign](/guides/share-campaign)
{% endcontent-ref %}

{% content-ref url="/pages/jNFcObwrBOLsnnA8pt2p" %}
[White Label](/guides/white-label)
{% endcontent-ref %}


# Notifications

Notifications let you automatically alert your team when important events happen in your workspace — missed calls, voicemails, qualified leads, and more.

{% hint style="info" %}
Notifications are available on **all plans**. The **Email** channel requires the **Agency plan** with [custom SMTP configured](/guides/white-label#custom-email-delivery-optional). Future channels (Slack, Discord, Telegram) will be available on all plans.
{% endhint %}

***

### How Notifications Work

When an event occurs (e.g., a missed call), Ring Tonic checks your notification rules. If a rule matches the event, a notification is sent to all configured recipients with the details of what happened.

```
┌─────────────┐      ┌─────────────┐      ┌──────────────┐
│  Event      │──────│  Rule       │──────│  Notification │
│  happens    │      │  matches    │      │  sent to      │
│  (missed    │      │  event &    │      │  recipients   │
│   call)     │      │  is active  │      │               │
└─────────────┘      └─────────────┘      └──────────────┘
```

***

### Available Events

Notification rules can trigger on any of these events:

| Event                   | Description                                                                  |
| ----------------------- | ---------------------------------------------------------------------------- |
| Call Started            | Fires when a call starts ringing                                             |
| Call Completed          | Fires when a call ends                                                       |
| Call Missed             | Fires when a call is missed (busy, no-answer, failed)                        |
| Call Blocked            | Fires when a blocked number attempts to call                                 |
| Recording Available     | Fires when call recording is ready                                           |
| Transcription Available | Fires when call transcription is complete                                    |
| Voicemail Received      | Fires when a caller leaves a voicemail                                       |
| Voicemail Transcribed   | Fires when voicemail transcription is complete                               |
| Lead Qualified          | Fires when you qualify a lead in the dashboard                               |
| Contact Stage Changed   | Fires when a contact moves to a new pipeline stage                           |
| Conversion Recorded     | Fires when a conversion advances a contact's stage (postback, call, or form) |
| Form Submitted          | Fires when a visitor submits a captured form                                 |

{% hint style="info" %}
**Contact Stage Changed** and **Conversion Recorded** overlap: both fire when a contact moves to a new stage. If you create a rule for each, you'll get two emails per stage change — pick the one that fits, or use both intentionally.
{% endhint %}

***

### Creating a Notification Rule

{% stepper %}
{% step %}
**Navigate to Notifications**

Go to **Automations > Notifications** in the sidebar and click **Create Rule**.

<figure><img src="/files/4wWra9aSUbMEbThlTfiB" alt=""><figcaption><p>Notifications index page with Create Rule button</p></figcaption></figure>
{% endstep %}

{% step %}
**Configure Rule Settings**

* **Name** (optional): Give your rule a descriptive name. If left empty, a name is auto-generated from the selected events and channel.
* **Channel**: Select **Email** (more channels like Slack, Discord, and Telegram are coming soon).
* **Active**: Toggle the rule on or off.

<figure><img src="/files/eP3CAwehVJjxzTmkD2cR" alt=""><figcaption><p>Rule settings card with name, channel, and active toggle</p></figcaption></figure>
{% endstep %}

{% step %}
**Select Events**

Choose which events should trigger this notification. Events are grouped by category:

* **Calls** — Call Started, Call Completed, Call Missed, Call Blocked
* **Recordings & Transcriptions** — Recording Available, Transcription Available
* **Voicemail** — Voicemail Received, Voicemail Transcribed
* **Leads** — Lead Qualified
* **CRM Funnel** — Contact Stage Changed, Conversion Recorded, Form Submitted

Use the **Select All** / **Clear** buttons to quickly manage your selection. You can also click a group header to toggle all events in that group.

<figure><img src="/files/La8DOOsTY60Yi62FFKFy" alt=""><figcaption><p>Event selection with grouped checkboxes</p></figcaption></figure>
{% endstep %}

{% step %}
**Add Recipients**

Choose who should receive the notifications:

**Workspace Roles** — Select roles (Admin, Manager, Member, etc.) to notify all workspace members with those roles. Members can individually opt out from their notification preferences.

**External Email Addresses** — Type an email address and press **Enter** to add it. External recipients receive an unsubscribe link in every email.

{% hint style="warning" %}
At least one role or external email address is required.
{% endhint %}

<figure><img src="/files/yDVYDf0bsTXyZm3TskAA" alt=""><figcaption><p>Recipients card with workspace roles and external emails</p></figcaption></figure>
{% endstep %}

{% step %}
**Customize Template (Optional)**

Each event type has a default template. You can override the **Subject** and **Body** with your own content.

* Click **Variables** to insert dynamic placeholders like `{{caller_name}}`, `{{campaign_name}}`, or `{{call_link}}`
* Click **Preview** to see how your template looks with sample data
* Use **Markdown** formatting in the body (headings, bold, links, etc.)

Leave the fields empty to use the built-in defaults.

<figure><img src="/files/DnkYPLbZctzaACwsa03c" alt=""><figcaption><p>Template editor with variable picker and preview button</p></figcaption></figure>
{% endstep %}

{% step %}
**Save the Rule**

Click **Create Rule** to save. Your notification rule is now active and will trigger on the next matching event.
{% endstep %}
{% endstepper %}

***

### Template Variables

Use these variables in your notification template. They are replaced with actual values when the notification is sent.

#### Call Info

| Variable              | Description                     |
| --------------------- | ------------------------------- |
| `{{caller_name}}`     | Caller name                     |
| `{{caller_number}}`   | Caller phone number             |
| `{{called_number}}`   | Called/tracking number          |
| `{{call_status}}`     | Call status                     |
| `{{call_duration}}`   | Call duration (e.g., "2m 34s")  |
| `{{campaign_name}}`   | Campaign name                   |
| `{{tracking_number}}` | Tracking number name            |
| `{{call_date}}`       | Call date (e.g., "Mar 7, 2026") |
| `{{call_time}}`       | Call time (e.g., "2:30 PM")     |

#### Source Data

| Variable           | Description      |
| ------------------ | ---------------- |
| `{{source}}`       | UTM source       |
| `{{medium}}`       | UTM medium       |
| `{{landing_page}}` | Landing page URL |
| `{{referrer}}`     | Referrer URL     |
| `{{keyword}}`      | Search keyword   |
| `{{gclid}}`        | Google Click ID  |

#### Workspace

| Variable             | Description               |
| -------------------- | ------------------------- |
| `{{workspace_name}}` | Workspace name            |
| `{{agent_name}}`     | Agent name                |
| `{{lead_status}}`    | Lead qualification status |
| `{{contact_name}}`   | Contact name              |
| `{{voicemail_url}}`  | Voicemail recording URL   |
| `{{call_link}}`      | Link to call details      |

#### Pipeline

Available on the CRM Funnel events (Contact Stage Changed, Conversion Recorded, Form Submitted).

| Variable                | Description                                    |
| ----------------------- | ---------------------------------------------- |
| `{{from_stage}}`        | Previous pipeline stage                        |
| `{{to_stage}}`          | New pipeline stage                             |
| `{{conversion_source}}` | Conversion source (postback, call, form, etc.) |

***

### Managing Notification Rules

From the **Automations > Notifications** page, you can manage all your rules:

| Action     | Description                                                 |
| ---------- | ----------------------------------------------------------- |
| **Edit**   | Modify the rule's events, recipients, or template           |
| **Test**   | Send a test notification with sample data to all recipients |
| **Delete** | Permanently remove the rule                                 |

{% hint style="info" %}
Test notifications include a **\[TEST]** prefix in the subject line so recipients can distinguish them from real alerts.
{% endhint %}

***

### Testing a Notification Rule

Before relying on a rule for real events, send a test notification:

1. Go to **Automations > Notifications**
2. Click the **Send** icon on the rule you want to test
3. Confirm by clicking **Send Test**
4. All recipients will receive a test notification with realistic sample data

{% hint style="success" %}
**Pro Tip:** Use the test feature to verify that your custom template looks good and all recipients are receiving notifications before going live.
{% endhint %}

***

### Editing a Rule

Click a rule's name or the **Edit** icon to open the edit page. You can change any setting — events, recipients, template, or status.

#### Unsubscribed Emails

If any external recipients have unsubscribed from a rule, an **Unsubscribes** icon will appear in the rule's action column on the **Automations > Notifications** table. The **Unsubscribes** column also shows the total count.

Click the icon to open the Unsubscribed Emails page, where you can view all unsubscribed recipients and **re-subscribe** them if requested.

<figure><img src="/files/n3fjcDog2Z0vbMbpNPv9" alt=""><figcaption><p>Unsubscribed emails page with re-subscribe action</p></figcaption></figure>

***

### Notification Preferences (For Team Members)

Team members who are targeted by role can manage their own notification preferences:

1. Go to **Settings > Notifications**
2. Toggle the switch next to each notification rule to opt in or opt out

<figure><img src="/files/p6AtyCXYST2juQYGqYBt" alt=""><figcaption><p>Notification preferences page with opt-in/opt-out toggles</p></figcaption></figure>

{% hint style="info" %}
Only notification rules that target your role are shown. Opting out only affects your account — other members with the same role will still receive notifications.
{% endhint %}

***

### Unsubscribe (For External Recipients)

Every notification sent to an external recipient includes an **Unsubscribe** link. Clicking it immediately stops future notifications from that specific rule.

{% hint style="warning" %}
Unsubscribing is per-rule. If you're added to multiple notification rules, you'll need to unsubscribe from each one separately.
{% endhint %}

***

### White Label Branding

If you've configured SMTP settings in [White Label Settings](/guides/white-label#custom-email-delivery-optional), email notifications will be sent from your custom domain with your branding (logo and sender name). Otherwise, they use the default Ring Tonic sender.

{% hint style="info" %}
A banner on the Notifications index page will remind you to configure SMTP if it hasn't been set up yet.
{% endhint %}

***

### Common Questions

<details>

<summary>What plan do I need for notifications?</summary>

Notifications are available on **all plans**. However, the **Email** channel requires the **Agency plan** with [custom SMTP configured](/guides/white-label#custom-email-delivery-optional) in White Label settings.

</details>

<details>

<summary>Can I send notifications to people outside my workspace?</summary>

Yes. Add their email addresses in the **External Email Addresses** section of the rule. They will receive an unsubscribe link in every notification.

</details>

<details>

<summary>How quickly are notifications sent?</summary>

Notifications are dispatched immediately when the event occurs, typically within seconds.

</details>

<details>

<summary>Can a team member opt out of notifications?</summary>

Yes. Members can go to **Settings > Notifications** and toggle off any notification rule that targets their role.

</details>

<details>

<summary>Can I have multiple rules for the same event?</summary>

Yes. You can create multiple rules for the same event type with different recipients, templates, or configurations.

</details>

<details>

<summary>What happens if I leave the template fields empty?</summary>

Ring Tonic uses built-in default templates for each event type. These include caller details, campaign info, and a link to the call details page.

</details>

<details>

<summary>Can I use Markdown in the template body?</summary>

Yes. The template body supports Markdown formatting — headings, bold, italic, links, and lists are all supported.

</details>


# Webhooks

<figure><img src="/files/jZEjTriAkaZeOofb09ry" alt=""><figcaption></figcaption></figure>

Webhooks let you receive real-time notifications when events happen in Ring Tonic. Instead of polling our API, we push data to your server the moment a call comes in, a recording is ready, or a lead is qualified.

{% hint style="info" %}
Webhooks are available on the **Agency plan** only. Perfect for CRM integrations like GoHighLevel, HubSpot, and Zapier.
{% endhint %}

***

### Available Events

| Event                     | Description                                           |
| ------------------------- | ----------------------------------------------------- |
| `call.started`            | Fires when a call starts ringing                      |
| `call.completed`          | Fires when a call ends (includes duration and status) |
| `call.missed`             | Fires when a call is missed (busy, no-answer, failed) |
| `recording.available`     | Fires when call recording is ready                    |
| `transcription.available` | Fires when call transcription is complete             |
| `lead.qualified`          | Fires when you qualify a lead in the dashboard        |
| `call.blocked`            | Fires when a blocked number attempts to call          |
| `voicemail.received`      | Fires when a caller leaves a voicemail                |
| `voicemail.transcribed`   | Fires when voicemail transcription is complete        |

{% hint style="info" %}
**Forms vs. webhooks:** Webhooks fire for **call events only**. The website tracker script also injects attribution data (UTMs, click IDs, `ga_client_id`, `ga_session_id`) into your website's forms as hidden fields — but that data is sent to *your* form handler (HubSpot, Squarespace, your CRM, etc.), not back to Ring Tonic. There is no `form.submitted` webhook.
{% endhint %}

***

### Attribution Fields in Call Payloads

Every call payload includes a nested `visitor_session` object with the full attribution context captured by the website tracker script when the caller's session was created.

{% hint style="warning" %}
**Where to find GA fields:** `ga_client_id` and `ga_session_id` live inside `data.visitor_session`, **not** at the top level of `data`. Only `utm_source` and `utm_medium` are promoted to the top level for convenience.
{% endhint %}

| Field                                   | Description                                    |
| --------------------------------------- | ---------------------------------------------- |
| `data.visitor_session.gclid`            | Google Ads click ID                            |
| `data.visitor_session.gbraid`           | Google iOS app click ID                        |
| `data.visitor_session.wbraid`           | Google privacy-restricted web click ID         |
| `data.visitor_session.fbclid`           | Facebook/Instagram click ID                    |
| `data.visitor_session.msclkid`          | Microsoft/Bing click ID                        |
| `data.visitor_session.ttclid`           | TikTok click ID                                |
| `data.visitor_session.li_fat_id`        | LinkedIn click ID                              |
| `data.visitor_session.ga_client_id`     | Google Analytics Client ID (from `_ga` cookie) |
| `data.visitor_session.ga_session_id`    | GA4 Session ID (from `_ga_XXXXXX` cookie)      |
| `data.visitor_session.utm_campaign`     | Campaign name from URL                         |
| `data.visitor_session.utm_term`         | Search term from URL                           |
| `data.visitor_session.utm_content`      | Ad variant/content from URL                    |
| `data.visitor_session.referrer_url`     | The referring page that brought the visitor    |
| `data.visitor_session.landing_page_url` | The first page the visitor landed on           |

If the caller could not be matched to a website visitor session (e.g., they dialed the number directly without visiting your site), `data.visitor_session` will be `null`.

***

### Timestamps & Time Zones

Every timestamp in a webhook payload is in **UTC** (Coordinated Universal Time), formatted as an [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) string ending in `+00:00` — for example, `2026-06-09T07:25:37+00:00`. The trailing `+00:00` is the time-zone offset, and it confirms the value is UTC.

{% hint style="warning" %}
**Webhook times are UTC; your dashboard shows local time.** Your call logs and analytics pages convert times into your campaign or workspace time zone so they're easy to read, but webhooks always send UTC. A time that looks an hour (or more) different from your dashboard is the **same moment shown in two time zones** — not a mismatch.
{% endhint %}

For example, a call that starts at `07:25 UTC` arrives in the webhook as `2026-06-09T07:25:37+00:00`. If that campaign uses UK time, the call's detail page shows it as **8:25 AM**, because the UK runs one hour ahead of UTC during British Summer Time (UTC+1). Both values are correct — they describe the same instant.

#### Timestamp fields

| Field                           | Where it appears                                                                   |
| ------------------------------- | ---------------------------------------------------------------------------------- |
| `created_at`                    | Top level — when the webhook event was generated                                   |
| `data.started_at`               | All call events — when the call started                                            |
| `data.qualified_at`             | `lead.qualified` — when the lead was qualified                                     |
| `data.summarized_at`            | `transcription.available` and `lead.qualified` — when the AI summary was generated |
| `data.voicemail.transcribed_at` | `voicemail.transcribed` — when the voicemail was transcribed                       |

{% hint style="success" %}
**Working with the times:** Because each timestamp carries the `+00:00` offset, most date libraries parse it correctly out of the box. Convert it to your preferred time zone for display, or store it as UTC and convert on read.
{% endhint %}

***

### Creating a Webhook Endpoint

<figure><img src="/files/iqpaH3iOtqv2BSUqdgsx" alt=""><figcaption><p>Create a webhook endpoint form</p></figcaption></figure>

1. Go to **Automations > Webhooks** in the sidebar
2. Click **Add Endpoint**
3. Fill in the endpoint details:
   * **Name:** A friendly name (e.g., "GoHighLevel Integration")
   * **Endpoint URL:** Your HTTPS URL that will receive the webhook
   * **Events:** Select which events to subscribe to
4. Click **Create Endpoint**

{% hint style="warning" %}
**HTTPS Required:** Your endpoint URL must use HTTPS. HTTP URLs are not accepted for security reasons.
{% endhint %}

***

### Signing Secret

Each webhook endpoint has a unique signing secret (e.g., `whsec_abc123...`). Use this to verify that requests are genuinely from Ring Tonic.

We sign every webhook request using HMAC-SHA256. The signature is included in the `Signature` header.

#### Verifying Signatures (PHP Example)

```php
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_SIGNATURE'];
$secret = 'whsec_your_secret_here';

$expectedSignature = hash_hmac('sha256', $payload, $secret);

if (!hash_equals($expectedSignature, $signature)) {
    http_response_code(401);
    exit('Invalid signature');
}

// Process the webhook...
```

{% hint style="success" %}
**Pro Tip:** You can regenerate your signing secret anytime from the Edit page if you suspect it's been compromised.
{% endhint %}

***

### Testing Your Endpoint

1. Go to your webhook endpoint's detail page
2. Click **Send Test**
3. Select an event type from the dropdown (only events you're subscribed to are shown)
4. Click **Send Test** to dispatch a sample webhook with realistic data
5. Check your server logs for the test payload
6. Verify the delivery status in the **Recent Deliveries** table

{% hint style="info" %}
**Realistic Sample Data:** Test webhooks include sample data that matches the real payload structure for each event type. This helps you test your integration logic before real calls come in.
{% endhint %}

<figure><img src="/files/Ou26DEDxpeAzMgnRD7eQ" alt=""><figcaption><p>Test a webhook endpoint</p></figcaption></figure>

***

### Payload Examples

All webhooks follow the same structure with event-specific data in the `data` object.

<details>

<summary>call.blocked</summary>

Fires when a call from a blocked number is rejected. This event has a different payload structure than other call events since the call is never connected.

```json
{
  "event": "call.blocked",
  "created_at": "2026-01-15T14:30:00+00:00",
  "workspace": {
    "id": 1,
    "name": "My Workspace"
  },
  "data": {
    "blocked_number": "+15551234567",
    "called_number": "+15559876543",
    "caller_name": "John Spam",
    "caller_city": "San Francisco",
    "caller_state": "CA",
    "block_list_type": "workspace",
    "block_reason": "spam",
    "tracking_number": {
      "id": 1,
      "phone_number": "+15559876543",
      "friendly_name": "Sales Line"
    },
    "campaign": {
      "id": 1,
      "name": "Google Ads Campaign"
    }
  }
}
```

</details>

<details>

<summary>call.completed (base payload — shared by all call.* events)</summary>

This is the full base payload shared by `call.started`, `call.completed`, `call.missed`, `recording.available`, `transcription.available`, `lead.qualified`, `voicemail.received`, and `voicemail.transcribed`. Event-specific fields are appended on top (see the sections below).

```json
{
  "event": "call.completed",
  "created_at": "2026-01-15T14:30:00+00:00",
  "workspace": {
    "id": 1,
    "name": "My Workspace"
  },
  "data": {
    "call_log_id": 12345,
    "twilio_call_sid": "CA1234567890abcdef",
    "from_number": "+14155551234",
    "caller_name": "John Smith",
    "tracking_number": "+18005551234",
    "tracking_number_name": "Google Ads - Main",
    "campaign_id": 42,
    "campaign_name": "Google Ads Campaign",
    "status": "completed",
    "duration": 145,
    "caller_location": {
      "city": "San Francisco",
      "state": "CA",
      "country": "US",
      "zip": "94102"
    },
    "is_first_time_caller": true,
    "utm_source": "google",
    "utm_medium": "cpc",
    "visitor_session": {
      "gclid": "CjwKCAiA-sample-gclid-123",
      "gbraid": null,
      "wbraid": null,
      "fbclid": null,
      "msclkid": null,
      "ttclid": null,
      "li_fat_id": null,
      "ga_client_id": "1234567890.1234567890",
      "ga_session_id": "1234567890",
      "utm_campaign": "winter-sale-2026",
      "utm_term": "plumber near me",
      "utm_content": "ad-variant-a",
      "referrer_url": "https://www.google.com/search?q=plumber+near+me",
      "landing_page_url": "https://example.com/services/plumbing"
    },
    "started_at": "2026-01-15T14:27:35+00:00"
  }
}
```

</details>

<details>

<summary>recording.available</summary>

Includes all base fields plus:

```json
{
  "event": "recording.available",
  "data": {
    "recording_url": "https://api.twilio.com/recordings/RE123...",
    // ... all base call data
  }
}
```

</details>

<details>

<summary>transcription.available</summary>

Includes all base fields plus:

```json
{
  "event": "transcription.available",
  "data": {
    "transcription": "Hi, I'm calling about your services...",
    "transcription_confidence": 0.95,
    "summary": "Customer called inquiring about services and pricing. Requested a callback.",
    "summarized_at": "2026-01-15T14:32:00+00:00"
    // ... all base call data
  }
}
```

</details>

<details>

<summary>lead.qualified</summary>

Includes all base fields plus:

```json
{
  "event": "lead.qualified",
  "data": {
    "lead_status": "qualified",
    "qualification_reason": "Customer interested in premium package",
    "qualification_confidence": 0.89,
    "deal_value": 2500.00,
    "qualified_at": "2026-01-15T15:00:00+00:00",
    "tags": ["High Intent", "New Customer", "Service Inquiry"],
    "summary": "Customer called inquiring about services and pricing. Requested a callback.",
    "summarized_at": "2026-01-15T14:32:00+00:00"
    // ... all base call data
  }
}
```

</details>

<details>

<summary>voicemail.received</summary>

Fires when a caller leaves a voicemail. Includes all base fields plus:

```json
{
  "event": "voicemail.received",
  "data": {
    "voicemail": {
      "recording_url": "https://api.twilio.com/recordings/RE456...",
      "duration": 15
    },
    // ... all base call data
  }
}
```

</details>

<details>

<summary>voicemail.transcribed</summary>

Fires when a voicemail transcription is complete. Includes all base fields plus:

```json
{
  "event": "voicemail.transcribed",
  "data": {
    "voicemail": {
      "recording_url": "https://api.twilio.com/recordings/RE456...",
      "duration": 15,
      "transcription": "Hi, this is John. I missed your call and wanted to learn more about your services. Please call me back when you get a chance. Thanks!",
      "transcribed_at": "2025-01-15T14:32:00+00:00"
    },
    // ... all base call data
  }
}
```

</details>

***

### Delivery & Retries

Ring Tonic automatically retries failed deliveries with exponential backoff. You can monitor delivery status from the endpoint detail page:

* **Success:** Your server returned 2xx
* **Retrying:** Delivery failed, retrying automatically
* **Failed:** All retry attempts exhausted

{% hint style="danger" %}
**Circuit Breaker:** After 10 consecutive failures, the endpoint is automatically disabled to prevent further issues. Re-enable it from the detail page after fixing the problem.
{% endhint %}

#### Manual Retry

For failed deliveries, click the **Retry** button in the delivery detail modal to manually queue a retry.

<figure><img src="/files/0I47QUwGjKIKgMH90jrW" alt=""><figcaption><p>Manual retry a webhook delivery</p></figcaption></figure>

***

### Integration Example: GoHighLevel

This example shows how to connect Ring Tonic with GoHighLevel (GHL) to automatically create contacts and trigger automations when calls come in.

#### How It Works

```
┌─────────────┐      ┌─────────────┐      ┌─────────────┐
│  Caller     │──────│  Ring Tonic │──────│  GHL        │
│  dials      │      │  tracks &   │      │  creates    │
│  tracking # │      │  attributes │      │  contact &  │
│             │      │  the call   │      │  triggers   │
│             │      │             │      │  automation │
└─────────────┘      └─────────────┘      └─────────────┘
```

1. **Ring Tonic handles inbound calls** - Your tracking number lives in Ring Tonic. We record the call and attribute the source (Google Ads, SEO, etc.) which GHL can't do natively.
2. **Ring Tonic pushes data to GHL** - When a call ends, we fire a webhook to GHL with full call details and attribution data.
3. **GHL automations fire** - Your GHL workflow creates the contact, adds tags (e.g., "PPC Lead"), and triggers SMS/email follow-ups.

{% stepper %}
{% step %}
**Create the GHL Workflow**

* In GoHighLevel, go to **Automation** → **Workflows**
* Click **Create Workflow** → **Start from Scratch**
* Click **Add New Trigger** → Select **Inbound Webhook**
* Copy the generated **Webhook URL** (you'll need this for Ring Tonic)
* Click **Save Trigger**

{% hint style="success" %}
For more details, see [GHL's Inbound Webhook documentation](https://help.gohighlevel.com/support/solutions/articles/155000003147-workflow-trigger-inbound-webhook).
{% endhint %}
{% endstep %}

{% step %}
**Create the Ring Tonic Endpoint**

* In Ring Tonic, go to **Automations > Webhooks** → **Add Endpoint**
* Enter a name: `GoHighLevel Integration`
* Paste the GHL Webhook URL from Step 1
* Select events: `call.completed`, `call.missed` (and optionally `recording.available`)
* Click **Create Endpoint**
  {% endstep %}

{% step %}
**Test the Connection**

* In Ring Tonic, click **Send Test** on your new endpoint
* Back in GHL, your workflow should show the test data received
* You can now map the incoming fields to GHL contact fields
  {% endstep %}

{% step %}
**Build the GHL Workflow**

After the Inbound Webhook trigger, add these actions:

* **Create/Update Contact**
  * Phone: `{{data.from_number}}`
  * First Name: (optional, or use a placeholder)
  * Tags: Add tags based on campaign, e.g., `{{data.campaign_name}}`
* **Add to Campaign/Sequence** (optional)
  * Enroll the contact in a follow-up sequence
* **Send SMS** (optional)
  * "Thanks for calling! We'll be in touch shortly."
    {% endstep %}
    {% endstepper %}

#### Field Mapping Reference

| Ring Tonic Field                        | GHL Use Case                                                     |
| --------------------------------------- | ---------------------------------------------------------------- |
| `data.from_number`                      | Contact Phone                                                    |
| `data.caller_name`                      | Contact Name                                                     |
| `data.campaign_name`                    | Contact Tag or Custom Field                                      |
| `data.utm_source`                       | Lead Source                                                      |
| `data.utm_medium`                       | Custom Field (e.g., "ppc", "organic")                            |
| `data.caller_location.city`             | Contact City                                                     |
| `data.caller_location.state`            | Contact State                                                    |
| `data.is_first_time_caller`             | Tag: "New Caller" vs "Repeat Caller"                             |
| `data.duration`                         | Custom Field (call length in seconds)                            |
| `data.recording_url`                    | Custom Field (link to recording)                                 |
| `data.visitor_session.gclid`            | Custom Field (Google Ads click ID for offline conversion upload) |
| `data.visitor_session.fbclid`           | Custom Field (Facebook click ID for CAPI conversions)            |
| `data.visitor_session.ga_client_id`     | Custom Field (stitch the call to a GA4 session)                  |
| `data.visitor_session.utm_campaign`     | Custom Field (campaign name)                                     |
| `data.visitor_session.landing_page_url` | Custom Field (entry page)                                        |

{% hint style="success" %}
**Pro Tip:** Use `is_first_time_caller` to branch your workflow. Send a welcome message to new callers and a "thanks for calling again" to repeat callers.
{% endhint %}

***

### Common Questions

<details>

<summary>Why do webhook times differ from the times in my dashboard?</summary>

Webhook timestamps are always in **UTC** — you'll see `+00:00` at the end of each time. Your dashboard, call logs, and analytics convert times into your campaign or workspace time zone so they're easier to read.

So a call delivered as `07:25 UTC` in the webhook can appear as `08:25` on the call detail page if the campaign is on a time zone that's an hour ahead — for example, UK time during British Summer Time.

It's the same moment shown two ways, so nothing is wrong. See the **Timestamps & Time Zones** section above for the full list of timestamp fields and how to convert them.

</details>

<details>

<summary>What HTTP method is used?</summary>

All webhooks are sent as `POST` requests with a JSON body. The `Content-Type` header is set to `application/json`.

</details>

<details>

<summary>How many times will you retry a failed delivery?</summary>

Each delivery is retried up to 3 times with exponential backoff. After all retries are exhausted, that delivery is marked as failed. If 10 consecutive deliveries fail (each after exhausting retries), the endpoint is automatically disabled via circuit breaker.

</details>

<details>

<summary>How quickly are webhooks sent?</summary>

Webhooks are dispatched immediately when the event occurs, typically within seconds.

</details>

<details>

<summary>What response should my server return?</summary>

Return any 2xx status code (200, 201, 204, etc.) to acknowledge receipt. We ignore the response body.

</details>

<details>

<summary>How long do you store delivery logs?</summary>

Delivery logs are retained for 30 days.

</details>

<details>

<summary>Can I have multiple endpoints for the same event?</summary>

Yes, you can create multiple endpoints subscribing to the same events. Each will receive the webhook independently.

</details>


# API

API Keys let you access Ring Tonic data programmatically. Use them to build custom integrations, sync call data with your CRM, or power dashboards.

{% hint style="info" %}
API Keys are available on the **Agency plan** only.
{% endhint %}

***

### Creating an API Key

1. Go to **Settings** → **API Keys**
2. Enter a descriptive name (e.g., "SEO Utils Integration")
3. Choose the key's scopes — pick the **Read-only** preset, **Full access**, or toggle individual scopes yourself
4. *(Optional)* Set an **Expiration**: Never, 30, 90, or 365 days
5. Click **Create API Key**
6. Copy your key immediately — you won't see it again

<figure><img src="/files/gnPEZByluC4wqK6IMyqw" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
**Store your key securely.** Treat it like a password. Anyone with your key can access your data.
{% endhint %}

{% hint style="info" %}
**Only grant the scopes an integration actually needs.** A dashboard that displays call data needs read scopes alone — giving it write scopes means a mistake in that integration can change or delete your records.
{% endhint %}

***

### Using Your API Key

Include the key in the `Authorization` header of all requests:

```bash
curl "https://ringtonic.app/api/v1/campaigns" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
```

***

### Managing Keys

| Action        | How                            |
| ------------- | ------------------------------ |
| View keys     | **Settings** → **API Keys**    |
| See last used | Check the "Last Used" column   |
| Revoke key    | Click the trash icon → Confirm |

{% hint style="danger" %}
**Revoking is permanent.** Any integrations using that key will immediately stop working.
{% endhint %}

***

### Available Endpoints

Full interactive documentation — every endpoint with request and response schemas, plus a built-in "Try It" console — lives here:

{% embed url="<https://ringtonic.app/docs/api>" %}

You can **read** campaigns, call logs (with recordings and transcriptions), contacts, conversions, tracking numbers, call flows, tags, webhook endpoints, form submissions, blocked numbers, products & services, and appointments.

***

### Creating and Changing Data

The API can now build and maintain your account, not just read from it. Onboarding a new client no longer has to be a session in the dashboard — it can be a script.

| What you can manage | Create | Update | Delete |
| ------------------- | ------ | ------ | ------ |
| Campaigns           | ✅      | ✅      | ✅      |
| Call flows          | ✅      | ✅      | ✅      |
| Tracking numbers    | ✅      | ✅      | ✅      |
| Tags                | ✅      | ✅      | ✅      |
| Products & services | ✅      | ✅      | ✅      |
| Webhook endpoints   | ✅      | ✅      | ✅      |
| Blocked numbers     | ✅      | —      | ✅      |
| Call logs           | —      | ✅      | ✅      |
| Contacts            | —      | —      | ✅      |

A few actions go beyond simple create and update:

* **Attach or detach a call flow** on a campaign, to change how its calls are answered
* **Duplicate a call flow**, to reuse a working setup for another client
* **Rotate a webhook signing secret**, or **send a test event** to confirm your endpoint is reachable

{% hint style="warning" %}
**Deleting a call flow changes how calls are answered.** Every campaign using that flow is detached and falls back to its simple forwarding settings. Check which campaigns use a flow before removing it.
{% endhint %}

{% hint style="success" %}
**Call flows and phone numbers can now be managed end to end.** You can design a flow, publish it, and buy the number that answers it without opening the dashboard. Both are covered in their own sections below.
{% endhint %}

***

### Building Call Flows

A call flow is a set of steps — greet the caller, check business hours, ring a team, take a message — connected together. The API works with the same flows the [Call Flow Builder](/guides/call-flow-builder) produces, so you can design one by hand and then reproduce it for every client with a script.

Each flow has two copies: the **draft** you are editing, and the **published** version that is answering calls. Writing to a flow only ever changes the draft.

{% stepper %}
{% step %}

#### Create the flow

Create a flow with its starting steps, or with none at all to begin from a blank flow.
{% endstep %}

{% step %}

#### Edit the draft

Send the steps and the connections between them. Callers are unaffected — the published version keeps answering.
{% endstep %}

{% step %}

#### Publish

Publishing takes a snapshot of the draft and puts it into service for every campaign using that flow.
{% endstep %}

{% step %}

#### Roll back if needed

Rolling back restores an earlier version **into the draft**. Publish again to actually return that version to service.
{% endstep %}
{% endstepper %}

{% hint style="warning" %}
**A flow is written whole, not step by step.** There is no way to add or remove a single step: whatever you send becomes the draft, so a step you leave out is removed along with its connections.

Always read the flow first, change the parts you want, and send the whole thing back. Building the request from scratch for a small edit will delete the rest of the flow.
{% endhint %}

{% hint style="info" %}
**Drafts are checked as though you were publishing them.** The builder lets you save half-finished work because you can see it on the canvas; a script cannot. So an incomplete flow is refused straight away, naming the step and the setting at fault, rather than being accepted and failing later when you publish.
{% endhint %}

<details>

<summary>Working safely when more than one thing edits a flow</summary>

* Read, change, and write back as one operation, then publish
* Two publishes of the same flow at the same time will not both apply — one succeeds and the other is asked to try again
* A flow that contains AI-generated voice audio publishes in the background, so check its version list to confirm the new version went live
* If you send back a webhook step's hidden signing secret exactly as you received it, the stored secret is kept — so a read-and-write round trip never destroys your credentials

</details>

***

### Buying and Releasing Numbers

Onboarding a client can now include getting them a number. The API can search what is available, buy one, point it at a campaign, and give it back when the client leaves.

{% stepper %}
{% step %}

#### Search what is available

Search by country, and narrow it down by area code, the digits the number contains, whether it is local, toll-free or mobile, and whether it needs to handle calls, texts or both. Prices come back per number type, so a toll-free number is quoted at its own rate.
{% endstep %}

{% step %}

#### Buy a number

Buy a specific number from those results, or give the criteria and let Ring Tonic pick the first match. You can assign it to a campaign and give it a label in the same request.
{% endstep %}

{% step %}

#### Release it when you are done

Releasing gives the number back to the carrier and stops the monthly charge for it.
{% endstep %}
{% endstepper %}

{% hint style="danger" %}
**Releasing a number is permanent.** The number returns to the carrier's pool, and anyone can buy it next. Calls to it stop reaching you immediately, and existing marketing that still shows the number will ring a stranger. If you only want to stop using a number on a campaign, unassign it instead — it stays in your inventory.
{% endhint %}

{% hint style="info" %}
**Numbers you already own in Twilio are imported from the dashboard.** Go to **Phone Numbers** → **Import from Twilio** to bring existing numbers into a workspace; the API buys new ones rather than adopting numbers already on your account.
{% endhint %}

<details>

<summary>What happens if a purchase fails half way through</summary>

Buying a number happens at the carrier before Ring Tonic can record it, so the two steps cannot be completed as one.

1. If the carrier sells the number but Ring Tonic cannot record it, the purchase is undone — the number is given straight back rather than left on your bill with nothing in your account to show for it.
2. If a purchase takes you past your daily cap, that number is released again and the response tells you the cap was reached.
3. If a request times out and you are unsure whether it went through, retry it with the same **Idempotency-Key** and you will get the original answer rather than a second number.

</details>

***

### Safe Retries

If a request times out, you rarely know whether it succeeded. Send it again and you risk creating the same campaign twice.

To avoid that, include an **Idempotency-Key** header on any request that creates something. Choose a unique value per action — a UUID works well:

```bash
curl -X POST "https://ringtonic.app/api/v1/campaigns" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: 7f3c1e94-2b6a-4d5e-9a10-c8f2b7d41e63" \
  -H "Content-Type: application/json" \
  -d '{"name": "Spring Promo", "tracking_type": "static", "forward_to": "+14155550123"}'
```

Retry with the same key and you get the original response back instead of a second campaign. Use a new key for each genuinely new action.

***

### Limiting What the API Can Spend

Workspace owners can cap how many phone numbers the API is allowed to buy per day, so an integration with a bug can't run up a bill overnight.

{% stepper %}
{% step %}

#### Open your workspace settings

Go to **Settings** → **Workspace**. The **API Access** section appears near the bottom of the **Basic** tab.
{% endstep %}

{% step %}

#### Set the daily cap

Enter a number between 0 and 100. Setting it to **0** prevents the API from buying numbers at all.

<figure><img src="/files/gA4GaP3xpWvoUrh4bhCo" alt=""><figcaption><p>The API Access section in workspace settings, showing the daily purchase cap field</p></figcaption></figure>
{% endstep %}
{% endstepper %}

{% hint style="info" %}
Only the **workspace owner** can change this — team members with admin access cannot.

Numbers that were bought and later released still count toward the day's total, because they were paid for. The count resets at midnight in your workspace's timezone.
{% endhint %}

***

### Common Questions

<details>

<summary>How many API keys can I create?</summary>

Unlimited. Create separate keys for each integration so you can revoke them independently.

</details>

<details>

<summary>Do API keys expire?</summary>

By default, no — keys stay active until you revoke them. When creating a key you can optionally set it to expire after 30, 90, or 365 days, and it will stop working automatically once that period passes.

</details>

<details>

<summary>What happens if my key is compromised?</summary>

Revoke it immediately from **Settings** → **API Keys** and create a new one.

</details>

<details>

<summary>Can I stop an integration from deleting things?</summary>

Yes. Scopes are granted per key, and read and write are separate.

* Give a reporting dashboard only the **read** scopes it needs
* Give a provisioning script the **write** scopes for the resources it manages, and nothing else
* Create a separate key per integration, so you can revoke one without breaking the others

</details>

<details>

<summary>Does deleting through the API also delete the call recordings?</summary>

Deleting a call log removes the call and its recording and transcription, exactly as deleting it in the dashboard does. This cannot be undone, so confirm you have exported anything you need first.

</details>

<details>

<summary>Why did my request come back with an error I did not expect?</summary>

Errors include a short machine-readable `type` and a human-readable explanation, so you can tell an invalid value apart from a missing permission or a record that belongs to another workspace.

Common causes:

1. **The key is missing a scope.** Check the key's scopes in **Settings** → **API Keys**.
2. **The record belongs to another workspace.** A key only ever sees the workspace it was created in.
3. **A value failed validation.** The response names the field and what was wrong with it.

</details>

<details>

<summary>I edited one step and the rest of my flow disappeared — why?</summary>

A flow is written whole. The request replaces the draft with exactly what you send, so any step missing from it is removed.

To change one step:

1. Read the flow first
2. Change that step in what you read
3. Send the whole thing back

Building the request from scratch, listing only the step you wanted to change, deletes everything else. If this has already happened, roll the flow back to the last published version and publish again.

</details>

<details>

<summary>Can I cap what the API is allowed to spend?</summary>

Yes — workspace owners set a daily limit on how many numbers the API may buy. See [Limiting What the API Can Spend](#limiting-what-the-api-can-spend) above.

* The default is 10 numbers per day
* Setting it to **0** stops the API buying numbers entirely
* Numbers bought and then released still count toward the day, because they were paid for

</details>

<details>

<summary>Can two integrations safely write at the same time?</summary>

Yes. Requests are handled independently and your workspace is never left half-updated by a failed call.

Two behaviours worth knowing:

* Actions that create something accept an **Idempotency-Key**, so retries after a timeout do not duplicate records
* Where two requests genuinely conflict — publishing the same call flow twice at once, for example — one succeeds and the other is told to try again, rather than both partially applying

</details>


# CRM Postback API

The CRM API lets external systems — your existing CRM, Zapier, Calendly, n8n, or custom integrations — push conversion events back into Ring Tonic. Every event you push appears on the matching [Contact](/guides/contacts)'s timeline, advances the funnel, and (when configured) uploads to Google Ads as an Enhanced Conversion.

{% hint style="info" %}
The CRM Postback API is **Agency plan** only. The general API key feature ([API](/guides/api)) is also Agency-gated.
{% endhint %}

***

### Who this is for

{% hint style="info" %}
**For developers** — jump to [Quickstart](#quickstart) and [Endpoints](#endpoints): request/response bodies, status codes, idempotency, rate limits, and ready-to-paste recipes for Calendly, HubSpot, and Zapier.

**For everyone else** — this connects an *outside* system (your CRM, scheduler, or automation tool) to Ring Tonic, so that when a lead books a call or a deal closes elsewhere, it lands on the contact's timeline and pushes the conversion to Google Ads automatically. It needs a developer — or a tool like Zapier — to set up once. If you just want to capture leads from your own website, the no-code [Form Submissions](/guides/form-submissions) is usually the better fit (see below).
{% endhint %}

### Do I need the API?

Reach for the Postback API only when the event happens in a system Ring Tonic can't already see.

| You want to…                                                                                     | Use                                          | Code needed?                |
| ------------------------------------------------------------------------------------------------ | -------------------------------------------- | --------------------------- |
| Capture leads from your own or a client's website form                                           | [Form Submissions](/guides/form-submissions) | No (tracking script)        |
| Carry attribution into the client's existing CRM                                                 | Form Attribution                             | No (tracking script)        |
| Push events from an *external* CRM, scheduler, or automation (HubSpot, Calendly, Zapier, custom) | **CRM Postback API** (this page)             | Yes (a developer or Zapier) |

### What you need before you start

1. **An Agency-plan workspace** — the CRM Postback API is Agency-only.
2. **An API key**, created at **Settings → API Keys → Create API Key** (copy it once — it's shown only once).
3. **The right abilities on that key:**
   * `workspace:<id>` — **exactly one**, the workspace this key may act on (required)
   * `crm:write` — to record conversions and create or update contacts
   * `crm:read` — to look up contacts or read a contact's event log
   * `crm:force` — only if you'll ever move a contact *backward* in the funnel
4. **The base URL:** `https://ringtonic.app/api/v1`

The full ability reference is in [Authentication](#authentication) below.

***

### Quickstart

```bash
curl -X POST https://ringtonic.app/api/v1/conversions \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "phone": "+15551234567",
    "stage": "appointment_booked",
    "value_cents": 500000,
    "currency_code": "USD",
    "occurred_at": "2026-05-19T15:00:00Z"
  }'
```

That single call:

1. Finds the existing Contact with phone `+15551234567` in your workspace
2. Records a conversion event with stage `appointment_booked`
3. Advances the Contact's funnel stage (if forward)
4. Stores `deal_value` of `$5,000.00`
5. Fires `conversion.recorded` and `contact.stage_changed` webhooks
6. Queues a Google Ads Enhanced Conversion upload (if a mapping is configured)

***

### Authentication

All endpoints require a Sanctum personal access token. Generate one at **Settings** → **API Keys** → **Create API Key**.

<figure><img src="/files/rbbLsZ1lKe4uwqrqrheC" alt=""><figcaption><p>Creating a CRM API key under Settings → API Keys, with the workspace and crm abilities</p></figcaption></figure>

**Required header:**

```
Authorization: Bearer <your_api_key>
```

**Required token abilities** when creating the key:

| Ability          | Grants                                                                                   |
| ---------------- | ---------------------------------------------------------------------------------------- |
| `workspace:<id>` | Limits the token to one specific workspace — **exactly one workspace scope is required** |
| `crm:read`       | `GET /api/v1/contacts/match`, `GET /api/v1/contacts/{id}/events`                         |
| `crm:write`      | `POST /api/v1/contacts`, `PATCH /api/v1/contacts/{id}`, `POST /api/v1/conversions`       |
| `crm:force`      | Required when sending `force_stage: true` to move a contact backwards                    |

{% hint style="warning" %}
A CRM token must be scoped to **exactly one** workspace. Tokens without a `workspace:<id>` ability — or with multiple workspace abilities — receive 401 `token_missing_workspace_scope` / `token_multiple_workspace_scopes`. Mint a separate token per workspace.

Rule of thumb: **workspace-scope problems return `401`; a valid token that's simply missing a `crm:*` ability returns `403`.**
{% endhint %}

***

### Idempotency

Every state-changing endpoint accepts an optional `Idempotency-Key` header. Retries with the same key + same body return the original response and skip side effects.

```
Idempotency-Key: 7f4e9b2a-1c8d-4d6f-9e3b-2a1f8c4d7e9b
```

Recommended format: UUID v4 or any unique value your system can re-generate on retry.

* **Same key, same body** within 24h → cached response (200, not 201, on replay)
* **Same key, different body** within 24h → 409 `idempotency_key_reuse`
* **Same key on a previously-failed request** → cached failure response (mint a new key to retry against the same input)

Idempotency works equally for `POST /contacts` and `POST /conversions`. The window is 24h.

***

### Identity Matching

Several endpoints accept `phone`, `email`, and `external_id` as ways to identify a contact. Ring Tonic's matcher uses **priority order with conflict detection**:

```
1. external_id  (your system's contact ID — most reliable when set)
2. phone        (normalized to E.164 against the workspace's country)
3. email        (case-folded)
```

The matcher tries the highest-priority supplied identifier first. **If a lower-priority identifier points to a different contact**, the request is rejected with 422 `conflicting_identifiers` and a `candidates` array — this prevents a stale `email` from silently routing a conversion to the wrong contact.

**Resolving conflicts:** add `target_contact_id` to your request body to tell the matcher exactly which contact you mean. Hint identifiers are still soft-validated (a mismatch returns 422 `target_identifier_mismatch`), but the named contact is used.

```json
{
  "target_contact_id": 1284,
  "phone": "+15551234567",
  "stage": "won",
  "value_cents": 1200000
}
```

***

### Endpoints

#### `POST /api/v1/conversions` — record a conversion event

The primary postback endpoint. Use this whenever an external event has occurred that should advance the funnel: appointment booked, proposal sent, deal won, etc.

**Request body:**

```json
{
  "phone": "+15551234567",
  "email": "jane@example.com",
  "external_id": "hs-contact-12345",
  "stage": "appointment_booked",
  "value_cents": 500000,
  "currency_code": "USD",
  "occurred_at": "2026-05-19T15:00:00Z",
  "force_stage": false,
  "create_if_missing": false,
  "target_contact_id": null,
  "custom_fields": {
    "appointment_at": "2026-05-25T10:00:00Z"
  },
  "external_event_id": "calendly-evt-7d3"
}
```

**Required fields:**

* At least one identifier — `phone`, `email`, `external_id`, OR `target_contact_id`
* `stage` — any value from the Contact stages enum (`new`, `contacted`, `form_submitted`, `qualified`, `appointment_booked`, `proposal_sent`, `won`, `customer`, `lost`, `unqualified`)

**Optional fields:**

| Field               | Purpose                                                                                                                                        |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `value_cents`       | Deal value in cents. Required when `stage` is `won` or `proposal_sent` (or send `inherit_value: true` if the contact already has one set)      |
| `inherit_value`     | `true` to satisfy the `won` / `proposal_sent` value requirement by reusing the contact's existing deal value, instead of sending `value_cents` |
| `currency_code`     | ISO 4217 — defaults to workspace currency                                                                                                      |
| `occurred_at`       | When the event happened in your system (defaults to server time)                                                                               |
| `force_stage`       | `true` to allow a backward stage move. Requires `crm:force` token ability                                                                      |
| `create_if_missing` | `true` to create a new Contact when no match is found (otherwise 404)                                                                          |
| `target_contact_id` | Skip the matcher and use this contact id directly                                                                                              |
| `custom_fields`     | Map of `key: value` matching workspace custom field schema                                                                                     |
| `external_event_id` | Your system's identifier for this specific event (useful for support cross-referencing)                                                        |

**Response 201 (new event):**

```json
{
  "conversion_event_id": 88421,
  "contact_id": 1284,
  "contact_external_id": "hs-contact-12345",
  "previous_stage": "qualified",
  "requested_stage": "appointment_booked",
  "current_stage": "appointment_booked",
  "current_value_cents": 500000,
  "currency_code": "USD",
  "applied_stage_change": true,
  "google_ads_upload_status": "queued"
}
```

**Response 200** — idempotent replay (same body as the original 201).

**Response when stage was not applied** (e.g. backward move without force):

```json
{
  "conversion_event_id": 88422,
  "contact_id": 1284,
  "previous_stage": "won",
  "requested_stage": "qualified",
  "current_stage": "won",
  "applied_stage_change": false,
  "google_ads_upload_status": "skipped_no_stage_change",
  "ignore_reason": "backward_move_without_force"
}
```

In the no-op case the event still appears in the contact's timeline as audit history; `conversion.recorded` fires but `contact.stage_changed` does NOT.

***

#### `POST /api/v1/contacts` — create or upsert a contact

Use when you want to create a contact explicitly (without sending a conversion event yet).

**Request body:**

```json
{
  "external_id": "hs-contact-12345",
  "phone": "+15551234567",
  "email": "jane@example.com",
  "name": "Jane Doe",
  "company": "Acme Inc",
  "custom_fields": {
    "budget": 25000,
    "property_type": "condo"
  }
}
```

**Behavior:**

* **No existing contact** → creates one and returns `201`
* **Existing contact matched by `external_id`** → returns `409 external_id_exists` with the existing `contact_id`
* **Existing contact matched uniquely by phone or email** → returns `200` with the existing contact (idempotent on identifier match)
* **Multiple matches** → `422 ambiguous_match` with `candidates` array
* **Soft-deleted contact matches** → restored and returned with `"restored": true`

Phone numbers are normalized to E.164. `custom_fields` are validated against your workspace schema; unknown keys are rejected unless you pass `?allow_unknown_fields=true` (which stashes them under a `_unmapped` sub-key).

***

#### `PATCH /api/v1/contacts/{id}` — update a contact

Partial update. Body accepts any subset of the create-contact fields.

```bash
curl -X PATCH https://ringtonic.app/api/v1/contacts/1284 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Jane Doe-Smith",
    "company": "Acme Holdings",
    "custom_fields": { "budget": 35000 }
  }'
```

You can also move the contact's stage here by sending `lead_status`. Note the field name differs by endpoint: `POST /conversions` uses `stage`, while this endpoint uses `lead_status`. The same forward-only rules apply, and a conversion event is recorded with source `postback`.

***

#### `GET /api/v1/contacts/match` — diagnostic lookup

Returns the contact the conversion endpoint would resolve for the given identifiers. Useful when wiring up Zapier or n8n to test your match logic before going live.

```bash
curl "https://ringtonic.app/api/v1/contacts/match?phone=%2B15551234567&email=jane@example.com" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Responses:**

* `200 { "match": { "id": 1284, ... }, "matched_by": "phone" }` — unique match
* `404 { "match": null }` — no match
* `422 { "error": "ambiguous_match", "candidates": [ ... ] }` — multiple contacts matched, send `target_contact_id` on your conversion call to pick one

***

#### `GET /api/v1/contacts/{id}/events` — conversion event log

Returns the conversion-event timeline for one contact — every stage change, with where it came from, its value, and when it happened. Cursor-paginated, 50 per page; follow `next_cursor` for older events.

```bash
curl "https://ringtonic.app/api/v1/contacts/1284/events" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response 200:**

```json
{
  "data": [
    {
      "id": 88421,
      "contact_id": 1284,
      "from_stage": "qualified",
      "to_stage": "appointment_booked",
      "source": "postback",
      "applied_stage_change": true,
      "value_cents": 500000,
      "currency_code": "USD",
      "external_event_id": "calendly-evt-7d3",
      "occurred_at": "2026-05-19T15:00:00+00:00"
    }
  ],
  "next_cursor": null
}
```

Use it to sync a contact's funnel history back to your CRM.

***

### Status Codes

| Code  | Meaning                                                                                            |
| ----- | -------------------------------------------------------------------------------------------------- |
| `200` | Idempotent replay, or unique-identifier match returning existing contact                           |
| `201` | New event recorded / new contact created                                                           |
| `400` | Malformed body (invalid JSON, missing required structure)                                          |
| `401` | Token missing, invalid, or lacks `workspace:<id>` scope                                            |
| `403` | Workspace not on Agency plan, or token lacks `crm:write` / `crm:force`                             |
| `404` | No matching contact (and `create_if_missing=false`), or contact in another workspace               |
| `409` | `external_id_exists` (POST /contacts), or `Idempotency-Key` reused with a different body           |
| `422` | Validation failed, or `ambiguous_match` / `conflicting_identifiers` / `target_identifier_mismatch` |
| `429` | Rate limit (see below)                                                                             |

**Error responses** carry a JSON body with an `error` code (the names used in the rows above) plus any useful context:

```json
{
  "error": "ambiguous_match",
  "candidates": [1284, 1290]
}
```

***

### Rate Limits

| Endpoint                           | Limit                             |
| ---------------------------------- | --------------------------------- |
| `POST /api/v1/conversions`         | 120 requests / minute / workspace |
| `POST /api/v1/contacts`            | 60 requests / minute / workspace  |
| `PATCH /api/v1/contacts/{id}`      | 120 requests / minute / workspace |
| `GET /api/v1/contacts/match`       | 60 requests / minute / workspace  |
| `GET /api/v1/contacts/{id}/events` | 60 requests / minute / workspace  |

All limits are keyed per workspace. 429 responses include a `Retry-After` header — back off and retry after the window resets. (Idempotent replays still pass through the limiter, so count them in your budget.)

***

### Webhook Companions

Every postback fires one or more outbound webhooks (see [Webhooks](/guides/webhooks)):

| Webhook event           | Fires on                                                       |
| ----------------------- | -------------------------------------------------------------- |
| `conversion.recorded`   | Every accepted conversion event (including no-op audit events) |
| `contact.stage_changed` | Only when the contact's stage actually moved                   |
| `form.submitted`        | Only on form-capture beacons (not on postback API calls)       |

The ordering inside a transaction is deterministic: `form.submitted` → `conversion.recorded` → `contact.stage_changed`.

***

### Integration Recipes

<details>

<summary>Calendly: appointment booked</summary>

In Calendly's webhook settings, point at `https://ringtonic.app/api/v1/conversions` with body:

```json
{
  "email": "{{ invitee.email }}",
  "phone": "{{ invitee.questions_and_answers[0].answer }}",
  "stage": "appointment_booked",
  "occurred_at": "{{ event.start_time }}",
  "external_event_id": "calendly-{{ event.uuid }}",
  "create_if_missing": true,
  "custom_fields": {
    "appointment_at": "{{ event.start_time }}"
  }
}
```

Use `external_event_id` as your `Idempotency-Key` so Calendly's retry-on-failure doesn't double-book the funnel.

</details>

<details>

<summary>HubSpot: deal closed-won</summary>

Set up a workflow that fires when a deal stage = "Closed Won" and call:

```json
{
  "external_id": "{{ contact.hs_object_id }}",
  "stage": "won",
  "value_cents": {{ deal.amount * 100 }},
  "currency_code": "{{ deal.deal_currency_code }}",
  "occurred_at": "{{ deal.closedate }}",
  "external_event_id": "hubspot-deal-{{ deal.hs_object_id }}"
}
```

The `external_id` matched on the contact's HubSpot ID gives you stable identity across CRM updates.

</details>

<details>

<summary>Zapier: form-fill in a non-Ring-Tonic form</summary>

Use a Zap with Code by Zapier to generate an Idempotency-Key (UUID), then POST to `/api/v1/conversions` with:

```json
{
  "phone": "{{ form_phone }}",
  "email": "{{ form_email }}",
  "stage": "form_submitted",
  "create_if_missing": true,
  "external_event_id": "zapier-{{ zap_id }}-{{ timestamp }}"
}
```

For Ring Tonic-hosted tracking, use [Form Submissions](/guides/form-submissions) instead — it's faster and free of Zapier latency.

</details>

***

### Common Questions

<details>

<summary>Do I need a separate API key per integration?</summary>

It's a good idea — separate keys can be revoked independently if one integration is compromised. Each key needs the same `workspace:<id>` ability for the target workspace.

</details>

<details>

<summary>What's the difference between `external_id` and `target_contact_id`?</summary>

`external_id` is *your* system's stable identifier for the contact (e.g. HubSpot's `hs_object_id`). It's stored on the Contact and used for future matching. `target_contact_id` is Ring Tonic's internal contact ID — useful as an escape hatch when the matcher returns `conflicting_identifiers` and you need to disambiguate.

</details>

<details>

<summary>Can I push the same event twice without dedup?</summary>

Yes — omit `Idempotency-Key`. Each call creates a new `ConversionEvent`. The contact still only advances on the first forward-stage transition; subsequent events are logged as `(ignored)` no-ops. Most integrators want idempotency on; the option to skip it is there for systems that genuinely need a separate event per call.

</details>

<details>

<summary>How long are idempotency records kept?</summary>

24 hours from the original request. After that the key is reusable.

</details>

<details>

<summary>Why am I getting 401 even though my key is correct?</summary>

The most common cause is a missing or incorrect workspace ability. CRM endpoints require `workspace:<id>` matching the workspace you want to act on. Re-create the key under **Settings** → **API Keys** with explicit `workspace:<id>`, `crm:write` (and `crm:force` if needed). Legacy un-scoped keys created before the CRM API shipped will fail closed on these routes with an upgrade hint.

</details>

***

### Related Guides

* [API](/guides/api) — general API access (keys, GeoData endpoint)
* [Contacts](/guides/contacts) — pipeline view of the data this API writes
* [Form Submissions](/guides/form-submissions) — Ring Tonic's own no-code form capture
* [Webhooks](/guides/webhooks) — subscribe to events emitted by postbacks


# White Label

White Label lets you serve client reports from your own custom domain with your branding. Instead of sharing `ringtonic.app` links, your clients see your agency's domain (e.g., `reports.youragency.com`).

{% hint style="info" %}
White Label is available on the **Agency plan** only.
{% endhint %}

<div data-full-width="false"><figure><img src="/files/On06sZvo6v8F4dLmc9Xo" alt=""><figcaption><p>White Label Portal</p></figcaption></figure></div>

### How It Works

1. **Add your domain** in Ring Tonic settings
2. **Configure DNS** to add a CNAME record to your system
3. **Wait for automatic verification** (checked every 5 minutes)
4. **Customize branding** with your logo and colors
5. **Set up custom email delivery** so notifications come from your email address
6. **Migrate webhooks** so calls route through your domain

Once set up, your clients access reports at `https://reports.youragency.com` instead of `ringtonic.app`, with your branding throughout—including email notifications.

***

### Adding Your Domain

<figure><img src="/files/mpoUTQtecyG6cnF5A7Ea" alt="" width="375"><figcaption><p>Access White Label from the User Setting dropdown</p></figcaption></figure>

1. Go to **Settings** → **White Label**
2. Enter your custom domain (e.g., `reports.youragency.com`)
3. Click **Add Domain**

{% hint style="warning" %}
**Use a subdomain:** We recommend using a subdomain like `reports.youragency.com` rather than your root domain.
{% endhint %}

***

### Configuring DNS

<figure><img src="/files/H765VHkUasjuDxjxTVar" alt="" width="563"><figcaption><p>Configure your DNS after adding a domain</p></figcaption></figure>

After adding your domain, configure your DNS with a CNAME record:

| Type  | Name                     | Value              |
| ----- | ------------------------ | ------------------ |
| CNAME | `reports.youragency.com` | `to.laravel.cloud` |

{% hint style="info" %}
**DNS propagation** can take up to 48 hours, though it's usually much faster.
{% endhint %}

***

### Verification

Ring Tonic automatically checks pending domains every 5 minutes. Once your DNS is correctly configured:

1. Ring Tonic detects the DNS change
2. SSL certificate is automatically provisioned
3. Your domain becomes active

You can also manually trigger a check by clicking **Check Verification** on the White Label settings page.

{% hint style="success" %}
**Automatic SSL:** Ring Tonic automatically provisions and renews SSL certificates. No manual configuration needed.
{% endhint %}

#### Verification Status

| Status       | Meaning                                    |
| ------------ | ------------------------------------------ |
| **Pending**  | Waiting for DNS verification               |
| **Verified** | DNS correct, SSL being provisioned         |
| **Active**   | Domain fully working, ready to use         |
| **Failed**   | DNS misconfigured, check your CNAME record |

***

### Customizing Your Branding

<figure><img src="/files/jv5JMjeVAIVHRMgSFuTg" alt="" width="563"><figcaption><p>Full branding customization</p></figcaption></figure>

After your domain is active, customize the appearance:

1. Go to **Settings** → **White Label**
2. Update your branding:
   * **Brand Name:** Your agency name (used in browser titles and as logo fallback)
   * **Logo:** Your company logo (PNG, JPG, SVG, WebP)
   * **Favicon:** Browser tab icon
   * **Support Email:** Where clients contact for help
3. Click **Save**

#### Brand Name

The brand name appears in two places:

| Location          | When It's Used                                               |
| ----------------- | ------------------------------------------------------------ |
| **Browser title** | Always shows as suffix (e.g., "Call Activity - Your Agency") |
| **Page header**   | Only when no logo is uploaded                                |

{% hint style="info" %}
**No logo?** If you haven't uploaded a logo, your brand name displays as text in the header. This is useful if you want a text-based branding without creating a logo image.
{% endhint %}

{% hint style="success" %}
**Pro Tip:** Use a transparent PNG for your logo so it looks good on both light and dark backgrounds.
{% endhint %}

***

### Custom Email Delivery (Optional)

By default, Ring Tonic sends notifications (call log exports, webhook migration updates, workspace invitations, etc.) from our email address. With Custom Email Delivery, these notifications are sent through **your own mail server** so clients see your agency's sender identity.

{% hint style="info" %}
**Requires verified domain:** The Email Delivery section only appears after your white-label domain is verified and active.
{% endhint %}

<figure><img src="/files/Ohq2KIh5MYj2o3SUKTu6" alt=""><figcaption><p>Email Delivery settings within the White Label configuration</p></figcaption></figure>

#### Setting Up Custom SMTP

1. Go to **Settings** → **White Label**
2. Scroll to the **Email Delivery** section
3. Enter your SMTP credentials:

| Field          | Description                  | Example                     |
| -------------- | ---------------------------- | --------------------------- |
| **SMTP Host**  | Your mail server address     | `smtp.youragency.com`       |
| **Port**       | SMTP port number             | `587` (TLS) or `465` (SSL)  |
| **Username**   | SMTP authentication username | `noreply@youragency.com`    |
| **Password**   | SMTP authentication password | Leave blank if not required |
| **Encryption** | Connection security          | None, TLS, or SSL           |
| **From Email** | Sender email address         | `noreply@youragency.com`    |
| **From Name**  | Sender display name          | `Your Agency Name`          |

4. Click **Test Connection** to verify your credentials
5. Click **Save**

{% hint style="warning" %}
**Test before saving.** Always use the **Test Connection** button to verify your SMTP credentials are correct before saving. Incorrect settings won't prevent Ring Tonic from sending emails—it will fall back to the default sender—but your clients won't see your branding.
{% endhint %}

All app notifications (exports, invitations, alerts, etc.) will be sent through your SMTP server. Password reset and email verification emails always use Ring Tonic's default sender for security.

#### Clearing SMTP Settings

To stop using your own mail server and revert to Ring Tonic's default:

1. Click **Clear SMTP** in the Email Delivery section
2. Click **Save**

All future notifications will be sent from Ring Tonic's default email address.

<details>

<summary>What happens to email delivery if I downgrade my plan?</summary>

Your SMTP credentials are preserved, but email delivery automatically reverts to Ring Tonic's default sender while your domain is inactive. If you upgrade again, your custom SMTP settings are restored automatically—no reconfiguration needed.

</details>

<details>

<summary>Can I use any SMTP provider?</summary>

Yes. Any SMTP server works, including Gmail, Amazon SES, Mailgun, Postmark, SendGrid, or your own mail server.

</details>

<details>

<summary>What if my SMTP server is down?</summary>

Ring Tonic will automatically retry failed notifications. If your server remains unreachable, notifications will be skipped for that attempt.

</details>

***

### Migrating Webhooks (Optional)

When you enable White Label, your tracking numbers can be updated to route calls through your custom domain.

<figure><img src="/files/UfNMC9mgjuW880aYP6bC" alt="" width="563"><figcaption><p>Update existing Twilio webhooks to use your white-label domain</p></figcaption></figure>

1. Go to **Settings** → **White Label**
2. Click **Update now** under your domain
3. Review how many numbers need updating
4. Click **Update** to migrate them
5. You'll receive an email when migration completes

{% hint style="info" %}
**No downtime:** Calls continue working throughout the migration.
{% endhint %}

***

### Common Questions

<details>

<summary>Do I need my own SSL certificate?</summary>

No. Ring Tonic automatically provisions and manages SSL certificates for your white-label domain.

</details>

<details>

<summary>Can I use my root domain (e.g., youragency.com)?</summary>

Technically yes, but we recommend using a subdomain to keep your main website separate.

</details>

<details>

<summary>How long does DNS verification take?</summary>

Once your DNS is correctly configured, verification typically happens within minutes. DNS propagation can take up to 48 hours.

</details>

<details>

<summary>What happens if I remove my white-label domain?</summary>

Your reports will revert to using `ringtonic.app`. Existing shared links using your custom domain will stop working.

</details>

<details>

<summary>Can I change my white-label domain?</summary>

Yes, but you'll need to remove the current domain and add a new one. This requires re-verifying DNS and migrating webhooks again.

</details>

<details>

<summary>Do all my workspaces use the same white-label domain?</summary>

Yes, white-label settings are tied to your user account, not individual workspaces.

</details>

<details>

<summary>What happens to call tracking if I downgrade my plan?</summary>

Call tracking and webhooks continue working normally even after downgrading. Only client-facing pages are affected - they'll be redirected to the main application domain.

</details>


# Port Existing Numbers

<figure><img src="/files/XkWNDtZRqzhKw33c3Nug" alt=""><figcaption></figcaption></figure>

If you're migrating from another call tracking platform like CallRail, you need to port your existing tracking numbers to Twilio before importing them into Ring Tonic. This ensures your phone numbers continue working and your customers can still reach you.

{% hint style="danger" %}
**Critical:** Do NOT cancel your existing call tracking service until the port is complete. If you cancel first, those numbers will be released immediately and your clients will call a dead line.
{% endhint %}

***

### Why Port Your Numbers?

If you've been using tracking numbers on your website, ads, business cards, or any marketing materials, those numbers are tied to your existing platform (e.g., CallRail, Marchex, DialogTech).

#### The Risk of Not Porting

When you cancel your existing service without porting:

* **Numbers are released immediately** - They stop working the moment your account closes
* **Customer calls fail** - Anyone dialing those numbers gets a "disconnected" message
* **Lost business** - Clients who saved your number can't reach you
* **Marketing waste** - All your ads, billboards, and printed materials become useless

#### The Solution: Port to Twilio

Porting transfers ownership of the phone numbers from your current provider to your Twilio account. Once in Twilio, you control them forever and can import them into Ring Tonic.

```
┌─────────────┐      ┌─────────────┐      ┌─────────────┐
│  CallRail   │──────│  Twilio     │──────│  Ring Tonic │
│  (or other  │ PORT │  (you own   │IMPORT│  (tracking  │
│  platform)  │      │  the number)│      │  & routing) │
└─────────────┘      └─────────────┘      └─────────────┘
```

***

### Porting Costs

{% hint style="success" %}
**Good News:** For US Local and Toll-Free numbers, Twilio charges **$0** to port them in. The porting process itself is completely free.
{% endhint %}

#### Ongoing Costs

Once the numbers are in your Twilio account, you pay Twilio's standard monthly rate:

| Number Type   | Monthly Cost  |
| ------------- | ------------- |
| US Local      | \~$1.15/month |
| US Toll-Free  | \~$2.00/month |
| International | Varies        |

These charges go directly to Twilio and are separate from your Ring Tonic subscription.

***

### How to Port Numbers

You initiate the porting process inside Twilio, not your current provider. Here's the complete workflow:

{% stepper %}
{% step %}
**Keep Your Current Service Active**

**Do NOT cancel your existing service yet.** This is critical:

* If you cancel before porting completes, the numbers are released immediately
* There's no way to recover released numbers
* The port request will fail if the account is closed

{% hint style="warning" %}
Keep your current service (CallRail, Marchex, etc.) active and paid until Twilio confirms the port is complete.
{% endhint %}
{% endstep %}

{% step %}
**Get Your CSR (Customer Service Record)**

You need proof that you own the numbers. This is called a CSR (Customer Service Record) or sometimes a "Port Out PIN" or "Letter of Authorization (LOA)".

**For CallRail:**

1. Log in to your CallRail account
2. Go to **Settings** → **Account** → **Porting**
3. Click **Request CSR** or download existing CSR documents
4. Alternatively, email CallRail support: `support@callrail.com`

**For other platforms:**

Contact your provider's support and request:

* A CSR (Customer Service Record)
* Port Out PIN
* Letter of Authorization (LOA)

Most platforms provide these documents within 1-2 business days.

{% hint style="info" %}
The CSR typically includes your account details, billing address, and a list of all phone numbers you want to port.
{% endhint %}
{% endstep %}

{% step %}
**Submit Port Request in Twilio**

Once you have your CSR, log in to Twilio and initiate the port:

1. Go to [Twilio Console](https://console.twilio.com/)
2. Navigate to **Phone Numbers** → **Port & Host** → **Port In**
3. Click **Create New Port In Request**
4. Fill in the port request form:
   * **Numbers to Port:** Enter all phone numbers (one per line)
   * **Current Provider:** Select your provider (e.g., CallRail)
   * **Account Details:** Match the information on your CSR exactly
   * **Billing Address:** Must match the address on file with your current provider
5. Upload supporting documents:
   * CSR from your current provider
   * Recent bill or invoice (if required)
6. Select a **Desired Activation Date** (Twilio will try to complete by this date)
7. Click **Submit Port Request**

{% hint style="success" %}
For detailed instructions, see [Twilio's Porting Guide](https://www.twilio.com/docs/phone-numbers/porting).
{% endhint %}
{% endstep %}

{% step %}
**Wait for Twilio to Process**

After submitting, Twilio handles the coordination with your current provider:

* **Processing Time:** Usually 1-4 weeks depending on the carrier and number type
* **Zero Downtime:** Your numbers continue working during the entire process
* **Status Updates:** Twilio emails you with progress updates

**Port Request Statuses:**

* **Pending:** Twilio is reviewing your documents
* **Submitted:** Sent to your current carrier for approval
* **FOC Received:** Firm Order Confirmation - port date is scheduled
* **Complete:** Numbers are now in your Twilio account

{% hint style="info" %}
You can track the port status anytime at **Twilio Console** → **Phone Numbers** → **Port & Host** → **Port In**.
{% endhint %}
{% endstep %}

{% step %}
**Cancel Your Old Service (After Confirmation)**

Only after Twilio confirms the port is **complete**:

1. Verify all numbers are working in your Twilio account
2. Log in to your old provider (CallRail, etc.)
3. Cancel your subscription

{% hint style="success" %}
Once the port is complete, you own the numbers forever through your Twilio account. Your old provider no longer has any control over them.
{% endhint %}
{% endstep %}
{% endstepper %}

***

### After Porting: Import to Ring Tonic

Once your numbers are in Twilio, the next step is importing them into Ring Tonic so you can use them for call tracking.

#### How to Import Numbers

1. Go to **Ring Tonic** → **Phone Numbers** → **Import Numbers**
2. Ring Tonic automatically loads all phone numbers from your Twilio account
3. Select the newly ported numbers
4. Click **Import**

The numbers are now in your Ring Tonic inventory and ready to be assigned to campaigns.

{% hint style="info" %}
For detailed instructions, see the [Phone Numbers guide](/guides/phone-numbers#importing-numbers-from-twilio).
{% endhint %}

***

### Common Porting Issues

<details>

<summary>Port request was rejected</summary>

**Possible reasons:**

* **Mismatched information:** The account details you provided don't match what's on file with your current provider
* **Outstanding balance:** You have unpaid bills with your current provider
* **Wrong documents:** The CSR is outdated or incomplete

**How to fix:**

1. Contact your current provider to verify account details
2. Ensure all bills are paid
3. Request a fresh CSR if needed
4. Resubmit the port request in Twilio with corrected information

</details>

<details>

<summary>How long does porting take?</summary>

**Typical timelines:**

* **US Local numbers:** 7-10 business days
* **US Toll-Free numbers:** 7-21 business days
* **International numbers:** Varies widely (2-6 weeks)

Twilio aims to complete ports on your requested activation date, but it depends on your current carrier's processing speed.

</details>

<details>

<summary>Will my numbers stop working during the port?</summary>

No. Porting has zero downtime. Your numbers continue working with your current provider until the exact moment the port completes. Then they seamlessly switch to Twilio without any interruption.

</details>

<details>

<summary>Can I port numbers from multiple providers at once?</summary>

Yes, but you need to submit a separate port request for each provider. For example, if you have numbers with both CallRail and Marchex, you'll create two port requests in Twilio.

</details>

<details>

<summary>What if I already canceled my CallRail account?</summary>

Unfortunately, if your account is already closed and the numbers were released, they're gone. You cannot port numbers that have been released back into the carrier pool.

**Your options:**

* Contact your old provider immediately to see if they can reactivate your account
* If the numbers are truly lost, you'll need to purchase new numbers and update all your marketing materials

**Lesson learned:** Always port before canceling.

</details>

<details>

<summary>Do I need to notify my current provider before porting?</summary>

No. The porting process itself is the notification. When Twilio submits the port request, your current provider receives it automatically. However, it doesn't hurt to give them a heads-up if you want to maintain a good relationship.

</details>

***

### Port Request Checklist

Before submitting your port request, verify:

* [ ] Current service account is **active and paid**
* [ ] CSR or LOA is **downloaded and ready**
* [ ] Account details (name, address) **match exactly** between CSR and Twilio
* [ ] All phone numbers are **listed correctly** (no typos)
* [ ] Supporting documents (CSR, recent bill) are **uploaded**
* [ ] Desired activation date is **realistic** (at least 2 weeks out)
* [ ] You have a **plan to cancel the old service** after port completes

{% hint style="success" %}
**Pro Tip:** Port during a low-traffic period if possible. While there's no downtime, it's good practice to minimize risk during your busiest seasons.
{% endhint %}


# How to Ensure 100% Attribution Accuracy

Ring Tonic automatically tracks where your website visitors come from (Source) and how they found you (Medium). To get the most accurate data, follow these rules for your different marketing channels.

Ring Tonic uses a smart attribution system that automatically detects traffic sources from multiple signals: click IDs from ad platforms, referrer URLs, and UTM parameters. Here's what works automatically and when you need to add tracking parameters.

<figure><img src="/files/GmlSAS1A17d1DFwstaKg" alt=""><figcaption></figcaption></figure>

***

## 1. What Works Automatically (No Action Needed)

You do not need to do anything for these sources. Ring Tonic automatically detects them.

### Paid Advertising (via Click IDs)

When visitors click your ads, the ad platform adds a special click ID to the URL. Ring Tonic automatically detects these:

| Platform               | Click ID                    | Attribution    |
| ---------------------- | --------------------------- | -------------- |
| Google Ads             | `gclid`, `gbraid`, `wbraid` | google / cpc   |
| Facebook/Instagram Ads | `fbclid`                    | facebook / cpc |
| Microsoft/Bing Ads     | `msclkid`                   | bing / cpc     |
| TikTok Ads             | `ttclid`                    | tiktok / cpc   |
| LinkedIn Ads           | `li_fat_id`                 | linkedin / cpc |

{% hint style="success" %}
**Important:** For Google Ads, ensure "Auto-Tagging" is enabled in your Google Ads settings. This is on by default for most accounts.
{% endhint %}

{% hint style="info" %}
**What are gbraid and wbraid?** These are Google's privacy-focused click IDs used when traditional cookies are restricted. `gbraid` tracks iOS app campaign conversions, while `wbraid` tracks web conversions on privacy-restricted browsers. Ring Tonic automatically detects both.
{% endhint %}

### Organic Search

Visitors coming from search engine results are automatically detected:

| Search Engine | Attribution          |
| ------------- | -------------------- |
| Google        | google / organic     |
| Bing          | bing / organic       |
| Yahoo         | yahoo / organic      |
| DuckDuckGo    | duckduckgo / organic |
| Baidu         | baidu / organic      |
| Yandex        | yandex / organic     |

### Social Media (Organic Posts)

Visitors clicking links from social media posts are automatically detected:

| Platform  | Attribution        |
| --------- | ------------------ |
| Facebook  | facebook / social  |
| Twitter/X | twitter / social   |
| Instagram | instagram / social |
| LinkedIn  | linkedin / social  |
| YouTube   | youtube / social   |
| TikTok    | tiktok / social    |
| Pinterest | pinterest / social |
| Reddit    | reddit / social    |
| Threads   | threads / social   |

{% hint style="success" %}
**Note:** This works for organic social posts. For paid social ads, the click ID detection (Section above) takes priority.
{% endhint %}

### Webmail Clicks

If someone clicks a link in your email from a webmail interface, Ring Tonic detects it:

| Webmail Provider        | Attribution         |
| ----------------------- | ------------------- |
| Gmail (mail.google.com) | gmail / email       |
| Outlook                 | outlook / email     |
| Yahoo Mail              | yahoo\_mail / email |
| AOL Mail                | aol / email         |
| ProtonMail              | protonmail / email  |

{% hint style="success" %}
**Note:** This only works when emails are opened in a web browser. Desktop and mobile email apps (like Apple Mail or Outlook desktop) typically don't send referrer data - see Section 2.
{% endhint %}

### Google Maps / Google Business Profile

Visitors clicking your website link from Google Maps are detected:

| Source            | Attribution            |
| ----------------- | ---------------------- |
| Google Maps (web) | google\_maps / organic |

**Important Caveat:** The Google Maps mobile app often does NOT send referrer data. Clicks from the app may appear as "Direct" traffic. See Section 2 for the recommended solution.

### Referral Sites

Visitors clicking a link on another website (e.g., Yelp, a local blog, a news article):

* Attribution: `{domain}` / referral
* Example: `yelp.com / referral`

### Direct Traffic

Visitors typing your URL directly into the browser, or when no tracking data is available:

* Attribution: `direct / none`

***

## 2. When to Use UTM Parameters (Recommended)

For these channels, referrer data is often missing or unreliable. Adding UTM parameters ensures accurate attribution.

### Email Newsletters (Desktop/Mobile Apps)

Email clicks from apps (Outlook desktop, Apple Mail, Gmail app) almost always show up as "Direct" traffic because email apps don't send referrer data.

**Your Link:**

```
https://yoursite.com/?utm_source=newsletter&utm_medium=email&utm_campaign=october_update
```

### Google Business Profile (Mobile App)

While web clicks from Google Maps are detected automatically, the Google Maps mobile app usually doesn't send referrer data.

**Recommended:** Add UTMs to your GBP website link:

```
https://yoursite.com/?utm_source=google_business_profile&utm_medium=organic
```

This ensures mobile app clicks are properly attributed instead of appearing as "Direct."

### QR Codes (Flyers/Mailers)

A QR code scan is just a direct link visit with no referrer. To track which flyer or mailer worked:

**Your Link:**

```
https://yoursite.com/?utm_source=mailer&utm_medium=qr_code&utm_campaign=zip_98101
```

### SMS/Text Message Campaigns

Links in text messages have no referrer data:

**Your Link:**

```
https://yoursite.com/?utm_source=sms&utm_medium=text&utm_campaign=appointment_reminder
```

### Custom Campaign Tracking

If you want human-readable campaign names in your Ring Tonic dashboard (rather than relying on click IDs), you can add UTM parameters to any link:

**Example for Facebook Ads:**

```
https://yoursite.com/?utm_source=facebook&utm_medium=cpc&utm_campaign=summer_promo
```

{% hint style="info" %}
**Note:** When UTM parameters are present, they take priority over automatic detection.
{% endhint %}

***

## 3. Attribution Priority Order

Ring Tonic uses this priority order to determine source/medium:

1. **Explicit UTM Parameters** - If `utm_source` or `utm_medium` are in the URL, they are used directly
2. **Click IDs** - gclid, gbraid, wbraid, fbclid, msclkid, ttclid, li\_fat\_id are detected and mapped to their platforms
3. **Referrer URL** - The browser's referrer is parsed to identify the source
4. **Direct** - If no data is available, traffic is marked as direct/none

This means you can always override automatic detection by adding UTM parameters if you need more specific tracking.

***

## 4. Offline Sources (Static Tracking Numbers)

If there is no link to click (e.g., Billboard, Radio Ad, TV Commercial, or the physical phone number on your Google Business Profile), UTM parameters don't apply.

**Strategy:** Purchase a unique Static Tracking Number inside Ring Tonic.

**Setup:**

1. Buy a dedicated phone number in Ring Tonic
2. Assign it to a Static Campaign named after the source (e.g., "Billboard I-95")
3. Use that number exclusively on that marketing material

**Attribution:** Any call to that number is automatically attributed to that campaign.

***

## Quick Reference: UTM Parameter Format

```
https://yoursite.com/?utm_source=SOURCE&utm_medium=MEDIUM&utm_campaign=CAMPAIGN_NAME
```

| Parameter      | Purpose                     | Examples                                         |
| -------------- | --------------------------- | ------------------------------------------------ |
| `utm_source`   | Where the traffic came from | `google`, `facebook`, `newsletter`, `billboard`  |
| `utm_medium`   | How it reached you          | `cpc`, `email`, `social`, `qr_code`, `organic`   |
| `utm_campaign` | Specific campaign name      | `summer_sale`, `october_newsletter`, `zip_98101` |

**Common Medium Values:**

* `cpc` - Cost per click (paid ads)
* `organic` - Unpaid/natural traffic
* `email` - Email campaigns
* `social` - Social media
* `referral` - Links from other websites
* `qr_code` - QR code scans

***

## Summary

| Channel                        | Action Required | Notes                             |
| ------------------------------ | --------------- | --------------------------------- |
| Google Ads                     | None            | Enable Auto-Tagging in Google Ads |
| Facebook/Instagram Ads         | None            | Click ID auto-detected            |
| Bing Ads                       | None            | Click ID auto-detected            |
| TikTok Ads                     | None            | Click ID auto-detected            |
| LinkedIn Ads                   | None            | Click ID auto-detected            |
| Organic Search                 | None            | Referrer auto-detected            |
| Social Media Posts             | None            | Referrer auto-detected            |
| Webmail (Gmail, Outlook web)   | None            | Referrer auto-detected            |
| Google Maps (web)              | None            | Referrer auto-detected            |
| Google Maps (mobile app)       | Add UTMs to GBP | Mobile app has no referrer        |
| Email (desktop/mobile apps)    | Add UTMs        | Email apps have no referrer       |
| QR Codes                       | Add UTMs        | No referrer data                  |
| SMS/Text Messages              | Add UTMs        | No referrer data                  |
| Offline (Billboard, Radio, TV) | Static Number   | Use dedicated tracking number     |


# Browser Dialer

### What is the Browser Dialer?

The Browser Dialer is a built-in softphone that lets agents make and receive calls directly from their web browser — no external phone apps or hardware needed. It appears as a floating widget on your dashboard, giving agents one-click calling from contacts, recent calls, or a manual dial pad.

<div data-full-width="true"><figure><img src="/files/beCIsfH7vUI7eG3cSeUM" alt=""><figcaption><p>Call Dialer</p></figcaption></figure></div>

{% hint style="warning" %}
**Agency Plan Required:** The Browser Dialer is only available on the Agency plan. Indie plan users can upgrade to access this feature.
{% endhint %}

{% hint style="info" %}
**Requirements:** The Browser Dialer requires Twilio credentials (Account SID + Auth Token) to be configured in your workspace, plus a separate Twilio API Key for secure browser-based calling.
{% endhint %}

***

### Setting Up the Dialer

Setting up the Browser Dialer involves four steps: enabling the feature, creating a Twilio API Key, upgrading your Twilio account if still on the free trial, and importing phone numbers for outbound caller ID.

#### Step 1: Enable the Dialer

1. Go to your **Workspace Settings**
2. Click the **Dialer** tab
3. Toggle **Enable Dialer** to on
4. Click **Update Workspace**

<figure><img src="/files/rGM4NRTy72DZV0VkfqCE" alt="" width="563"><figcaption><p>Enable the dialer toggle in workspace settings</p></figcaption></figure>

{% hint style="info" %}
Make sure your Twilio Account SID and Auth Token are already configured in the **Basic** tab. The dialer needs these to provision the necessary Twilio resources automatically.
{% endhint %}

When you save with the dialer enabled, Ring Tonic automatically creates a **TwiML Application** in your Twilio account. This is the bridge that connects browser calls to Twilio's network. If something goes wrong during provisioning, you'll see a warning message with instructions to verify your Twilio credentials.

#### Step 2: Create a Twilio API Key

The dialer uses Twilio API Keys (not your Account SID/Auth Token) to generate secure, short-lived tokens for browser calling. This is a Twilio security requirement.

**How to Create an API Key:**

1. Log into your [Twilio Console](https://console.twilio.com)
2. Navigate to **Account** → **API keys & tokens**
3. Click **Create API Key**
4. Give it a name (e.g., "Ring Tonic Dialer")
5. Leave the key type as **Standard**
6. Click **Create API Key**
7. **Copy both the SID and Secret immediately** — the Secret is only shown once

<figure><img src="/files/MoJ85N7GBVmNzEVHS4jM" alt=""><figcaption><p>Create an API Key in the Twilio Console</p></figcaption></figure>

{% hint style="danger" %}
**Important:** Copy the API Key Secret immediately after creation. Twilio only displays it once. If you lose it, you'll need to create a new API Key.
{% endhint %}

**Add the API Key to Ring Tonic:**

1. Go to **Workspace Settings** → **Dialer** tab
2. Paste the **API Key SID** (starts with "SK") into the "API Key SID" field
3. Paste the **API Key Secret** into the "API Key Secret" field
4. Click **Update Workspace**

<figure><img src="/files/gM32gtxdVB82uLQmqRaP" alt="" width="563"><figcaption><p>Enter your Twilio API Key credentials in the dialer settings</p></figcaption></figure>

{% hint style="success" %}
Once saved, the dialer widget will appear for all agents in your workspace. Each agent gets a unique, encrypted token that refreshes automatically every hour.
{% endhint %}

#### Step 3: Upgrade Your Twilio Account (If on Free Trial)

{% hint style="danger" %}
**Critical:** If your Twilio account is still on the **free trial**, outbound calls are severely limited. Trial accounts can only call **verified phone numbers** (numbers you've manually verified in Twilio), are limited to **one Twilio number**, and calls are capped at **10 minutes**. You must upgrade to a paid Twilio account for the dialer to work properly.
{% endhint %}

To upgrade your Twilio account:

1. Log into your [Twilio Console](https://console.twilio.com)
2. Click the **Upgrade** button (or navigate to **Billing** → **Upgrade**)
3. Add a payment method and fund your account
4. Once upgraded, all restrictions are removed — you can call any phone number using any of your Twilio numbers as the caller ID

{% hint style="success" %}
After upgrading, all your tracking numbers can be used for outbound calls to any destination, with no call duration limits.
{% endhint %}

#### Step 4: Set Up Phone Numbers for Outbound Calls

To make outbound calls, agents need at least one tracking number to use as the caller ID. These are the same phone numbers you manage in your **Phone Numbers** inventory.

1. Go to **Phone Numbers**
2. Make sure you have at least one number imported from Twilio
3. Numbers can be assigned to a campaign or unassigned — both work for outbound dialing

{% hint style="info" %}
Don't have phone numbers yet? See the [Phone Numbers guide](/guides/phone-numbers) to learn how to import numbers from your Twilio account.
{% endhint %}

All tracking numbers in your workspace automatically appear in the dialer's caller ID dropdown. Agents can pick which number to show as the outbound caller ID.

***

### Adding Agents

Only users with the **Agent**, **Admin**, or **Owner** role can access the dialer. When you invite team members, assign them the "Agent" role if they need to make and receive calls.

#### How to Add an Agent

1. Go to **Workspace Members**
2. Click **Invite Member**
3. Enter the person's email address
4. Select **Agent** as the role
5. Click **Send Invitation**

<figure><img src="/files/bUdwzEbfdIadUjpZyV5L" alt="" width="563"><figcaption><p>Invite a new member with the Agent role</p></figcaption></figure>

The invited person receives an email with a link to join your workspace. Once they accept and log in, the dialer widget automatically appears on their dashboard.

{% hint style="info" %}
**Existing members:** If a team member already has the Manager or Member role and you want them to use the dialer, change their role to Agent from the members page. See [Team Management](/guides/team-management) for details.
{% endhint %}

#### What Agents Can Do

| Capability            | Agent | Admin/Owner | Manager | Member  |
| --------------------- | ----- | ----------- | ------- | ------- |
| Make outbound calls   | Yes   | Yes         | No      | No      |
| Receive inbound calls | Yes   | Yes         | No      | No      |
| View contacts         | Yes   | Yes         | Depends | Depends |
| Edit contacts         | Yes   | Yes         | Depends | No      |
| View call logs        | Yes   | Yes         | Depends | Depends |
| Qualify leads         | Yes   | Yes         | No      | No      |
| Add call notes        | Yes   | Yes         | No      | No      |

{% hint style="warning" %}
**Only agents and admins/owners receive incoming calls.** Managers and Members never see the dialer widget, even if the dialer is enabled for the workspace.
{% endhint %}

***

### Using the Dialer

Once set up, the dialer appears as a floating widget in the bottom-right corner of your screen. It has three main views: idle (with tabs), active call, and incoming call.

#### Agent Status

Before making or receiving calls, set your availability status using the dropdown in the dialer header:

| Status             | Icon          | Meaning                                               |
| ------------------ | ------------- | ----------------------------------------------------- |
| **Online**         | Green circle  | Available — you'll receive incoming calls             |
| **Away**           | Yellow circle | Temporarily unavailable — calls are not routed to you |
| **Do Not Disturb** | Red circle    | Manually set — no incoming calls                      |
| **In Call**        | Blue circle   | Automatically set when on a call                      |
| **Offline**        | Gray circle   | Disconnected — no calls                               |

<figure><img src="/files/LyTGQCeBnEkLWsaRudU2" alt=""><figcaption><p>Agent status dropdown in the dialer header</p></figcaption></figure>

{% hint style="info" %}
**Auto-away:** If you're inactive for 10 minutes, your status automatically changes to Away. It restores to Online when you interact with the page again.
{% endhint %}

{% hint style="info" %}
**Heartbeat:** The dialer sends a heartbeat every 30 seconds to keep your session alive. If the heartbeat stops (e.g., you close your browser), you'll be marked as Offline after 2 minutes.
{% endhint %}

#### Making Outbound Calls

There are three ways to make an outbound call:

{% tabs %}
{% tab title="From Contacts" %}
**Dial from the Contacts tab**

1. Open the dialer widget
2. Click the **Contacts** tab
3. Search for a contact by name or phone number
4. Click the **phone icon** next to the contact

<figure><img src="/files/23LDXppPBhNV3UVKd4Ka" alt="" width="375"><figcaption><p>Dial a contact from the Contacts tab</p></figcaption></figure>
{% endtab %}

{% tab title="From Keypad" %}
**Dial a number manually**

1. Open the dialer widget
2. Click the **Keypad** tab
3. Enter the phone number using the dial pad or type it directly
4. Click the **call button** (green phone icon)

<figure><img src="/files/RnQZGMLWH8SSJ2XbZ4qD" alt="" width="375"><figcaption><p>Enter a number on the keypad and dial</p></figcaption></figure>
{% endtab %}

{% tab title="From Contacts Page" %}
**Dial from the Contacts page**

1. Go to the **Contacts** page in the main navigation
2. Find the contact you want to call
3. Click the **phone icon** in the row actions
4. The dialer widget opens and initiates the call

<figure><img src="/files/k0ZsM0tKUWkAqlxpeBWq" alt="" width="563"><figcaption><p>One-click calling from the contacts table</p></figcaption></figure>
{% endtab %}
{% endtabs %}

#### Smart Caller ID Selection

When you dial a number, the dialer automatically selects the best caller ID (the "From" number) using smart logic:

1. **Sticky sender:** If you've called this contact before, the dialer uses the same tracking number from the last call. This ensures the contact sees a familiar number when you call back.
2. **First available:** If this is a new contact with no call history, the dialer uses the first tracking number in your workspace.

**Manual override:** You can also select a specific tracking number from the caller ID dropdown at the top of the dialer. Your selection is saved locally and used for all subsequent calls until you change it.

<figure><img src="/files/iI08ggKGtOxPXKQxQoJg" alt="" width="563"><figcaption><p>Select a caller ID from the dropdown or let smart selection choose automatically</p></figcaption></figure>

{% hint style="success" %}
**Best Practice:** Let smart caller ID handle selection automatically. This keeps your outbound number consistent per contact, which improves answer rates since the contact recognizes the number.
{% endhint %}

#### During an Active Call

When a call connects, the dialer switches to the active call view:

<figure><img src="/files/oNSmZZZx0aIT9OnV8MXv" alt=""><figcaption><p>Active call view with call controls and context sidebar</p></figcaption></figure>

**Call controls:**

| Control     | Action                                                               |
| ----------- | -------------------------------------------------------------------- |
| **Mute**    | Toggle your microphone on/off                                        |
| **Keypad**  | Open DTMF keypad for touch-tone input (e.g., navigating phone menus) |
| **Hang Up** | End the call                                                         |

**Context sidebar:** When a call starts, a sidebar slides in from the left showing:

* Contact name, email, company
* Tags and lead status
* Call statistics (total calls, last call date, average duration)
* Deal value
* Recent call history with this contact

This gives agents full context about who they're talking to without leaving the call.

#### Receiving Inbound Calls

When a customer calls one of your tracking numbers and you're **Online**, the dialer automatically expands and shows an incoming call notification:

The notification shows:

* **Caller's phone number** (formatted)
* **Caller's name** (if available from CNAM lookup or existing contact)
* **Tracking number called** (which number the customer dialed)
* **Campaign name** (if the tracking number is assigned to a campaign)

**Answering:**

* Click **Answer** (green button) to pick up the call
* Click **Reject** (red button) to decline

{% hint style="info" %}
**Multi-agent routing:** All online agents in the workspace hear the ring simultaneously. The first agent to click Answer gets the call. Once answered, all other agents' ringing stops immediately.
{% endhint %}

{% hint style="info" %}
**Page refresh safe:** If you refresh the page while a call is ringing, the incoming call notification persists and you can still answer it.
{% endhint %}

#### Recent Calls Tab

The **Recents** tab in the dialer shows your personal call history — only calls you've made or answered. Each entry shows:

* Contact name or phone number
* Call direction (inbound/outbound icon)
* Call duration
* Time of the call

Click any entry to quickly redial that number.

***

### Contacts & Auto-Creation

The dialer is deeply integrated with Ring Tonic's contact management system. Contacts are automatically created from calls so you never lose track of who called or who you called.

#### How Contacts Are Auto-Created

Every time a call happens, Ring Tonic checks if a contact already exists for that phone number in your workspace:

* **If a contact exists:** The call is linked to that contact.
* **If no contact exists:** A new contact is automatically created with the phone number, and the call is linked to it. The source is set to "call."

This happens for both inbound and outbound calls, so your contact list grows organically as you use the dialer.

{% hint style="success" %}
**No manual entry needed:** You don't need to create a contact before making a call. Just dial the number and Ring Tonic handles the rest.
{% endhint %}

#### From Call to Contact: Lead Conversion

After a call, you can enrich the auto-created contact with business information:

1. Open the contact (from the **Contacts** page or from the dialer's context sidebar)
2. Add details like **name**, **email**, **company**, and **notes**
3. Update the **lead status** to track where they are in your pipeline:

| Lead Status      | Meaning                           |
| ---------------- | --------------------------------- |
| **New**          | Just created, not yet evaluated   |
| **Contacted**    | You've spoken with them           |
| **Qualified**    | Meets your qualification criteria |
| **Disqualified** | Does not meet your criteria       |

4. Set a **deal value** to track potential revenue
5. Add **tags** for categorization (e.g., "Hot Lead", "Follow Up", "Enterprise")
6. Set a **next follow-up date** to schedule your next action

<figure><img src="/files/LyTGQCeBnEkLWsaRudU2" alt=""><figcaption><p>Contact detail sheet with lead information and call history</p></figcaption></figure>

{% hint style="info" %}
**AI automation:** If you have OpenAI configured in your workspace, Ring Tonic can automatically analyze each **call log** — qualifying leads, estimating deal values, extracting keywords, and tagging calls based on the conversation. These AI insights live on the call log, not the contact. The one exception is **caller name detection**, which updates the contact's name automatically. To sync a call's qualification status to the contact, manually qualify the call log within 24 hours and it will update the linked contact's lead status. See [Setup Workspace](/guides/setup-workspace) for AI configuration.
{% endhint %}

***

### Contacts vs. Call Logs: Understanding the Difference

Ring Tonic stores information in two places — the **Contact** and individual **Call Logs**. This is intentional and important for accurate reporting. Think of it as **"Master vs. Snapshot"**:

* **Contact** = the **current truth** about a person ("John is a Qualified Lead worth $5,000 right now")
* **Call Log** = a **historical snapshot** of a specific interaction ("On Feb 1st, Agent Mike qualified John and attributed $5,000 to this call")

This separation is what lets you answer questions like "How much revenue did Agent Mike generate last week?" — something you can't answer from the Contact alone because the value may have changed since then.

#### Field-by-Field Breakdown

| Field           | On Contact (Master)                                                                         | On Call Log (Snapshot)                                                                    |
| --------------- | ------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| **Deal Value**  | Total pipeline value for this person                                                        | Attribution — the value generated by this specific call                                   |
| **Lead Status** | The person's status right now                                                               | The outcome of that specific interaction                                                  |
| **Notes**       | Contextual notes about the person (e.g., "Gatekeeper is Susan. Best time to call is 2 PM.") | Transactional notes about what happened on the call (e.g., "Customer asked for a refund") |
| **Tags**        | Categorize the person (e.g., "VIP", "Enterprise")                                           | Categorize the call (e.g., "Ready to Buy", "Needs Quote")                                 |

#### Why Lead Status Exists in Both Places

Consider this scenario:

1. **Monday:** Agent A calls John, marks the call as **Qualified**. The contact's status becomes Qualified.
2. **Tuesday:** Agent B calls John, realizes it was a mistake, marks the call as **Junk**. The contact's status becomes Junk.

Without the call log snapshot, Agent A's work on Monday would be invisible. The call log preserves that Agent A correctly qualified a lead — even though the contact's status changed later. This is essential for fair performance reporting.

#### How Notes Work

Contact notes and call log notes serve different purposes and are displayed separately:

* **Contact notes** appear pinned at the top of the contact sidebar — these are persistent, contextual details about the person that every agent should see
* **Call log notes** appear in the activity timeline alongside each call — these describe what happened during that specific conversation

{% hint style="success" %}
**Best Practice:** Use contact notes for information that's always relevant (preferences, best times to call, decision-maker details). Use call log notes for what happened during the call (requests made, issues raised, follow-up commitments).
{% endhint %}

***

### Managing Contacts

The **Contacts** page gives you a full view of all contacts in your workspace, whether auto-created from calls or manually added.

#### Viewing Contacts

1. Go to **Contacts** in the main navigation
2. Browse the table with columns for name, phone, company, lead status, deal value, call count, and last contact date
3. Use **search** to find contacts by name, phone, or email
4. Use **sorting** on any column to organize your list

<figure><img src="/files/4kjvLf4bZJLMldCgAH6z" alt=""><figcaption><p>Contacts page with searchable, sortable table</p></figcaption></figure>

#### Creating a Contact Manually

1. Go to **Contacts**
2. Click **Add Contact**
3. Enter at least a **phone number** (required)
4. Optionally fill in name, email, company, notes, lead status, and deal value
5. Click **Create**

{% hint style="info" %}
Phone numbers are automatically normalized to E.164 format (e.g., +12125551234). You can enter them in any common format and Ring Tonic will handle the conversion.
{% endhint %}

#### Editing a Contact

1. Click on any contact row to open the **Contact Detail Sheet**
2. Click on any field to edit it inline (name, email, company, etc.)
3. Changes are saved automatically

The detail sheet also shows:

* **Recent calls** with this contact (paginated)
* **Call statistics** (total calls, last call, average duration)
* **Tags** with autocomplete suggestions

#### Bulk Actions

Select multiple contacts using the checkboxes to perform bulk operations:

| Action                 | Description                                  |
| ---------------------- | -------------------------------------------- |
| **Add Tags**           | Apply one or more tags to selected contacts  |
| **Remove Tags**        | Remove specific tags from selected contacts  |
| **Update Lead Status** | Change lead status for all selected contacts |
| **Delete**             | Remove selected contacts from the workspace  |

***

### How It All Fits Together

Here's the complete workflow from setup to daily use:

{% stepper %}
{% step %}
**Set Up the Workspace**

Enable the dialer, add your Twilio API Key, and ensure you have tracking numbers imported. This is a one-time setup.
{% endstep %}

{% step %}
**Invite Your Agents**

Invite team members with the **Agent** role. They'll see the dialer widget as soon as they log in.
{% endstep %}

{% step %}
**Agents Go Online**

Agents set their status to **Online** to start receiving inbound calls. The dialer connects to Twilio and listens for calls in real-time.
{% endstep %}

{% step %}
**Make and Receive Calls**

Agents dial from contacts, the keypad, or the contacts page. Inbound calls ring all online agents simultaneously — first to answer gets the call.
{% endstep %}

{% step %}
**Contacts Are Auto-Created**

Every call automatically creates or links to a contact. Agents see full context (call history, lead status, tags) during the call via the context sidebar.
{% endstep %}

{% step %}
**Qualify and Follow Up**

After calls, agents update contact details, set lead status, add tags, and schedule follow-ups. If AI automation is configured, call logs are automatically qualified, tagged, and estimated with deal values — agents can then review and sync those insights to the contact.
{% endstep %}
{% endstepper %}

***

### Troubleshooting

<details>

<summary>Dialer widget is not showing up</summary>

**Possible causes:**

* Your role is not Agent, Admin, or Owner — ask an admin to change your role
* The dialer is not enabled — go to Workspace Settings → Dialer tab and enable it
* Twilio credentials are missing — check that Account SID and Auth Token are configured in the Basic tab
* API Key is missing — check that API Key SID and Secret are configured in the Dialer tab

</details>

<details>

<summary>"Dialer not ready" warning in workspace settings</summary>

**Problem:** Ring Tonic couldn't create the TwiML Application in your Twilio account.

**Solution:**

1. Verify your Account SID and Auth Token are correct in the Basic tab
2. Make sure your Twilio account is active (not suspended)
3. Save the workspace settings again — Ring Tonic will retry provisioning

</details>

<details>

<summary>No audio during calls</summary>

**Possible causes:**

* Browser microphone permission not granted — click the lock icon in your browser's address bar and allow microphone access
* Wrong audio device selected — click the settings icon in the dialer to select the correct microphone and speaker
* Browser audio blocked — interact with the page (click anywhere) to unlock audio playback, especially on Safari/iOS

</details>

<details>

<summary>Incoming calls not ringing</summary>

**Possible causes:**

* Your status is not Online — change it to Online in the dialer status dropdown
* Heartbeat timed out — refresh the page to reconnect
* Browser tab is in background — some browsers throttle background tabs; keep Ring Tonic in a visible tab

</details>

<details>

<summary>Cannot make outbound calls</summary>

**Possible causes:**

* No tracking numbers in the workspace — import at least one number from Twilio
* API Key not configured — add your Twilio API Key SID and Secret in the Dialer tab
* Phone number format invalid — ensure you're entering a valid phone number with country code

</details>

<details>

<summary>Agent shows as Offline unexpectedly</summary>

**Problem:** The heartbeat connection was lost.

**Solution:**

1. Refresh the page — the dialer will reconnect and restore your intended status
2. Check your internet connection
3. If the issue persists, your browser may be aggressively throttling background tabs — keep Ring Tonic as your active tab

</details>

<details>

<summary>Call connected but no one can hear each other</summary>

**Problem:** WebRTC connection issue.

**Solution:**

1. Check that your firewall allows WebRTC traffic
2. Try a different browser (Chrome is recommended)
3. Disable VPN if active — VPNs can interfere with real-time audio
4. Check the audio device settings in the dialer (gear icon)

</details>

<details>

<summary>Smart caller ID picking the wrong number</summary>

**Problem:** The sticky sender logic is using a number from an old call.

**Solution:**

* Manually select the desired tracking number from the caller ID dropdown
* Your manual selection is saved and used for all future calls until you change it

</details>


# AWS S3 External Storage

<figure><img src="/files/o2JObGYaDuCxG8wAXA7v" alt=""><figcaption><p>AWS S3 External Storage</p></figcaption></figure>

Store your call recordings and voicemails in your own AWS S3 bucket instead of Twilio's servers. This gives you full ownership of your audio data, faster playback, and enables HIPAA-compliant workflows for healthcare organizations.

{% hint style="info" %}
**Your Data, Your Bucket:** When you enable S3 storage, Ring Tonic migrates recordings from Twilio to your S3 bucket and then removes them from Twilio. Once migrated, audio streams directly from your bucket via secure signed URLs.
{% endhint %}

***

### Why Use Your Own S3 Bucket?

| Benefit                 | Description                                                                    |
| ----------------------- | ------------------------------------------------------------------------------ |
| **Faster Playback**     | Audio streams directly from S3 to your browser via signed URLs—no middleman    |
| **Lower Storage Costs** | S3 costs $0.023/GB vs Twilio's $0.0005/min ($0.03/GB at typical bitrates)      |
| **Data Ownership**      | You own the raw audio files in your own AWS account                            |
| **HIPAA Compliance**    | Required for healthcare—keeps PHI off third-party servers                      |
| **Flexible Archival**   | Use S3 Lifecycle Rules to automatically move old recordings to cheaper storage |

{% hint style="success" %}
**Performance Boost:** With S3, the audio player loads recordings directly from your bucket using signed URLs. This is faster than streaming through Twilio's servers because it eliminates an extra network hop.
{% endhint %}

***

### How It Works

```
┌─────────────┐      ┌─────────────┐      ┌─────────────┐      ┌─────────────┐
│  Caller     │──────│  Twilio     │──────│  Ring Tonic │──────│  Your S3    │
│  calls your │      │  records    │      │  downloads  │      │  bucket     │
│  tracking # │      │  the call   │      │  & uploads  │      │  (you own)  │
└─────────────┘      └─────────────┘      └─────────────┘      └─────────────┘
                                                 │
                                                 ▼
                                          ┌─────────────┐
                                          │  Twilio     │
                                          │  recording  │
                                          │  deleted    │
                                          └─────────────┘
```

1. **Call comes in** → Twilio records the conversation
2. **Recording ready** → Twilio notifies Ring Tonic when recording is available
3. **Migration** → Ring Tonic downloads from Twilio and uploads to your S3 bucket
4. **Cleanup** → After successful upload, Twilio recording is deleted to avoid double storage costs
5. **You play recordings** → Audio streams directly from S3 via secure signed URLs

***

### Setup Guide

{% stepper %}
{% step %}
**Create an S3 Bucket**

<figure><img src="/files/3g09rPr7yWV0mS7mbkk6" alt=""><figcaption><p>Create a S3 bucket</p></figcaption></figure>

1. Log in to [AWS Console](https://console.aws.amazon.com/)
2. Go to **S3** → **Create bucket** (If you cannot find S3, search using the header search bar)
3. Enter a bucket name (e.g., `yourcompany-call-recordings`)
4. Select your preferred region (e.g., `us-east-1`)
5. Keep **Block all public access** enabled
6. Click **Create bucket**

{% hint style="warning" %}
**Keep it private.** Your bucket should NOT be public. Ring Tonic uses secure signed URLs that expire after 60 minutes.
{% endhint %}
{% endstep %}

{% step %}
**Create an IAM Policy**

First, create a policy that grants access to your bucket.

<figure><img src="/files/4hfuIaj9qGf4Vrge8JYV" alt=""><figcaption></figcaption></figure>

1. Go to **IAM** → **Policies** → **Create policy**
2. **Select a service:** S3

<figure><img src="/files/SFULLHtb3EGE29AsBDqS" alt=""><figcaption></figcaption></figure>

3. Click the **JSON** tab and paste:

```json
{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Effect": "Allow",
         "Action": [
            "s3:GetObject",
            "s3:PutObject",
            "s3:DeleteObject",
            "s3:ListBucket"
         ],
         "Resource": [
            "arn:aws:s3:::YOUR-BUCKET-NAME",
            "arn:aws:s3:::YOUR-BUCKET-NAME/*"
         ]
      },
      {
         "Effect": "Allow",
         "Action": [
            "s3:GetBucketCors",
            "s3:PutBucketCors"
         ],
         "Resource": "arn:aws:s3:::YOUR-BUCKET-NAME"
      }
   ]
}
```

{% hint style="info" %}
**DeleteObject Permission:** This allows Ring Tonic to clean up S3 recordings when call logs are deleted (if enabled in workspace settings).
{% endhint %}

4. Replace `YOUR-BUCKET-NAME` with your actual bucket name that you created in step 1
5. Click **Next** → Name it `RingTonicS3Access` → **Create policy**
   {% endstep %}

{% step %}
**Create an IAM User**

Now create a user and attach the policy.

1. Go to **IAM** → **Users** → **Create user**
2. Enter a name: `ringtonic-s3-access` → Click **Next**
3. Select **Attach policies directly**
4. Search for `RingTonicS3Access` and check the box
5. Click **Next** → **Create user**
6. Open the user → **Security credentials** tab
7. Click **Create access key** → Select **Third-party service**
8. Click **Create access key** → **Save both keys**

{% hint style="warning" %}
**Save your keys now.** The Secret Access Key is only shown once. Store it in a password manager.
{% endhint %}
{% endstep %}

{% step %}
**Configure Ring Tonic**

<figure><img src="/files/YtleEZdQfSktWLs4cSUe" alt="" width="563"><figcaption><p>Setup Storage in Ring Tonic</p></figcaption></figure>

1. Go to **Workspace Settings** → **Storage** tab
2. Enable **S3 External Storage**
3. Enter your credentials:
   * **Access Key ID:** From IAM user
   * **Secret Access Key:** From IAM user
   * **Bucket Name:** Your S3 bucket name
   * **Region:** Must match your bucket (e.g., `us-east-1`)

![](/files/qqbCnAfHicqGPLKg7j1H)

4\. Click **Test Connection**

5\. Click **Save**

6\. After saving, two **Deletion Settings** toggles appear at the bottom of the tab. Both default to safe values — see [Deletion Settings](#deletion-settings) below for what each one does.

{% hint style="info" %}
**Automatic Setup:** When you test the connection, Ring Tonic automatically configures CORS on your bucket so recordings can play in the browser.
{% endhint %}
{% endstep %}

{% step %}
**Migrate Existing Recordings (Optional)**

If you have existing recordings stored in Twilio:

1. Go to **Workspace Settings** → **Storage** tab
2. Click **Migrate Existing Recordings**
3. Migration runs in the background—large accounts may take several hours

{% hint style="info" %}
**Twilio cleanup is automatic.** As each recording is uploaded to S3, the original copy on Twilio is deleted in the background (unless you've turned that off in **Deletion Settings**). You don't need to do anything else to avoid double storage costs.
{% endhint %}
{% endstep %}
{% endstepper %}

***

### Deletion Settings

Once S3 is configured, two independent toggles appear at the bottom of the **Storage** tab. They control different things — make sure you know which is which.

<figure><img src="/files/rQCDASb0aHXnTv6aC5vA" alt=""><figcaption><p>The two Deletion Settings toggles in the Storage tab</p></figcaption></figure>

#### Delete Twilio copy after migration

**Default: ON.** Controls what happens to the original Twilio recording once Ring Tonic finishes copying it to your S3 bucket.

| Setting              | What happens                                                                                           |
| -------------------- | ------------------------------------------------------------------------------------------------------ |
| **ON (recommended)** | After a recording is safely on S3, the Twilio copy is deleted. You only pay for storage in one place.  |
| **OFF**              | The recording lives in **both** Twilio and your S3 bucket. You'll be billed for storage on both sides. |

Most people want this ON — it's the whole point of bringing your own bucket. Turn it OFF only if you have a specific reason to keep redundant copies on Twilio (e.g. a compliance policy that mandates dual storage).

{% hint style="info" %}
**Safe by design.** Deletion is retried up to 3 times with backoff if Twilio is temporarily unreachable, and the link to the Twilio recording in Ring Tonic's database is only cleared after Twilio confirms the deletion. A transient failure won't orphan your recording.
{% endhint %}

#### Delete S3 files when call logs are deleted

**Default: OFF.** Controls what happens to the S3 file when you delete a call log inside Ring Tonic.

| Setting           | What happens                                                                                                                           |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| **OFF (default)** | Deleting a call log removes it from Ring Tonic only. The recording stays in your S3 bucket — you can still access it directly via AWS. |
| **ON**            | Deleting a call log also removes the corresponding audio file from your S3 bucket. **Files cannot be recovered.**                      |

This is unrelated to the toggle above. It's a separate question: "when I delete a call log in my dashboard, should the S3 file go too?" The answer depends on whether you treat S3 as an archive (keep it OFF) or as the single source of truth tied to your dashboard (turn it ON).

{% hint style="danger" %}
Turning this ON makes call-log deletion permanent. If you also use the API or bulk-delete tools to clean up call logs, those deletions will erase the corresponding S3 files too.
{% endhint %}

***

### HIPAA Compliance

For healthcare organizations handling Protected Health Information (PHI), Ring Tonic's architecture supports HIPAA-compliant workflows.

#### How We Handle Compliance

| Area                             | How It's Protected                                                                                                                     |
| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| **Telephony (BAA)**              | You connect your own Twilio account and execute a BAA directly with Twilio. The transmission layer stays under your legal umbrella.    |
| **Call Recordings & Voicemails** | With S3 External Storage, recordings are migrated from Twilio to your bucket. After migration, audio is stored only in your S3 bucket. |
| **Database**                     | All call logs and metadata are encrypted at rest.                                                                                      |

{% hint style="success" %}
**The Key Difference:** Because of our "Bring Your Own Key" architecture, you retain full legal ownership of raw call data. After migration, we only store metadata and references—recordings live exclusively in your S3 bucket.
{% endhint %}

{% hint style="info" %}
**Need a BAA?** Contact [Twilio Sales](https://www.twilio.com/en-us/hipaa) and [AWS](https://aws.amazon.com/compliance/hipaa-compliance/) to execute Business Associate Agreements if you handle PHI.
{% endhint %}

***

### Storage Costs & Lifecycle Rules

S3 storage is billed directly by AWS.

| Storage Class               | Cost                | Retrieval   | Best For                      |
| --------------------------- | ------------------- | ----------- | ----------------------------- |
| **S3 Standard**             | \~$0.023/GB/month   | Instant     | Recent recordings (< 90 days) |
| **S3 Glacier Instant**      | \~$0.004/GB/month   | Instant     | Older recordings (90+ days)   |
| **S3 Glacier Deep Archive** | \~$0.00099/GB/month | 12-48 hours | Long-term archival (1+ years) |

#### What Are Lifecycle Rules?

S3 Lifecycle Rules automatically move files to cheaper storage classes as they age. For example:

* **Day 0-90:** Recording stays in S3 Standard (fast access)
* **Day 91-365:** Automatically moves to Glacier Instant (80% cheaper, still instant access)
* **After 1 year:** Moves to Deep Archive (95% cheaper, slower retrieval)

This saves money without manual intervention—old recordings you rarely access cost almost nothing to store.

{% hint style="success" %}
**Example:** 1,000 calls/month × 3 min average × 1 MB/min = 3 GB/month. With lifecycle rules, annual storage costs under $5.
{% endhint %}

***

### Common Questions

<details>

<summary>Do I need S3 for Ring Tonic to work?</summary>

No. S3 storage is optional. By default, recordings and voicemails are stored in Twilio. S3 is recommended for faster playback, HIPAA compliance, or cost optimization at scale.

</details>

<details>

<summary>How long does Twilio store recordings?</summary>

Twilio stores recordings indefinitely unless you delete them. The first 10,000 minutes are free; after that, Twilio charges $0.0005 per minute per month. With S3, you pay AWS directly at typically lower rates.

</details>

<details>

<summary>Are recordings encrypted in S3?</summary>

Yes. Enable S3 Server-Side Encryption (SSE-S3 or SSE-KMS) on your bucket. Data in transit is always encrypted via HTTPS.

</details>

<details>

<summary>How long are signed URLs valid?</summary>

60 minutes. Each time you play a recording, a fresh signed URL is generated. This prevents sharing via leaked URLs.

</details>

<details>

<summary>Can I use other S3-compatible storage?</summary>

Yes. Enter the custom endpoint URL in the **Endpoint** field. Ring Tonic supports MinIO, DigitalOcean Spaces, and other S3-compatible providers.

</details>

<details>

<summary>What happens if I disable S3 storage later?</summary>

Existing S3 recordings remain accessible. New recordings will be stored in Twilio. You can re-enable S3 anytime.

</details>

<details>

<summary>Are S3 recordings deleted when I delete call logs?</summary>

Only if you turn it on. In **Workspace Settings** → **Storage** → **Deletion Settings**, toggle "Delete S3 files when call logs are deleted." When ON, deleting a call log (individually, via campaign deletion, or workspace deletion) also removes the corresponding recording from your S3 bucket. When OFF (the default), recordings stay in S3 even after the call log is gone.

</details>

<details>

<summary>What happens to Twilio recordings after migration?</summary>

With the **Delete Twilio copy after migration** toggle ON (the default), Ring Tonic deletes the Twilio copy as soon as the recording is safely on S3 — so you don't pay for storage on both sides. The deletion is retried automatically if Twilio is temporarily unavailable. With the toggle OFF, the Twilio copy is kept and you'll be billed for storage in both places.

</details>

<details>

<summary>What's the difference between the two Deletion Settings toggles?</summary>

They control completely different things:

* **Delete Twilio copy after migration** — about avoiding **duplicate storage** the moment a recording is migrated. ON by default. Most people want it on.
* **Delete S3 files when call logs are deleted** — about whether deleting a call log in your Ring Tonic dashboard also wipes the file from S3. OFF by default. Turn it on only if you want call-log deletion to be permanent.

The first runs once per recording, right after migration. The second runs whenever you (or your team, or the API) deletes a call log. See the [Deletion Settings](#deletion-settings) section above for the full breakdown.

</details>

<details>

<summary>Do I need to enable anything on Twilio to avoid duplicate storage?</summary>

No. With the **Delete Twilio copy after migration** toggle ON (the default), Ring Tonic handles cleanup automatically — you don't need to configure anything on the Twilio side. Twilio's account-level "External S3 Storage" feature is still an option if you want recordings to land directly in your bucket without ever touching Twilio's servers, but it's no longer required to prevent duplicates.

</details>


# Google Ads Integration

Push offline conversions from your Ring Tonic funnel back to Google Ads so Smart Bidding actually knows which clicks turn into customers. When a lead in Ring Tonic reaches a mapped stage (e.g. **Won**), Ring Tonic uploads a conversion to your chosen Google Ads conversion action — with hashed identifiers, the originating click ID, and the deal value.

<figure><img src="/files/akJhlp0wF4Oh676kOiVg" alt=""><figcaption><p>Google Ads integration page — connected and healthy</p></figcaption></figure>

{% hint style="info" %}
This integration uses Google Ads' **Enhanced Conversions for Leads (ECL)**. We only ever *upload* conversions — we never touch your campaigns, ad groups, bids, or budgets.
{% endhint %}

***

### What This Solves

Without this integration, Google Ads optimizes toward shallow signals (clicks, form submits) because it has no idea which submissions became paying customers. With it, Google sees the full funnel:

```
Google Ads click  →  Visitor on your site (Ring Tonic tracking)
                              ↓
                     Call / form submission
                              ↓
                       Lead in Ring Tonic
                              ↓
                   Funnel: New → Qualified → Won
                              ↓
                  Ring Tonic uploads to Google Ads:
                  hashed(email/phone) + gclid + value
                              ↓
                Smart Bidding learns: "this keyword
                actually drives paying customers"
```

Net effect: same ad budget, more closed deals, lower cost per closed customer.

***

### Prerequisites

Before connecting, make sure your Google Ads account has all of these:

| Requirement                                                 | Where to set it                                                                                                      |
| ----------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| **Customer data terms accepted**                            | Google Ads → *Tools → Conversions → Settings → Customer data terms* — only an **Admin** on the account can accept    |
| **Enhanced conversions for leads enabled**                  | Google Ads → *Tools → Conversions → Settings → Enhanced conversions for leads* — toggle on                           |
| **At least one lead-type conversion action**                | Google Ads → *Tools → Conversions → Goals* — categories like "Submit lead form", "Phone call lead", "Qualified lead" |
| **Admin or Standard access** for the Google user connecting | Google Ads → *Tools → Admin → Access and security*                                                                   |

{% hint style="warning" %}
**Customer data terms acceptance is a Google-side gate.** If the account isn't set up, Ring Tonic can still connect — but the health check will show **TermsNotAccepted** and you won't be able to create mappings until the Admin accepts the terms inside Google Ads.
{% endhint %}

***

### Connecting Your Google Ads Account

{% stepper %}
{% step %}

#### Navigate to the Integration

Go to **Settings → Google Ads** in Ring Tonic (it's in the Settings sidebar).

<figure><img src="/files/9NkLCpYr8z1ZOzgYe4SN" alt=""><figcaption><p>Google Ads integration page, before connecting</p></figcaption></figure>
{% endstep %}

{% step %}

#### Start the OAuth Flow

Click **Connect**. You'll be redirected to Google's consent screen, signed in with the Google account you want to grant access from.

Review the requested permission:

> **See, edit, create, and delete your Google Ads accounts and data.**

This is the standard `adwords` scope — required for uploading conversions. We don't request any other Google scopes.

Click **Continue** to authorize.

<figure><img src="/files/8rfSS6Vl50GFMvDGEHbv" alt=""><figcaption><p>Google OAuth consent screen</p></figcaption></figure>
{% endstep %}

{% step %}

#### Pick an Account

Ring Tonic lists every Google Ads customer the signed-in user can access. Manager accounts are tagged **\[MCC]**, and sub-customers reached through a manager show the manager ID in the row.

Pick the customer account you want to bind to this workspace, then click **Bind account**.

<figure><img src="/files/2zbejSPhCmUFYxj8tGds" alt=""><figcaption><p>Account picker showing accessible Google Ads customers</p></figcaption></figure>

{% hint style="info" %}
**One Google Ads account per workspace.** If you manage multiple advertisers, each one should have its own Ring Tonic workspace with its own Google Ads binding. This keeps mappings and upload attempts cleanly scoped.
{% endhint %}
{% endstep %}

{% step %}

#### Health Check Runs Automatically

The moment you bind, Ring Tonic queries Google to confirm the account is ready for uploads. The result appears on the integration page — see the [Health Check](#health-check) section below for what each status means.
{% endstep %}
{% endstepper %}

***

### Health Check

The health check verifies that the connected account satisfies Google's prerequisites for Enhanced Conversions for Leads. It runs:

* Immediately after **Bind account**
* When you click **Re-check** on the integration page
* Daily at midnight UTC (background job)
* Just before any upload, if the cached result is stale (>36h)

| Status               | Meaning                                                                         | What to do                                                                                                         |
| -------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| **Ok**               | Terms accepted, ECL enabled. Uploads will go through.                           | Nothing — you're ready to create mappings                                                                          |
| **TermsNotAccepted** | Customer data terms haven't been accepted on this Google Ads account            | An **Admin** on the Google Ads account must accept terms at *Tools → Conversions → Settings → Customer data terms* |
| **EclDisabled**      | Enhanced conversions for leads is off                                           | An Admin must toggle it on at *Tools → Conversions → Settings → Enhanced conversions for leads*                    |
| **Error**            | Google API call failed (developer token issue, account suspended, network blip) | Click Re-check after a few minutes. If it persists, see [Common Issues](#common-issues)                            |

{% hint style="warning" %}
**Lead and click mappings are gated by health.** While health is anything other than **Ok**, the lead and click mapping editor is disabled and any pending upload jobs skip with `skipped_health_check_failed`. As soon as health goes green and you click Re-check, future uploads resume normally.
{% endhint %}

{% hint style="info" %}
**Call conversion mappings are gated differently.** The customer data terms and enhanced conversions requirements exist to protect customer details, which imported call conversions don't contain — so **TermsNotAccepted** and **EclDisabled** don't block them. See [Calls from Google Ads Call Assets](#calls-from-google-a-ds-call-assets).
{% endhint %}

***

### Default Consent

Google's Consent Mode requires you to send a consent signal for every conversion upload. Ring Tonic resolves consent per upload using this priority:

```
1. Consent attached to the originating form submission
2. Consent from the visitor's session (set by the tracking script)
3. Workspace-level defaults (this section)
```

If neither the form nor the visitor session carries an explicit consent value, Ring Tonic falls back to the workspace defaults set on the integration page. (An `Unspecified` signal from a form or pageview is treated as "no signal" — only an explicit `Granted` / `Denied` overrides these defaults.)

<figure><img src="/files/gGOLDUReaMLXDNTWA0v9" alt=""><figcaption><p>Workspace-level default consent — the fallback when no explicit signal is captured</p></figcaption></figure>

| Signal                 | What it means                                                                       | Recommended default                                                   |
| ---------------------- | ----------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
| **Ad user data**       | Whether Google can use this conversion to associate with the user's ad interactions | `Granted` if your privacy policy + cookie banner cover ad measurement |
| **Ad personalization** | Whether Google can use this conversion for personalized advertising                 | `Denied` unless you explicitly collect consent for personalization    |

{% hint style="info" %}
Whatever the *resolved* `ad_user_data` value is, if it's **Denied**, Ring Tonic skips the upload entirely (records `skipped_consent_denied`). The conversion never reaches Google, in line with Consent Mode policy.
{% endhint %}

***

### Enhanced Conversions: Name and Address

Email and phone aren't the only ways Google can match a lead back to a click. Google can also match on the lead's **name and mailing address**. Sending these extra details raises your match rate — more of your leads get tied to the click that produced them — which gives Smart Bidding a cleaner signal. It's optional, and everything is hashed before it leaves Ring Tonic.

<figure><img src="/files/pgFneWsSBrndtTwIz7ww" alt=""><figcaption><p>Enhanced conversions name &#x26; address — map each address component to one of your custom fields</p></figcaption></figure>

Where the data comes from:

* **First and last name** are derived automatically from the contact's name — no setup needed.
* **Street, city, state/region, postal code, and country** come from your [workspace custom fields](/guides/contacts#custom-fields). You choose which custom field feeds each component.

{% stepper %}
{% step %}

#### Capture the details on your forms

Create custom fields for the address details you collect (for example `zip` and `country`) and capture them on your lead forms. See [Form Submissions](/guides/form-submissions) for how form inputs map to custom fields.
{% endstep %}

{% step %}

#### Map each component

On **Settings → Google Ads**, open the **Enhanced conversions: name & address** section. For each component — Street address, City, State / region, Postal code, Country — pick the custom field that holds that value. Leave anything you don't collect set to **— not mapped —**.

Only text and single-select custom fields appear in the dropdowns, since address values need to be plain values.

Click **Save address mapping**.
{% endstep %}
{% endstepper %}

{% hint style="warning" %}
**Google only accepts a complete address.** For any address to be sent, the contact must have a first name, last name, postal code, **and** country. If any of those is missing, Ring Tonic sends email/phone only and skips the address for that upload — Google ignores a partial address, so there's no benefit to sending one.
{% endhint %}

{% hint style="info" %}
**Country must be recognizable.** Enter countries as two-letter codes (`US`, `GB`) or common names (`United States`, `United Kingdom`). Ring Tonic converts recognized values to the format Google expects; anything it can't recognize is skipped for that contact.
{% endhint %}

***

### Mapping Stages to Conversion Actions

A mapping says: *"When a contact in this workspace reaches stage X, upload a conversion to this Google Ads conversion action."* Open them from the integration page via **Configure mappings** (breadcrumb: **Settings → Google Ads → Mappings**).

{% stepper %}
{% step %}

#### Pick a Stage

The dropdown shows every Ring Tonic funnel stage that's eligible for upload. `new` is excluded because it's the entry point — only progress through the funnel triggers uploads.

Common picks:

* **Qualified** — lead has been validated by sales
* **Appointment booked** — committed buying intent
* **Won** — the deal closed for actual revenue
  {% endstep %}

{% step %}

#### Pick a Conversion Action

Ring Tonic queries Google Ads and lists every lead-category conversion action in the connected account. Pick the one that should receive uploads for the chosen stage.

<figure><img src="/files/ywVpuvcvVn7YqGFsehXv" alt=""><figcaption><p>Mapping editor — each funnel stage maps to a Google Ads conversion action, with currency and an enable toggle</p></figcaption></figure>

{% hint style="info" %}
**Use distinct conversion actions per stage.** Creating one action for "Qualified Lead" and another for "Closed Deal" lets Google attribute different value to each step in the funnel. Mapping multiple stages to the same action collapses that signal.
{% endhint %}
{% endstep %}

{% step %}

#### Set Value and Currency (Optional)

If you've set a default value on the conversion action in Google Ads, leave this empty and Ring Tonic uses the contact's `deal_value`. If you want to override, enter a fixed value + ISO 4217 currency code.

{% hint style="warning" %}
**Value semantics.** For dynamic per-deal values, leave the mapping value blank and make sure your funnel sets `deal_value` (via form value rules, the Contacts UI, or the CRM Postback API). Ring Tonic will use that. For flat-value events (e.g. "every qualified lead = $50"), enter the value here.
{% endhint %}
{% endstep %}

{% step %}

#### Save

Click **Save mapping**. From this point, every contact that crosses this stage triggers a queued upload. You can disable a mapping at any time without losing it — toggle **Enabled** off.
{% endstep %}
{% endstepper %}

#### Form Submitted: Every Submission or First Touch

The **Form Submitted** stage has two extra options that no other stage has, because a single lead can submit your forms more than once.

<figure><img src="/files/GfWQbueDCBPfdXbUR5M8" alt=""><figcaption><p>Form Submitted mapping with the "Upload every form submission" toggle and the optional "Repeat submissions action"</p></figcaption></figure>

* **Upload every form submission** (on by default) — upload a conversion for *every* form submission, including repeat submissions from a contact you already know. With it off, only a lead's *first* form submission uploads.
* **Repeat submissions action** (optional) — send repeat submissions to a *different* Google Ads conversion action than first-time submissions. Leave it on **Same as first-time** to send both to the same action. This lets you value a returning lead differently from a brand-new one.

{% hint style="info" %}
**Double-clicks won't inflate your numbers.** If the same contact submits again within 30 seconds — the classic double-click or accidental resubmit — Ring Tonic stores the submission but skips the duplicate upload, so a single intent is never counted twice.
{% endhint %}

#### What Gets Uploaded

Per upload, Ring Tonic sends to Google Ads:

* **Hashed user identifiers** — SHA-256 of normalized email and phone (lowercased, Gmail dot/+ canonicalization, E.164 phone). Required by ECL — at least one must be present, otherwise the upload skips with `skipped_no_identifiers`.
* **Hashed name & address** (optional) — when you've set up [Enhanced Conversions: Name & Address](#enhanced-conversions-name-and-address), the contact's name and mapped address are also hashed and sent to raise match rate. This is additive — email or phone is still required.
* **Click IDs** — `gclid` / `gbraid` / `wbraid` if captured by the tracking script when the visitor arrived. Strengthens matching.
* **Conversion action resource** — the one you mapped to the stage.
* **Value + currency** — from mapping or `deal_value`.
* **Conversion time** — when the stage transition happened.
* **Consent flags** — `ad_user_data`, `ad_personalization`.
* **Order ID** — `rt:{workspace}:{contact}:{mapping}:{event}` — Ring Tonic's deduplication key. Re-running the same event won't double-count in Google Ads.

Everything that identifies the lead is **hashed** before it leaves Ring Tonic — Google never sees a raw email, phone, name, or street address. We do **not** send: transcripts, notes, campaign data, or any custom fields other than the address components you explicitly mapped for enhanced conversions.

***

### Counting Repeat Conversions: "One" vs "Every"

When you upload every form submission, how those repeats are *counted* is controlled inside Google Ads — not Ring Tonic. Each Google Ads conversion action has a **Count** setting (Google Ads → **Goals → Conversions → your action → Count**):

| Count setting | What it does                               | When to use it                                                                                                                                                       |
| ------------- | ------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **One**       | Counts at most one conversion per ad click | Lead generation, where only unique leads matter. Google de-duplicates repeat submissions from the same click for you — even with "Upload every form submission" on.  |
| **Every**     | Counts every upload                        | When each submission has its own value (quotes, orders). Pair it with a separate **Repeat submissions action** to bid differently on first-time vs. returning leads. |

{% hint style="info" %}
Most lead-gen advertisers choose **One**: leave "Upload every form submission" on and let Google's Count setting handle de-duplication. You get complete data in Ring Tonic and clean counts in Google Ads.
{% endhint %}

***

### Calls from Google Ads Call Assets

If you run **call assets** (or call-only ads), Google shows a temporary **Google forwarding number** on your ad instead of your real number. A customer taps it, Google connects the call through to your Ring Tonic tracking number, and the call arrives — but the caller never visited your website.

That means there's no click ID and no visitor session to match on, so the lead and click uploads described above can't attribute the call. Google's answer for exactly this case is **imported call conversions**: you send the caller's number and the time the call started, and Google matches that pair against its own record of the forwarding-number call.

Ring Tonic supports this as a separate upload path, mapped and reported alongside your lead and click conversions.

{% hint style="info" %}
This is only for calls that reach a **static number campaign** through a Google forwarding number. Website Tracker campaigns swap in a tracking number for each visitor, so their calls already carry a session and click ID and stay on the lead and click path.
{% endhint %}

#### Before You Start

| Requirement                                       | Where to set it                                                                                                                           |
| ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| **Call reporting turned on**                      | Google Ads → *Tools → Conversions → Settings → Call reporting* — without it Google never assigns a forwarding number                      |
| **A call asset pointing at your tracking number** | Google Ads → your campaign → *Assets → Call*                                                                                              |
| **A conversion action for imported calls**        | Google Ads → *Goals → Conversions → New conversion action → Import → Conversions from calls*                                              |
| **A static number campaign in Ring Tonic**        | Ring Tonic → **Campaigns** — see [Campaigns](https://help.ringtonic.app/guides/pages/VdOTbPSa6hi12UUj6ZLp#id-2.-create-a-static-campaign) |

{% hint style="warning" %}
**Call reporting is what makes matching possible.** If it's off, Google puts your real number on the ad, there's no forwarding-number record to match against, and every upload comes back as **Call not found**.
{% endhint %}

#### Setting It Up

{% stepper %}
{% step %}

#### Create the conversion action in Google Ads

In Google Ads, go to **Goals → Conversions → New conversion action** and choose **Import**, then **Conversions from calls**.

Give it a clear name such as *Qualified Call (Imported)* and pick a call-related category like **Phone call lead**.

{% hint style="info" %}
Set it as a **Secondary** action first. Secondary actions are recorded and reported but never used by Smart Bidding, so you can confirm calls are matching before they influence how your budget is spent. Promote it to Primary once you're happy with the match rate.
{% endhint %}
{% endstep %}

{% step %}

#### Tell Ring Tonic the campaign receives forwarded calls

Open the static campaign in Ring Tonic and click **Edit**. In the **Google Ads Call Assets** card, tick **This number receives calls forwarded from a Google Ads call asset**, then click **Update Campaign**.

This is a deliberate opt-in. Ring Tonic can't tell from an incoming call whether it came through a forwarding number, so without the toggle it would attempt an upload for every call to every static number — including billboard and print calls that Google has no record of.

<figure><img src="/files/6M65F705FkOZSQDiN56z" alt=""><figcaption><p>The Google Ads Call Assets card on a static campaign, with the forwarding toggle enabled</p></figcaption></figure>
{% endstep %}

{% step %}

#### Map stages to your call conversion action

Go to **Settings → Google Ads → Configure mappings**. Below the lead and click table you'll find **Call conversions (Google call assets)**.

Pick the stage that should report a call conversion — **Qualified** is the usual choice — and select your imported-call action. Only conversion actions built for imported calls appear here, so you can't accidentally point a call mapping at a click action.

<figure><img src="/files/LgUNM9cAaHPXe8XdnN2j" alt=""><figcaption><p>The Call conversions table, mapping the Qualified stage to an imported-call conversion action</p></figcaption></figure>
{% endstep %}
{% endstepper %}

#### What Gets Uploaded

Imported call conversions carry far less than a lead upload, because Google matches on the call itself rather than on the person:

* **Caller's number and call start time** — the pair Google matches against its forwarding-number records
* **Conversion action** — the one you mapped to the stage
* **Value and currency** — from the mapping or the contact's deal value
* **Conversion time** — when the stage transition happened
* **Consent signal** — the ad user data signal, resolved exactly as it is for lead uploads

No email, phone hashes, name, or address is sent — this path has no use for them. The caller's number is never stored in the upload log either; you'll see it only on the call record itself, where it already lives.

#### Timing: Why a Call Conversion Isn't Instant

Google needs several hours to index a forwarding-number call before it can be matched. Ring Tonic handles this for you.

If an upload arrives before Google is ready, the attempt is recorded as **Pending** with the reason **Too recent call**, and Ring Tonic automatically retries after 6 hours, then after 12. Nothing is lost and you don't need to do anything.

{% hint style="success" %}
In practice most call conversions upload on the first try, because they're triggered when you qualify the call — usually hours after it happened, by which point Google has already indexed it.
{% endhint %}

#### Two Important Behaviors

<details>

<summary>Flagged campaigns send calls to this path only — never to lead and click uploads</summary>

Once a campaign is marked as receiving forwarded calls, its calls use the call path exclusively. If no call mapping exists for the stage, nothing uploads — the call does **not** fall back to a lead or click upload.

This is deliberate for two reasons:

1. A caller who never visited your site produces a weak lead-upload signal that Google may attribute to unrelated activity by the same person.
2. Routing that silently switches paths depending on which mappings happen to exist makes the upload log impossible to interpret.

If you flag a campaign and don't create a call mapping, you'll see attempts recorded as **Skipped — not configured for calls**, which tells you exactly what's missing.

</details>

<details>

<summary>Avoid double-counting against Google's own call conversions</summary>

Google Ads can count calls from your ads on its own, based on call duration, through its built-in "Calls from ads" conversion action. That action and your imported one can both fire for the same call.

If both are set as **Primary**, the same call is counted twice in your Conversions column and Smart Bidding learns from an inflated number.

Pick one to be Primary:

* **Imported call conversion as Primary** — best when a call only counts once your team qualifies it. This is the reason to use Ring Tonic here.
* **Google's duration-based action as Primary** — simpler, but counts any call over your chosen length, qualified or not.

Set the other to Secondary so it's still reported without influencing bidding.

</details>

#### Health Requirements Are Different

The two Google Ads prerequisites for lead uploads — customer data terms and enhanced conversions for leads — exist because those uploads contain customer details. Imported call conversions don't, so **those two requirements don't apply here**.

If your health check shows **TermsNotAccepted** or **EclDisabled**, your lead and click mappings are blocked but your call mappings keep working normally. The banners on the integration page say so.

Call mappings do still need a connection that has completed a health check successfully, because that check is also how Ring Tonic learns which account should receive your conversions.

***

### Viewing Upload Attempts

The **Recent upload attempts** section at the bottom of **Settings → Google Ads** lists every conversion upload Ring Tonic has attempted, with the result and a sanitized payload (no raw PII). Each row shows the status, contact, funnel event, value, which identifiers were sent (email / phone / address), any click IDs, and the resolved consent signals.

A **Type** column marks each attempt as **Clicks** or **Calls**, so you can tell lead uploads apart from imported call conversions at a glance. Use **Filters → Type** to show only one kind.

<figure><img src="/files/1mnDjD0zYMy9Fys49AML" alt=""><figcaption><p>Upload attempts — status, contact, value, identifiers, click IDs, and resolved consent per attempt</p></figcaption></figure>

| Status                             | Meaning                                                                                                                                                                                               |
| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Success**                        | Google accepted the conversion. It'll appear in your Google Ads account's conversions reporting within \~3 hours.                                                                                     |
| **Failed**                         | Google rejected the call. See `error_code` + `error_message` in the row for the specific reason; transient errors are retried automatically up to 3 times with exponential backoff (60s, 5min, 30min) |
| **Skipped — duplicate**            | A successful upload for the same `(event, conversion action)` already exists. Ring Tonic prevents double-counting                                                                                     |
| **Skipped — no identifiers**       | Contact has neither email nor phone, so we can't satisfy ECL's identifier requirement                                                                                                                 |
| **Skipped — consent denied**       | The resolved `ad_user_data` consent was `Denied`, so the upload was suppressed per Consent Mode policy                                                                                                |
| **Skipped — no integration**       | The workspace's Google Ads integration was disconnected between dispatch and execution                                                                                                                |
| **Skipped — health check failed**  | Health was non-Ok at execution time                                                                                                                                                                   |
| **Skipped — mapping disabled**     | The mapping was toggled off or deleted between dispatch and execution                                                                                                                                 |
| **Skipped — mapping changed**      | The mapping was repointed at a different conversion action — Ring Tonic refuses to silently redirect the upload                                                                                       |
| **Skipped — plan feature revoked** | The workspace owner's plan no longer includes Google Ads uploads (job was queued before downgrade)                                                                                                    |

These statuses appear only on imported call conversions:

| Status                                 | Meaning                                                                                                                                                                      |
| -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Pending — too recent call**          | Google hasn't finished indexing the call yet. Ring Tonic retries automatically after 6 hours, then after 12 — no action needed                                               |
| **Failed — call not found**            | Google has no forwarding-number record matching this caller and time. Expected for calls that didn't come from an ad; see [Common Issues](#common-issues) if it's every call |
| **Skipped — caller ID unavailable**    | The call arrived withheld, blocked, or with an unusable number. There's nothing to match on, so no upload is attempted                                                       |
| **Skipped — not configured for calls** | The campaign is marked as receiving forwarded calls, but no call mapping exists for this stage                                                                               |

Scroll the table right to reveal the sanitized **Request** and **Response** payload columns — useful for debugging integration issues with your Google Ads admin. Use **Filters** to narrow by status (e.g. show only `Failed`) and **Columns** to choose what's visible.

***

### Common Issues

<details>

<summary>"TermsNotAccepted" — health check keeps showing this</summary>

The Google Ads account hasn't accepted the customer data terms required for Enhanced Conversions for Leads. This is a Google-side gate that can only be unblocked by an **Admin** on the Google Ads account:

1. In Google Ads, go to *Tools → Conversions → Settings*
2. Expand **Customer data terms**
3. Read the policies, tick **I have read and accept the terms on behalf of my company**, save

If the checkbox is greyed out with the message *"Customer data terms for this account must be accepted by an Administrator"*, the currently signed-in Google user doesn't have Admin role on this account. Ask the account owner to either accept the terms themselves or grant you Admin access at *Tools → Admin → Access and security*.

After the terms are accepted, return to Ring Tonic and click **Re-check** — the status should flip to **Ok**.

</details>

<details>

<summary>"EclDisabled" — Enhanced Conversions for Leads is off</summary>

In Google Ads, go to *Tools → Conversions → Settings → Enhanced conversions for leads* and toggle it on. You'll need to choose between the **Google tag** and **Google Tag Manager** implementation paths — pick either, then come back to Ring Tonic and click **Re-check**.

You only need to enable ECL once per Google Ads account. Ring Tonic itself doesn't require any tag installation — we send identifiers via the API, not via a page tag.

</details>

<details>

<summary>"DEVELOPER_TOKEN_NOT_APPROVED" appears in upload errors</summary>

This means Ring Tonic's developer token is not yet approved by Google for production use. Either:

* Ring Tonic is currently using a **Test Account** token — it only works against Google Ads test customer IDs (sandbox accounts), not real accounts. This is the initial state for new Ring Tonic installations; we'll roll out approved tokens during onboarding.
* Or the developer token is pending Basic Access review.

This is a Ring Tonic ops issue, not something you can fix on your side. [Contact support](mailto:support@ringtonic.app) and we'll confirm the developer-token state for your workspace.

</details>

<details>

<summary>"CUSTOMER_NOT_ENABLED" appears in upload errors</summary>

The Google Ads account being uploaded to is cancelled, suspended, or otherwise disabled on Google's side. Common causes:

* Billing failed and the account auto-cancelled
* Google suspended the account for a policy violation
* The account is brand new and hasn't completed signup yet

Resolve the underlying Google Ads account state (billing, policy review, signup completion). Once the account is back to **Enabled** in Google Ads, click **Re-check** in Ring Tonic.

</details>

<details>

<summary>"INVALID_USER_IDENTIFIER" appears in upload errors</summary>

Google rejected the hashed email or phone we sent. Almost always because the source contact has a malformed value — e.g. a non-E.164 phone like `(555) 1234` instead of `+15551234567`, or a missing TLD on the email.

Open the contact, fix the bad identifier, advance the stage again. The next upload will succeed.

</details>

<details>

<summary>Every call conversion comes back as "Call not found"</summary>

Google has no forwarding-number record matching the caller and time you sent. Work through these in order:

1. **Check call reporting is on** in Google Ads at *Tools → Conversions → Settings → Call reporting*. This is the most common cause — with it off, your ad shows your real number, so no forwarding-number call ever exists.
2. **Confirm the call actually came from an ad.** Calls from a billboard, business listing, or someone redialling your number directly will never match, because Google has no record of them. Some **Call not found** results are normal and expected.
3. **Check the call asset points at the right number** — the tracking number on the flagged campaign, not your main line.
4. **Confirm the campaign flag is on the correct campaign.** If it's set on a campaign whose number isn't behind a call asset, every call fails to match.

A useful sanity check: filter the upload log to **Type: Calls** and compare the number of attempts against the calls Google reports for your call asset. If Ring Tonic is attempting far more than Google recorded, non-ad calls are reaching that number.

</details>

<details>

<summary>Call conversions sit at "Pending — too recent call" for hours</summary>

This is normal and requires no action. Google needs several hours to index a forwarding-number call before it can be matched, so an upload sent soon after the call is rejected as too recent.

Ring Tonic retries automatically after 6 hours, then after 12. Most calls succeed on one of those retries.

If an attempt is still pending well beyond a day, check that call reporting is enabled — an unindexed call and a never-recorded call can look similar early on, but a never-recorded one eventually settles as **Call not found**.

</details>

<details>

<summary>Uploads succeed but the conversion never appears in Google Ads reports</summary>

Two things to check:

1. **Wait at least 3 hours** — Google Ads has a delay between conversion upload acceptance and report visibility. Some attribution refresh windows take up to 24 hours.
2. **Check the conversion action's "Include in 'Conversions'" toggle** in Google Ads. If it's off, the conversion is recorded but excluded from the headline Conversions column (and from Smart Bidding learning). This is sometimes intentional (e.g. a test conversion action) — make sure it's on for the action your mapping points to.

</details>

***

### Disconnecting

Click **Disconnect** on the integration page. Ring Tonic immediately:

1. Clears the encrypted refresh token from the workspace
2. Disables all mappings for the workspace (they're kept on disk so you can re-enable after re-connect, but they won't fire while disconnected)
3. Stops dispatching new upload jobs

In-flight upload jobs that were queued before disconnect will skip with `skipped_no_integration` when they run.

To fully revoke Ring Tonic's access on Google's side, go to [myaccount.google.com/permissions](https://myaccount.google.com/permissions) and remove **Ring Tonic** from the list.

***

### Plan Requirements

Google Ads uploads are available on **Pro** and **Agency** plans. If your workspace owner's plan changes mid-flight, any queued upload jobs are evaluated against the current plan at execution time:

* **Plan retained or upgraded** → uploads proceed as normal
* **Plan downgraded** → jobs skip with `skipped_plan_feature_revoked` and the integration stays connected (no data loss; re-upgrade to resume)

***

### Common Questions

<details>

<summary>Does Ring Tonic ever modify my Google Ads campaigns?</summary>

No. The OAuth scope we request (`adwords`) technically grants edit access, but Ring Tonic only calls the conversion upload and metadata read endpoints. We never touch campaigns, ad groups, ads, keywords, bids, budgets, audiences, or any account-level settings.

</details>

<details>

<summary>What's the difference between a "conversion" mapping and a Google Ads campaign goal?</summary>

A **conversion action** is the bucket in Google Ads that holds individual conversion events. A Ring Tonic **mapping** is just our pointer: "when stage X happens, push an event into conversion action Y". One conversion action can be the destination for multiple workspaces; one workspace can map several stages to different conversion actions.

</details>

<details>

<summary>Can I map multiple stages to the same conversion action?</summary>

Technically yes — but you'll lose the per-stage signal. Smart Bidding can't tell that "Qualified Lead" and "Won" represent different funnel depths if both feed the same action. Use distinct conversion actions per stage for the best optimization signal.

</details>

<details>

<summary>What happens if a contact moves backward through the funnel?</summary>

Backward moves don't trigger uploads — Ring Tonic only fires when a stage advances forward. The one exception is the **Form Submitted** stage with **Upload every form submission** on, where repeat submissions from a known contact upload even without a forward move (see [Form Submitted: Every Submission or First Touch](#form-submitted-every-submission-or-first-touch)).

The original event(s) that already uploaded stay in Google Ads (they're real history). If you need to retract a previously uploaded conversion, use Google Ads' conversion adjustments tooling directly.

</details>

<details>

<summary>How are repeat form submissions counted?</summary>

It depends on two settings working together:

1. **Ring Tonic — "Upload every form submission"** decides whether repeat submissions are *uploaded* at all. On by default; turn it off to upload only a lead's first submission.
2. **Google Ads — the conversion action's "Count" setting** decides whether uploaded repeats are *counted*. Choose **One** to count a single conversion per click (recommended for lead gen), or **Every** to count each one.

A repeat within 30 seconds of the previous submission is always skipped as an accidental duplicate. See [Counting Repeat Conversions](#counting-repeat-conversions-one-vs-every).

</details>

<details>

<summary>Should I use imported call conversions or Google's built-in call reporting?</summary>

It depends on what you want a "conversion" to mean.

**Google's built-in "Calls from ads"** counts a call once it runs longer than a duration you choose. It needs no setup beyond call reporting, but it can't tell a genuine prospect from a wrong number that talked for two minutes.

**Ring Tonic's imported call conversions** count a call only when it reaches a funnel stage you chose — typically once your team has qualified it. Smart Bidding then optimizes toward calls that turn into real opportunities rather than calls that merely lasted a while.

Many advertisers run both, with one set as Primary and the other Secondary. See [Avoid double-counting](#two-important-behaviors) before turning both on.

</details>

<details>

<summary>Can one campaign send both lead and call conversions?</summary>

Yes, but not for the same call.

A static campaign marked as receiving forwarded calls sends its **calls** through the imported call path. If that campaign also has form tracking enabled, its **form submissions** continue to upload as lead conversions in the usual way.

What never happens is one call producing both kinds of upload — that would double-count a single conversion.

</details>

<details>

<summary>Why does a withheld or blocked caller ID skip the upload?</summary>

Imported call conversions match entirely on the caller's number and the call time. When a caller withholds their number, there's nothing to match against, so an upload would always fail.

Ring Tonic recognizes withheld and blocked calls — including the placeholder numbers some carriers substitute — and records the attempt as **Skipped — caller ID unavailable** instead of sending a request that can only be rejected.

The call itself is still logged in Ring Tonic as normal; only the Google Ads upload is skipped.

</details>

<details>

<summary>How does this compare to installing the Google Ads tag on my website?</summary>

The Google Ads tag fires conversions in real time, in the browser, when a page loads (e.g. a "Thank You" page after a form submit). That captures the immediate event but tells Google nothing about what happened to the lead afterward.

Ring Tonic's integration is the **offline conversion** companion: it picks up *after* the form submit and tells Google what actually closed. Most advertisers run both — the page tag for top-of-funnel signal, this integration for downstream value.

</details>

<details>

<summary>Should I turn on name &#x26; address matching?</summary>

If you collect the data, yes — it's free extra match signal. Google matches primarily on email, then phone, then address, so name and address mainly help for leads where the email didn't match or wasn't captured. There's no downside: it's opt-in, always hashed, and only sent when a complete address is present. The main requirement is that you actually capture address details on your forms and map them under [Enhanced Conversions: Name & Address](#enhanced-conversions-name-and-address).

</details>

<details>

<summary>Are uploads encrypted in transit?</summary>

Yes. All Google Ads API calls go over HTTPS, and user identifiers (email, phone) are SHA-256 hashed before they leave Ring Tonic — Google never sees raw PII.

</details>

<details>

<summary>How long does Ring Tonic keep my refresh token?</summary>

Until you click **Disconnect** or revoke access at [myaccount.google.com/permissions](https://myaccount.google.com/permissions). The token is encrypted at rest with the workspace's encryption key.

</details>

<details>

<summary>What's the daily upload limit?</summary>

Ring Tonic's developer token is approved for **Basic Access** (15,000 API operations per day across all workspaces). Each conversion upload counts as one operation. This ceiling is sufficient for the vast majority of workspaces — if you're approaching it, contact support and we'll review your usage.

</details>

***

### Related Guides

* [Contacts](/guides/contacts) — the funnel view that drives stage transitions
* [Form Submissions](/guides/form-submissions) — how Ring Tonic captures the original lead and its click ID
* [CRM Postback API](/guides/crm-api) — push external events that advance the funnel (and trigger Google Ads uploads)
* [How to Ensure 100% Attribution Accuracy](/guides/how-to-ensure-100-attribution-accuracy) — what the tracking script needs to capture for ECL to work


# Privacy Policy

Last Updated: June 10th, 2026

**1. Introduction**

* This Privacy Policy applies to all information collected through our desktop application, Ring Tonic ("Service"), and any related services, sales, marketing, or events.

**2. Information We Collect**

* We may collect personal information that you voluntarily provide to us when registering to use our Service, expressing an interest in obtaining information about us or our products and services, or otherwise contacting us.
* The personal information we collect depends on the context of your interactions with us and the Service, the choices you make, and the features you use.

**3. How We Use Your Information**

* We use personal information collected via our Service for a variety of business purposes, such as:
  * To facilitate the creation and securing of your account on our Service.
  * To post testimonials with your consent.
  * To enforce our terms, conditions, and policies.
  * For other business purposes, such as data analysis, identifying usage trends, determining the effectiveness of our promotional campaigns, and to evaluate and improve our Service, products, marketing, and your experience.

**4. Sharing Your Information**

* We may share your information with our service providers, in connection with any business transfers, to comply with laws, to protect your rights, or with your consent.

**5. Cookies and Similar Technologies**

* We may use cookies and similar tracking technologies to access or store information.

**6. Data Security**

* We have implemented appropriate technical and organizational security measures designed to protect the security of any personal information we process.

**7. Data Retention**

* We will only retain your personal information for as long as necessary for the purposes set out in this Privacy Policy.

**8. Privacy Rights**

* Depending on your location, you may have rights under applicable data protection laws in relation to your personal data, such as the right to request access, correction, or deletion of your personal data.

**9. Policy Updates**

* We may update this Privacy Policy from time to time. The updated version will be indicated by an updated "Revised" date and the updated version will be effective as soon as it is accessible.

**10. Google User Data (Google API Services)**

* When you connect a Google Ads account to Ring Tonic, you authorize us through Google's OAuth consent screen using the `https://www.googleapis.com/auth/adwords` scope. Ring Tonic's access to and use of information received from Google APIs adheres to the [Google API Services User Data Policy](https://developers.google.com/terms/api-services-user-data-policy), including the Limited Use requirements.
* **Google data we access.** Only for the Google Ads account(s) you explicitly select, we access: the list of Google Ads accounts your Google login can manage (account IDs and account names), each account's conversion-tracking settings, and each account's conversion actions. We do not access Gmail, Google Drive, Google Contacts, or any other Google service.
* **How we use it.** We use this data solely to (a) let you choose which Google Ads account to connect, (b) map your pipeline stages to your existing Google Ads conversion actions, and (c) upload offline ("click") conversions to that account so your inbound calls and contacts can be attributed to the campaigns, ad groups, and keywords that generated them. We do not use Google user data for any other purpose.
* **What we store.** We store your Google OAuth tokens in encrypted form, the Google Ads customer IDs you connect, your conversion mappings, and records of conversion-upload attempts. Personal identifiers such as email address and phone number are hashed before they are sent to Google and are redacted from any stored API responses; we do not retain raw Google user identifiers.
* **What we send to Google.** When a contact advances through your pipeline, we upload an offline conversion to your own Google Ads account containing the conversion action, conversion value and currency, a timestamp, an order ID, hashed email/phone identifiers, the ad click identifiers (gclid, gbraid, or wbraid), and your configured consent signals.
* **Sharing.** We do not sell Google user data, do not use it for advertising or to train artificial-intelligence or machine-learning models, and do not transfer it to third parties except (i) to Google as described above, (ii) to service providers that operate our Service under confidentiality obligations, or (iii) when required by law.
* **Your control.** You can disconnect your Google Ads account at any time from **Settings → Integrations → Google Ads** in Ring Tonic, which stops all further access and removes the stored tokens. You can also review or revoke Ring Tonic's access from your [Google Account permissions](https://myaccount.google.com/permissions) page.

**11. Google Calendar (Google API Services)**

* When you connect a Google Calendar account to Ring Tonic, you authorize us through Google's OAuth consent screen using the `https://www.googleapis.com/auth/calendar.events` and `https://www.googleapis.com/auth/calendar.readonly` scopes. Ring Tonic's access to and use of information received from Google APIs adheres to the [Google API Services User Data Policy](https://developers.google.com/terms/api-services-user-data-policy), including the Limited Use requirements.
* **Google data we access.** Only for the Google account the workspace owner explicitly connects, we access: the connected account's primary calendar, whose calendar ID (which Google sets to the account email) we use as a display label and connection health check; and free/busy availability for the specific time window of a requested appointment. The free/busy lookup returns only free/busy time ranges — not event titles, attendees, or any other event content. We do not list or read other people's events, we do not access any calendar other than the connected account's calendar, and we do not access Gmail, Google Drive, Google Contacts, Google Photos, or any other Google service.
* **How we use it.** We use this data solely to (a) label the connected calendar in your settings, (b) check availability for a requested time slot so our AI Agent call-flow node can detect scheduling conflicts, and (c) create the single appointment event the caller requested on your primary calendar. We do not use Google user data for any other purpose.
* **Limited Use and human access.** Our use of Google user data complies with the Google API Services User Data Policy, including the Limited Use requirements. We do not allow our personnel to read your Google Calendar data except where you have given affirmative consent, where necessary for security, to comply with applicable law, or where the data is aggregated and used for internal operations in accordance with the Limited Use requirements.
* **What we store.** We store your Google OAuth refresh token and latest access token in encrypted form, along with the access-token expiry, the connected account email, the calendar ID, which user connected the integration, the connect and disconnect timestamps, and the connection's health status. We retain this data while the integration is connected and until it is no longer needed to provide the booking feature; when it is no longer needed we delete or destroy it. To fully revoke Ring Tonic's access and invalidate the stored tokens at any time, remove Ring Tonic from your [Google Account permissions](https://myaccount.google.com/permissions) page.
* **What we send to Google.** When a caller confirms an appointment, we create one event on your connected account's primary calendar containing a title ("Appointment with {caller name}", or "Appointment (AI booking)" when no name was captured), a description with the caller's name, phone number, and any optional booking notes, and the start and end times in your workspace's configured timezone. We do not add attendees and do not send email invitations. Caller-provided details written into the event are handled in accordance with our caller-facing privacy terms and call-consent practices.
* **Sharing.** We do not sell Google user data, do not use it for advertising or to train artificial-intelligence or machine-learning models, and do not transfer it to third parties except (i) to Google as described above, (ii) to service providers that operate our Service under confidentiality obligations, or (iii) when required by law.
* **Changes to this policy.** If we change how Ring Tonic uses Google user data, we will notify you and ask you to consent to the updated privacy policy before the new use takes effect.
* **Your control.** You can disconnect your Google Calendar at any time from **Settings → Integrations → Google Calendar** in Ring Tonic, which immediately stops all further access; Ring Tonic makes no further Google Calendar calls for your workspace and no longer uses the stored tokens. To fully revoke Ring Tonic's access and invalidate the stored tokens at Google, review or remove Ring Tonic's access from your [Google Account permissions](https://myaccount.google.com/permissions) page.

**12. Contact Us**

* If you have questions or comments about this policy, you may [email us](mailto:me@phuclh.com).


# Terms of Service

Last Updated: November, 12th 2025

**1. Acceptance of Terms**

* By downloading, accessing, or using Ring Tonic, you agree to be bound by these Terms and Conditions ("Terms"). If you do not agree with these Terms, you must not use this application.

**2. Use of the Application**

* This application is intended for use in managing and improving the SEO of websites.
* Users must ensure that their use of the application complies with all applicable laws and regulations.
* The application should not be used for any unlawful purposes or in a way that violates the rights of others.

**3. Intellectual Property**

* All content, features, and functionality (including but not limited to all information, software, text, displays, images, and the design) are owned by Ring Tonic or its licensors.

**4. User Obligations**

* Users must provide accurate and complete registration information and keep this information up to date.
* Users are responsible for maintaining the confidentiality of their license keys.
* Any unauthorized use of the application or breach of these Terms must be immediately reported to Ring Tonic.

**5. Prohibited Activities**

* Users may not engage in activities that harm, disrupt, or otherwise negatively affect the operation of the application or the enjoyment of other users.
* Reverse engineering, decompiling, or disassembling the application is prohibited.
* Distributing, selling, or otherwise transferring your rights under these Terms to third parties is not allowed.

**6. Disclaimer of Warranties**

* Ring Tonic is provided "as is" without any warranties, express or implied, including but not limited to implied warranties of merchantability or fitness for a particular purpose.

**7. Limitation of Liability**

* Ring Tonic will not be liable for any indirect, incidental, special, consequential, or punitive damages arising out of or in connection with your access to or use of the application.

**8. Modifications to the Terms**

* Ring Tonic reserves the right, at its sole discretion, to modify or replace these Terms at any time. If a revision is material, we will provide at least 30 days' notice prior to any new terms taking effect.

**9. Governing Law**

* These Terms shall be governed and construed in accordance with the laws of Washington, without regard to its conflict of law provisions.

**10. Contact Information**

* If you have any questions about these Terms, please contact us at [me@phuclh.com](/legal/terms-of-service).

***


