Appearance
Click To Call
FreshClick-to-Call Widget
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
<sw-click-to-call> is a single-button call element. With a token and a destination, it renders a styled button that dials the configured destination and opens the full call UI in a modal.
Under the hood it’s a thin wrapper around <sw-call-widget> configured in modal mode, the button is the trigger; media, controls, and the optional AI transcript are delegated to the widget once the user clicks.
Minimum embed
One script tag, one element:
<script src="https://unpkg.com/@signalwire/web-components/dist/embed/signalwire-web-components-embed.iife.js"></script>
<sw-click-to-call
token="c2c_892b29eca7b6d96091faf713f07cdf46"
destination="/public/support"
label="Talk to support"
></sw-click-to-call>For bundler-based projects, swap the script tag for import "@signalwire/web-components/sw-click-to-call". The element markup is identical. See Overview for the two pathways.
Token
token accepts two formats:
- Embed token (
c2c_…/c2t_…prefix), created from a Click to Call resource in the dashboard (sidebar → Tools → Click to Call). The destination is pinned in the resource configuration; thedestinationattribute is ignored when the embed token already pins one. The widget routes throughembeds.signalwire.comautomatically. - Subscriber Access Token (SAT), a JWT minted by your backend for an authenticated user. Pair it with an explicit
destination.
For public pages, prefer the embed token: it’s safe to expose in HTML, scoped to a single destination, and revocable from the dashboard. Use a SAT when the visitor is signed into your app and the call should be attributed to their account. See Authentication.
Attributes
token is required. destination selects the resource to dial (ignored when the embed token already pins one). label sets the button text. audio-only skips video. See <sw-click-to-call> for the full attribute list.
Events
The element bubbles three composed events:
sw-dial, dialing startedsw-call-hangup, the visitor clicked hangupsw-call-ended, the call reached any terminal state
document.querySelector("sw-click-to-call")
.addEventListener("sw-dial", (e) => {
analytics.track("call_started", { destination: e.detail.destination });
});Styling
The button reads from the SignalWire DTCG tokens shipped in theme.css. Override them at any ancestor to restyle without piercing shadow DOM:
sw-click-to-call {
--interactive-status-success: #1d4ed8; /* button background */
--radius-md: 999px; /* pill shape */
--type-family-body: "Inter", sans-serif;
--type-size-body: 15px;
}For finer control, target the inner button via its CSS Part:
sw-click-to-call::part(button) {
padding: 14px 28px;
box-shadow: 0 4px 14px rgba(29, 78, 216, 0.4);
}See Theming for the full token list and brand-color recipes.
When to use <sw-call-widget> instead
<sw-click-to-call> is single-destination, button-only, modal-only. Use <sw-call-widget> directly for any of:
- Multiple destinations or dynamic routing.
- Inline (non-modal) rendering.
- A custom trigger element (use the default slot of
<sw-call-widget>). - Receiving incoming calls (
allow-incoming-calls). - Programmatic
dial()/hangup()control.
Both share the same underlying call lifecycle, see <sw-call-widget> for the full surface.
sw-click-to-call
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Drop-in call button, embed it anywhere on a page and clicking it dials a preconfigured destination, opening the full call UI in a modal.
<sw-click-to-call
token="YOUR_GUEST_TOKEN"
destination="/private/sales"
>
Call sales
</sw-click-to-call>sw-click-to-call is a thin wrapper around <sw-call-widget> configured in modal mode. The host renders only the green “Call” pill button; everything else (client init, SignalWire connection, media, controls, optional transcript) is delegated to the widget once the user clicks.
Use this element on marketing pages, support sites, or anywhere a single destination should be dialable with one click. For more elaborate scenarios (multiple destinations, custom UI, inline call) reach for <sw-call-widget> directly instead.
Class: SwClickToCall · Module: packages/web-components/src/components/sw-click-to-call.ts
class: SwClickToCall, sw-click-to-call
Fields
token
stringDefaults to ''
token field.
host
stringDefaults to ''
host field.
destination
stringDefaults to ''
destination field.
label
stringDefaults to 'Call'
label field.
audioOnly
booleanDefaults to false
audioOnly field.
Attributes
| Name | Field | Inherited From |
|---|---|---|
token | token | |
host | host | |
destination | destination | |
label | label | |
audio-only | audioOnly |
CSS Properties
| Name | Default | Description |
|---|---|---|
--interactive-status-success | Background color of the call button. | |
--type-family-body | Button font family (inherits the global tokens). | |
--type-size-body | Button font size. | |
--radius-md | Button border radius. | |
--transition-fast | Hover-state transition duration. |
Events
| Name | Detail | Description |
|---|---|---|
sw-call-ended | , | Fired when the call reaches a terminal state for |
sw-call-hangup | , | Fired only when the user clicks the hang-up |
sw-dial | , | Fired when the user clicks the button and the underlying |
Click-to-Call
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
What is Click-to-Call?
SignalWire Click-to-Call (C2C) is an embeddable script that adds real-time voice communication functionality directly to your website with minimal setup. With just a few lines of code, you can embed SignalWire’s calling capabilities inside an HTML page, allowing your website visitors to initiate voice calls directly from your web pages without requiring any additional software or setup.
Click-to-Call provides a simple way to embed voice communication on your website. If you need more advanced customization or features, the C2C widget uses the SignalWire Client SDK. You can leverage this SDK directly to build more sophisticated communication applications with additional control and functionality.
Prerequisites
The C2C embeddable script requires:
- A SignalWire account that has access to the dashboard
- A website where you can embed the C2C widget
- Full support for embedded scripts
Set up Click-to-Call
1
Create the widget
Start by creating a widget in your SignalWire Dashboard:
- Log in to your SignalWire Dashboard
- Navigate to Tools > Click To Call
- Configure your widget settings:
- Give your widget a descriptive name
- Set a destination for incoming calls (this is the resource address that will receive calls)
- Adjust any other settings as needed
- Click Save to generate your widget
- Click the Copy Embeddable Widget button to copy your personalized C2C script
The copied script will look similar to this (but with your unique API key):
<script>
// Sample code - Do not use this example. Always use the script generated from your dashboard.
(a => {
// Minified initialization code...
})({ apiKey: "c2c_YOUR_UNIQUE_API_KEY", v: "0.0.1" });
// Widget configuration
sw.c2c.spawn('C2CButton', {
destination: '/private/example',
buttonParentSelector: '#click2call',
callParentSelector: '#call',
// Additional parameters...
});
</script>2
Prepare your website
Before adding the script to your website, you need to add two HTML elements where the call button and interface will appear. Without these elements, the button and interface may appear in unintended locations, or not at all.
<!-- Add these elements where you want the C2C components to appear -->
<div id="click2call"></div> <!-- This will become your call button -->
<div id="call" style="height: 500px;"></div> <!-- This will display the call interface when active -->These elements can be positioned anywhere in your HTML based on where you want the button and call interface to appear on your page.
The call container (the element targeted by callParentSelector, #call above) must have an explicit CSS height. The widget does not set a height or min-height of its own, so without one the container collapses to 0px: the button still works and the call connects, but the call interface renders as a blank, invisible area. Set a fixed height such as height: 500px; (or any value that fits your layout) on this container.
If you prefer to use existing elements on your page instead of creating new ones, you can modify the script to target those elements in the next step. Simply note the IDs of your existing elements and update the buttonParentSelector and callParentSelector parameters accordingly. See the Technical Reference for more details on these and other configurable selectors.
3
Add the C2C script to your website
With your container elements in place, you’re ready to add the Click-to-Call script to your website:
Open your website’s HTML file in your preferred editor
Choose the best location for the script:
- Head section (recommended): Placing it in the
<head>ensures the script loads early, making the button available as soon as possible - End of body: Alternatively, you can place it just before the closing
</body>tag if you prefer to load scripts last
- Head section (recommended): Placing it in the
Add the script you copied from the dashboard to your chosen location:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Your Website Title</title>
<!-- Your other head elements (stylesheets, meta tags, etc.) -->
<!-- Option 1: Place script here in the head section -->
<!-- <script></script> -->
</head>
<body>
<!-- Your website content -->
<!-- The container elements for the Click-to-Call components -->
<div id="click2call"></div>
<div id="call" style="height: 500px;"></div>
<!-- More of your website content -->
<!-- Option 2: Or place script here at the end of the body -->
<!-- <script></script> -->
</body>
</html>The script will automatically find your container elements and render the call button and interface in those locations.
4
Test your implementation
- Save your changes and open your website in a browser
- You should see the Click-to-Call button in the location you specified
- Click the button to test:
- A call interface should appear
- A call should be initiated to your configured destination
- Try making a test call to ensure everything works properly
If the button doesn’t appear or calls don’t connect, check:
- That your element IDs match what’s in the script
- That the script is properly placed in your HTML
- Your browser console for any JavaScript errors
If the button works and the call connects (you can hear audio) but the call interface shows only a blank or white area, the call container is collapsed to 0px. Set an explicit CSS height on the callParentSelector element (#call), as shown above.
Next Steps
- View the technical reference for customization options
Technical reference
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
This page provides a comprehensive reference for Click-to-Call, including all available configuration parameters and their usage.
Snippet structure
The Click-to-Call snippet consists of two main parts that work together to create a fully functional Click-to-Call widget on your website:
Async loader (IIFE)
The first part is an Immediately Invoked Function Expression (IIFE) that handles:
- Loading the required JavaScript resources
- Authentication with SignalWire services
- Setting up the necessary namespaces and methods
// Async Loader IIFE - Do not modify this section except for the API key if necessary
(a => {
// Loader implementation
// ...
})({ apiKey: "c2c_XXXXXXXXXXXXXXXXXXXXX", v: "0.0.1" });Only modify the API key if necessary
- Never modify the Async Loader code except for the API key if necessary
- The API key is linked to your SignalWire account and specific permissions
- If you need to change the API key, ensure the new key has permissions for the destinations you plan to use
- If your key doesn’t have access to the destination resources, calls will fail to connect
The loader initializes a global sw namespace in your browser window, with a nested c2c namespace that contains all the methods needed to work with the Click-to-Call widget.
Component initialization
The second part calls the spawn method to configure and render the widget:
// Component initialization - Can be customized
sw.c2c.spawn('C2CButton', {
// Configuration parameters
destination: '/public/example',
buttonParentSelector: '#click2call',
callParentSelector: '#call',
// Additional parameters as needed
});When you create a Click-to-Call widget in the SignalWire Dashboard, both parts are generated together as a single code snippet. You can copy this entire snippet into your website’s HTML, and the Click-to-Call widget will be initialized immediately when the page loads.
In some cases, you might want to delay the initialization of the Click-to-Call widget until a specific user action or page event. You can achieve this by:
- Including only the Async Loader part of the script in your page’s head or early in the body
- Calling the component initialization method later when you want to initialize the widget
Methods
spawn
The spawn method is used to initialize the C2C widget. It will use the CSS selectors provided in buttonParentSelector and callParentSelector to render the call button and widget.
Syntax
sw.c2c.spawn('componentName', options)Parameters
componentName
stringRequired
The component to initialize. Currently only 'C2CButton' is supported.
options
objectRequired
An object of configuration options that control the behavior and appearance of the C2C widget.
destination
stringRequired
The destination address to call, using SignalWire Address format. Bound to the destination(s) selected when the snippet was created in the dashboard, if the destination is not valid, the call will not connect.
The destination must reference a valid destination that was selected when creating the C2C widget in the dashboard. If the destination is not valid, the call will not connect.
sw.c2c.spawn('C2CButton', {
destination: '/public/support',
});buttonParentSelector
stringDefaults to #click2callRequired
CSS selector for the HTML element where the call button will be rendered. This element must exist in the DOM when sw.c2c.spawn is called.
sw.c2c.spawn('C2CButton', {
buttonParentSelector: '#my-call-button-container',
});callParentSelector
stringDefaults to #callRequired
CSS selector for the HTML element where the call widget will be displayed when a call is active. This element must exist in the DOM when sw.c2c.spawn is called.
sw.c2c.spawn('C2CButton', {
callParentSelector: '#my-call-widget-container',
});innerHTML
string
Optional HTML markup to render a custom call button. If not provided, a default button will be used. Allows you to fully customize the button appearance to match your website’s design.
sw.c2c.spawn('C2CButton', {
innerHTML: '<button class="my-custom-button"><i class="icon-phone"></i> Call Support</button>',
});beforeCallStartFn
function
Called when the user clicks to start a call, before call setup begins. Return true to proceed with the call or false to cancel.
Common uses: validating form data, performing business hours checks, showing loading indicators, confirming with the user.
sw.c2c.spawn('C2CButton', {
beforeCallStartFn: () => {
const hour = new Date().getHours();
if (hour < 9 || hour >= 17) {
alert('Our call center is only available from 9 AM to 5 PM.');
return false;
}
document.getElementById('loading').style.display = 'block';
return true;
},
});afterCallStartFn
function
Called after call setup completes and the connection is established. Useful for updating UI elements or tracking call start events.
Common uses: hiding the call button, updating UI to reflect active call state, triggering analytics events.
sw.c2c.spawn('C2CButton', {
afterCallStartFn: () => {
document.getElementById('loading').style.display = 'none';
document.getElementById('call-button-container').style.display = 'none';
console.log('Call connected successfully');
},
});beforeCallLeaveFn
function
Called when the user or system initiates call end, before teardown begins. Return true to proceed with hanging up or false to cancel.
Common uses: showing confirmation dialogs, performing cleanup operations.
sw.c2c.spawn('C2CButton', {
beforeCallLeaveFn: () => {
return confirm('Are you sure you want to end this call?');
},
});afterCallLeaveFn
function
Called after the call has fully ended and the widget is removed from view.
Common uses: restoring UI elements to their pre-call state, showing feedback forms, triggering analytics events.
sw.c2c.spawn('C2CButton', {
afterCallLeaveFn: () => {
document.getElementById('call-button-container').style.display = 'block';
document.getElementById('call-feedback').style.display = 'block';
console.log('Call ended');
},
});onCallError
function
Called if any error occurs during the call setup process. Receives the error object as a parameter.
Common uses: displaying user-friendly error messages, logging errors, hiding loading indicators, implementing retry logic.
sw.c2c.spawn('C2CButton', {
onCallError: (error) => {
console.error('Call error:', error);
document.getElementById('loading').style.display = 'none';
if (error.name === 'MediaDeviceError') {
alert('Please ensure your microphone is connected and you have granted permission to use it.');
} else {
alert('Sorry, we couldn\'t connect your call. Please try again later.');
}
},
});Complete example
Here’s a complete example that demonstrates all available configuration parameters:
sw.c2c.spawn('C2CButton', {
// Core parameters
destination: '/public/support',
buttonParentSelector: '#click2call',
callParentSelector: '#call',
innerHTML: '<button class="custom-call-button">Contact Support</button>',
// Callback parameters
beforeCallStartFn: () => {
console.log('Preparing to start call...');
document.getElementById('loading').style.display = 'block';
return true;
},
afterCallStartFn: () => {
console.log('Call connected!');
document.getElementById('loading').style.display = 'none';
document.getElementById('click2call').style.display = 'none';
},
beforeCallLeaveFn: () => {
return confirm('Are you sure you want to end this call?');
},
afterCallLeaveFn: () => {
console.log('Call ended.');
document.getElementById('click2call').style.display = 'block';
document.getElementById('feedback-form').style.display = 'block';
},
onCallError: (error) => {
console.error('Call error:', error);
document.getElementById('loading').style.display = 'none';
alert('Sorry, we couldn\'t connect your call. Please try again later.');
}
});