# Add calling capabilities to your React app with Zoom Phone Smart Embed - Part 2
Welcome back! This is part 2 of the series on the step-by-step process of embedding and configuring Zoom Phone Smart Embed within a simple React application.
In [Part 1](docs/blog/phone-smart-embed-reactapp-part1) of this series, we created a SmartEmbed component for rendering the Zoom Phone widget, and we also established a smartEmbedService file that manages API communication with the Zoom Phone SDK.
In Part 2, we’ll build upon that foundation by:
- Implementing Click-to-Call functionality
- Creating a modal component to track real time Zoom Phone events
- Introducing some UI enhancements
### Let's get started
Open your `zoom-phone-smart-embed` project, and let’s dive in!
## Step 1: Implement Click-to-Call
[Click-to-Call](/docs/phone/smart-embed-guide/#click-to-dial-from-a-third-party-app) is a fundamental feature in any phone experience, as it reduces friction by enabling users to initiate calls without directly interacting with the Smart Embed widget UI. In this sample app, we have implemented a simple interface to dial numbers from our custom app.
Let's update our `smartEmbedService.js` file to send a `postMessage` to the Zoom Phone iframe. This is how Smart Embed communicates - by listening for specific messages types and data structures.
```js
export const makeCall = (phoneNumber, callerId) => {
const iframe = document.querySelector(
"iframe#zoom-embeddable-phone-iframe",
);
if (iframe && iframe.contentWindow) {
const message = {
type: "zp-make-call",
data: {
number: phoneNumber,
callerId: callerId, // The caller ID (optional)
autoDial: true, // Whether to dial automatically, default is true
},
};
iframe.contentWindow.postMessage(
message,
"https://applications.zoom.us",
);
console.log(`Making call to ${phoneNumber} with caller ID ${callerId}`);
} else {
console.error("Iframe or contentWindow not ready. Cannot make call.");
}
};
```
We're using `postMessage` to send a `zp-make-call` event directly to the Smart Embed iframe. This tells Zoom Phone to initiate a call using the provided number and caller ID. You can customize this later to pull numbers from contacts, CRM records, etc.
## Step 2: Create the `ClickToCall` component
Now that we have a function to initiate calls, we need a UI component that collects input and triggers that function. Create a `ClickToCall` component which gives your users an input to dial numbers without needing to navigate through the Smart Embed widget interface.
```js
import React, { useState } from "react";
import { makeCall } from "../services/smartEmbedService";
const ClickToCall = () => {
const [phoneNumber, setPhoneNumber] = useState("");
const handleCall = () => {
if (phoneNumber.trim()) {
makeCall(phoneNumber);
}
};
return (
setPhoneNumber(e.target.value)}
/>
);
};
export default ClickToCall;
```
Here’s what’s happening:
- We're using React state to track the entered phone number.
- When the user clicks “Call,” we call `makeCall()` and pass the number along.
- At this point, you can trigger real calls from your own app UI.
## Step 3: Add real-time event tracking
The Zoom Phone Smart Embed widget sends out `postMessage` events when important call actions occur - like incoming calls, call connected, call ended, and voicemail received.
Let's create an `EventLog.jsx` file where we are going to listen for [these events](/docs/phone/smart-embed-guide/#events), filter through them and display each as a modal pop-up in our application.
```js
import React, { useState, useEffect } from "react";
import EventModal from "./EventModalComponent"; // Import the EventModal component
import { isValidEventType } from "../utils/eventUtils"; // Import the utility function
const EventLog = () => {
const [logs, setLogs] = useState([]);
useEffect(() => {
const handleEvent = (event) => {
const eventType = event.data?.type;
// Use the utility function to filter event types
if (isValidEventType(eventType)) {
setLogs((prevLogs) => [
...prevLogs,
{
eventType,
data: event.data,
id: Date.now(), // Add a unique id for each log
},
]);
} else {
console.log(eventType);
}
};
window.addEventListener("message", handleEvent);
return () => window.removeEventListener("message", handleEvent);
}, []);
// Function to close modal by removing log from state
const closeModal = (id) => {
setLogs((logs) => logs.filter((log) => log.id !== id));
};
return (
{logs.map((log, index) => (