Bitrix24 Telephony: How not to Miss a Single Call

29 June 2018

next article
Vladimir Sidletsky

Back End Developer

Vladimir Sidletsky
Bitrix24 Telephony: How not to Miss a Single Call

The sales in most companies, online stores, or organizations are directly linked to phone conversations. Special scripts for the communication with customers are developed for managers, and training courses are conducted. But even these measures don’t exclude human errors.

To minimize the loss of new or current customers, many companies switch to IP telephony. After all, it allows monitoring all stages of communication, thereby analyzing the level of service (for example, listening to recorded manager conversations). After such measures are taken, the employees have a better attitude toward their work, because they understand that their conversations are under constant control, and they can’t avoid communicating.

In order not to lose potential customers, we will use the Bitrix API. We have to create a functional mechanism to keep in mind each customer and timely contact him/her. Let’s figure out how we can do that using Bitrix24 and its telephony.

First of all, it is a virtual ATS, which can help you distribute the “waiting line” of incoming calls between employees. You can record all conversations and then conduct a selective customer service quality control in the form of listening to the records by the line managers. And additionally, you can customize your “greeting message”, “on hold” tunes, as well as redirect calls, keep tracking calls from customers, save the recordings of conversations, etc.

To process the call, we will use the onCallEnd event (the event is called when the conversation ends (writing to the history)): We create the event handler:


AddEventHandler("voximplant", "onCallEnd", "AddTaskSkipCall");
     	function AddTaskSkipCall($arFields){} // array $arFields the data array gets to the

We check the value of the CALL_FAILED_CODE parameter: if it equals 304 (missed call), we keep on processing:

if($arFields['CALL_FAILED_CODE'] == '304'){};

To find out whether the caller is in our database, we search for him/her by phone number:

  	     	$arFilterPhone = array("TYPE_ID" => "PHONE", "VALUE_TYPE" => "WORK", "VALUE" => $arFields['PHONE_NUMBER']);
    	     	$obFields = CCrmFieldMulti::GetList(array(), $arFilterPhone);
    	     	while($arField = $obFields->Fetch()){
    	     	     	if ($arField['ENTITY_ID'] == 'CONTACT') {
                             	$contact_id = $arField['ELEMENT_ID'];
    	     	     	$obCRMContacts = CCrmContact::GetList($arOrder = array('DATE_CREATE' => 'DESC'), $arFilter = array("ID"=>$contact_id), $arSelect = array('NAME', 'LAST_NAME', 'ASSIGNED_BY_ID'), false);
	                  	$arContact = $obCRMContacts->Fetch();
                      	$contact = $arContact['NAME'].' '.$arContact['LAST_NAME']; // we get the full name
                                                         	$responsible_id = $arContact['ASSIGNED_BY_ID']; // we get the employee responsible

In order not to hang the task up, we will establish the deadline of one day. To do this, we get the object with the date of the call from the $arFields array. On the basis of the data obtained, we determine the deadline for the task:

$refValue = new \ReflectionClass($arFields['CALL_START_DATE']);
     	$propValue = $refValue->getProperty('value');
     	$value = $propValue->getValue($arFields['CALL_START_DATE']);
     	$sDate = $value->date;
     	$arDate = explode('.', $sDate);
     	$date = new DateTime($arDate[0]);
     	$date->add(new DateInterval('P1D'));
     	$deadline = $date->format('m/d/Y h:i:s a'); // our deadline

We add the task title:

$taskTitle = "Skipped call fr om ".$arFields['PHONE_NUMBER']; // task title

Based on whether the contact is in our database, we come up with a task description, along with the employee responsible if he/she has not been specified yet:

if ($contact) {
             	$description = "Call back to ".$contact.". The call was skipped at ".$arDate[0];
             	$description = "Call back to ".$arFields['PHONE_NUMBER'].". The call was skipped at ".$arDate[0];
             	$responsible_id = TASK_CREATED_BY; //the employee responsible (the default one is admin)

Using the CTaskItem::Add method (, we create the task:

	$task = new \Bitrix\Tasks\Item\Task(0, TASK_CREATED_BY);
     	// array with fields for task
     	$task['TITLE'] = $taskTitle; // task title
     	$task['DESCRIPTION'] = $description; // task description
     	$task['RESPONSIBLE_ID'] = $responsible_id; // the employee responsible
     	$task['CREATED_BY'] = TASK_CREATED_BY; // admin id 
     	$task['DEADLINE'] = $deadline; // deadline
     	// create the task
     	$result = $task->save();  

We can also add ACCOMPLICES to the task. If the interactive voice response (IVR) system is configured, we can assign specific user groups responsible for an action to specific response buttons. It is these groups that we can use as the task accomplices to assign the responsibilities more accurately. In this case, we will have to get the call log from the database by the call ID ($arFields['CALL_ID']):

global $DB;
     	$ob = $DB->Query("SEL ECT F.CALL_LOG FR OM b_voximplant_statistic F WH ERE F.CALL_ID = '".$arFields['CALL_ID']."'");
     	$res = $ob->Fetch();
     	$urlCallLog = $res['CALL_LOG']; // log address

We will pull out the code of the button pressed from the log file itself, and, accordingly, determine the users by previously specified IDs of the groups they are in:

$find_str = 'Received tone ';
     	$str = file_get_contents($urlCallLog);
     	$pos = strpos($str, $find_str);
     	$ivrButton = substr($str, $pos+strlen($find), 1);
     	if ($ivrButton == 2) {
             	$userGroup = CGroup::GetGroupUser(SUPPORT_GROUP_ID);
     	}elseif ($ivrButton == 1) {
             	$userGroup = CGroup::GetGroupUser(SALES_GROUP_ID);
     	}elseif ($ivrButton == 3) {
             	$userGroup = CGroup::GetGroupUser(BILLING_GROUP_ID);

We add the following to the array before creating the task:

$task['ACCOMPLICES'] = $userGroup; // task accomplices

In the end, I’d like to add that you can always add the handler to the given code to create the task. Even if the call was successful, you can see all of your calls and supplement the tasks with their results to see a broader picture.

That’s all. Now you won’t miss a single call, and your customers will be in good hands ))

Similar articles
Apply for a consultation

We will reach out to within 10 minutes