1. Automatic queue recalls with WombatDialer and QueueMetrics

    If you run a call center, serving clients in a timely way is often very complex, as it requires having enough people available to handle traffic spikes. The number of callers that disconnect because they have been waiting too long in a queue is then an important driver of the quality of your work, and these frustrated callers are the focus of much attention and scheduling/planning efforts in all call centers. This is because in a traditional setting doing inbound calling you basically had no other way of servicing the client but waiting for the person to call in.

    With an Asterisk-based PBX and using digital lines, this scenario changes a bit, as:

    • Your average caller has an associated caller-id that often matches a physical phone in their proximity
    • Telephone traffic is very cheap compared to the cost of agent time for call handling
    • You have ample means of programming the PBX to suit your exact needs

    So it is now a conceivable scenario to improve the services you are offering by adding an automated call-back option, so that you search the logs of lost calls and you actively schedule recalls on them in order to get back to people who hung up in frustration.

    The plan: automatic queue recalls

    In this article, we explain how to implement a basic call-back scenario using QueueMetrics and WombatDialer. What we do is very easy, as in:

    • We periodically run a script to gather the caller-ids of lost calls that were handled on a queue
    • We check each caller-id as to be sure is a valid number
    • We check that there is no subsequent successful call on the queue from the same caller-id (as to prevent recalling people who already retried themselves)
    • We schedule those calls for dialing no more than once per number per day

    As our dialing schedule happens on a WombatDialer campaign, we can control the flow of calls through it by adding and removing agents supposed to handle outbound traffic, or pausing it completely during periods of high inbound traffic.

    Step 1. Configuring QueueMetrics

    In order to gather information from QueueMetrics to an external script, we need to enable XML-RPC access credentials. This is usually very easy to do, as QueueMetrics ships with a (disabled) ROBOT login that allows external access.

    Enabling it is very easy: log in as an administrator, click on “Edit users”, edit the “robot” user and set “Enabled” to yes. While you are at it, take a second to change the default password.

    Step 2. Configuring WombatDialer

    Set up WombatDialer with a queue end-point (as described for example in "Elastix Queue call-backs with WombatDialer") and make sure everything is working.

    Create a new campaign for calling back people - set its “Idles on termination” property to yes and make the logging QueueMetrics-compatible. This way the campaign can run until needed, waiting for more numbers to be added when idle. Do not add any call list as we will load numbers to be called through the WombatDialer APIs.

    Before you start scheduling recalls, your campaign should look like the following one:

    You might also want to pause it, so you can decide when to run it.

    Step 3. The script

    Scripting QueueMetrics and WombatDialer is really easy. It can be done in any language - we chose PHP as it is well known, has good XML-RPC support to query QueueMetrics and is very simple to edit and customize.

    We created a sample script that can easily be downloaded from GitHub - as you will likely edit this to suit your needs, feel free to fork a new project and work on that. Our script is available from https://github.com/Loway/WombatDialerExamples in a folder named “AutoRecall”.

    The following parameters should be edited in the script:

    $qm_server = "10.10.5.11";
    $qm_port = 8080;
    $qm_webapp = "queuemetrics";
    $qm_login ="robot";
    $qm_pass = "robot";
    

    These parameters specify the XML-RPC connector of your QueueMetrics instance.

    $wbt_url = "http://10.10.5.18:8080/wombat";
    $wbt_cmp = "c1";
    

    These parameters specify the URL of WombatDialer and the campaign that calls should be added to. The dialer must be running when the calls are added and the campaign should be active (usually IDLE). Note that the campaign you use for call-back might be paused so that call-backs are actually deferred during periods of high activity.

    $queue = "300";
    $lookback = 3600 * 8 ; // in seconds
    $allowedPatterns = array( 
        "/^555..../",
        "/^0041.+/"
    );
    

    These parameters decide which set of queue(s) should be scanned and how long is to look back for the current day. Multiple queues can be used, separated by the pipe character.

    The last parameter is a set of regexps that will be used to check the numbers read from QueueMetrics. At least one regexp must match for the number to be queued. This is used to avoid queueing invalid numbers or - worse - malicious numbers.

    Step 4. Putting it all together

    In order to run the script periodically, you could crete a cron jub that runs it every 20 minutes. As number are never recalled more than once and the script keeps an history files of numbers already dialed, you can safely run it over and over again.

    Once tested, a crontab entry like the following one will automate the running:

    */20 * * * * /usr/bin/php /root/WombatDialerExamples/AutoRecall/autoRecall.php
    

    This is how a simple run looks like - the scripts logs its activity to STDOUT, so you may want to redirect it to some log file for the keeping.

    $>php autoRecall.php
    Finding applicable period
    Loading call log file for 2013-01-24
    Looking for data between 2013-01-24.07:54:33 and 2013-01-24.15:54:33
     on server '10.10.5.25' - queues '300'
    Query took 0 seconds.
    # 201 - Last call lost @ 2013-01-24.15:46:39 - Scheduling.
    Adding 201 to campaign c1 on WombatDialer.
    Saving call log
    

    After running this, you should see that new numbers are added to an AUTO call list like the one shown in the following screenshot; and if the campaign is not paused and agents are availble on the recall queue, calls will be dialed as needed.

    Improving the solution

    In order to run this solution in a real-life scenario, you should edit the campaign in order to:

    • set up a time window that matches your agents’ presence and when it is customarily allowed to recall. For example, even if a call is queued at 11 PM on a Saturday night, a recall might be acceptable only on Monday morning. This of course depends on what you are doing and the local customs.
    • set up reschedule rules in order to handle calls unanswered and busy lines correctly. It would be too bad not to be able to recall just because the caller’s phone was busy at the moment
    • it could also be useful to connect the caller to a reverse-IVR first, so that they get a message like “Hello, we are calling you back because of your call made at 10.30AM. If you’d like to talk to one of our agents, please press 1 now” before being routed to an agent
    • a simple addition that could be made to the script would be to set up a minimum wait time to qualify calls; that is, you would recall only people who waitied in queue for more than 10 seconds.
    • using a technique very similar to the one explained here, it would be trivial to set up campaigns for quality assessment or customer satisfaction, run as reverse IVRs.
     
  2. Elastix queue call-backs with WombatDialer

    You are called in to a client site; they seem to have a problem. They run a small (10 agents) inbound call centre, and when you join everybody else in the meeting room, there is a large and colourful graph in the middle of the table. The graph shows the call wait times during the week and boy, it’s not a good sight. Their main inbound activity is to offer client support for a company selling sport bikes, and everybody seems to be calling on Monday morning. It looks like people go riding on weekends and whatever problem they have, they call on Monday morning. Wait times peak, abandon rates spike, and nobody is happy. The call center manager is mostly concerned of having to hire and train some temp people in order to handle the load that only happens one day a week. They ask you if you have any better idea on what can be done. And yes, you have some.

    You can program an Asterisk queue so that when people tire of waiting, they press a digit and get to a menu where they can leave their number. Then the system queues their call and attempts to call them at a convenient time. This way:

    • your customer are happy; they don’t have to wait in queue for so long
    • your call center manager is twice happy: the first time because wait times and abandon rates go down, the second one because by placing calls at a convenient time they can smooth out the workload of their agents during the day

    This scenario requires some additional “glue” to what is basically supported by Asterisk - exiting a queue and reading a number are easy, but then starts the pain. You’ll have to create a database and write a script that reads back from it. You have to handle invalid numbers, busy numbers and the like (if we promised to call back the client, we cannot just try once and forget about it). You’ll have to have a GUI of some kind for the manager to start and stop dialing. You’ll have to adapt to the number of available agents. You’ll have to report on this activities. You’ll have to avoid flooding the trunks of your PBX with too many calls. In short, it’s the kind of thing that gets more complex the more you think about it. That’s what WombatDialer is for.

    What we plan to do is to use WombatDialer as the call-back engine. It can be controlled by an external HTTP API, so you can do that from the Asterisk dial-plan. It has a definite topology and call back rules, so you get the number of calls you expect on one or more Asterisk servers. It can work with an existing PBX and does not interfere with calls that are not its own. It keeps track of call completions and knows what to do in case of invalid and busy numbers. It has reports of its own and can work with QueueMetrics for powerful and detailed reports.

    The client uses Elastix as PBX system, so we’ll have to integrate it with WombatDialer. No problem!

    So what we do is:

    • First we create a normal queue, for inbound. We call it “400”.
    • Then we create a call-back queue. If our main queue is called “400”, then let’s call this second queue “401”. The idea is that WD will monitor this queue - when you have members on this queue, then WD will start placing calls. This way an inbound call-center with multiple queues will find it very natural to have some agents join and leave a call-back queue. When you creet this queue, make sure you set “Ring Strategy: rrmemory”, “Event When Called: Yes”, “Member Status: Yes”, “Autofill: yes” so that WD can use it effectively.
    • we create a piece of dialplan that will handle the exits from queue “400” and will gather the telephone number
    • we create a new “custom extension” (399) that will jump in the dialplan at “Local/1@queue-leavenumber”
    • In Elastix, we create an IVR menu and set it as a destination for queue “400”. This menu has only one option (1) that basically jumps to the custom extension “399” that we just created, in order to call our script
    • we go back to the queue “400” and set its “Fail Over Destination” as our IVR we just created

    We start by editing the extensions_custom.conf file in our system, adding a new stanza like:

    [queue-leavenumber]
    exten => 1,1,NoOp
    exten => 1,n(Start),agi(googletts.agi,"Please enter your telephone number and we will call you back.",en)
    exten => 1,n,agi(googletts.agi,"The number must be composed of 7 digits.",en)
    exten => 1,n,Read(CBNUM,beep,7,,2,5)
    exten => 1,n,NoOp( Num ${CBNUM} )
    exten => 1,n,GotoIf($["${LEN(${CBNUM})}"="7"]?lenOk)
    exten => 1,n,agi(googletts.agi,"The number you entered has the wrong number of digits.",en)
    exten => 1,n,GoTo(1)
    
    exten => 1,n(lenOk),agi(googletts.agi,"You entered the following number",en)
    exten => 1,n,SayDigits(${CBNUM})
    exten => 1,n,Wait(1)
    exten => 1,n,agi(googletts.agi,"Press 1 to confirm or any other digit to start again.",en)
    exten => 1,n,Read(CONF,beep,1,,2,5)
    exten => 1,n,GotoIf($["${CONF}"="1"]?Store:Start)
    
    exten => 1,n(Store),NoOp
    exten => 1,n,Set(WHEN=${STRFTIME(${EPOCH},,%y%m%d-%H%M%S )}
    exten => 1,n,Set(PARM=number=${CBNUM}&attrs=orgQ:400%2Cwhen:${WHEN})
    exten => 1,n,Set(foo=${CURL(http://10.10.5.18:8080/wombat/api/calls/? op=addcall&campaign=callback&${PARM})})
    exten => 1,n,agi(googletts.agi,"Thank you! we will call you back as soon as possible.",en)
    exten => 1,n,Hangup
    

    We use Google TTS as a voice synthesizer - you could use a different one or you could have the messages custom-recorded for you. What our dialplan does is first to collect a 7-digit number, then read it back asking for confirmation and when confirmed, it sends it over to WombatDialer on a campaign called “callback”. Together with the number, we also store the code of the queue that the call was on and the date and time this number was gathered. (Please note that in order to send multiple comma-separated parameters in the HTTP request, we have to use ‘%2C’ instead of the comma ‘,’).

    In order to configure WombatDialer:

    • We create a trunk called “Trunk” with a dial-string of Local/9${num}@from-internal and a capacity of 10 lines. This basically replies all numbers as if they were entered on a local extension prefixed by 9.
    • We create an End-Point of type Queue for monitoring queue 401; set extension to “401” and context to “from-internal”; max number of lines to 10; boost factor as 1 and max waiting calls to 2. This means that the number of calls placed will match the number of available agents on queue 401.
    • We create a campaign called “callback”; set it to Idle on termination and turn on QM_COMPATILE logging. We add the trunk and the EP we just created. We create a set of reschedule rules in order to handle REJECTED, BUSY, INVALID and NOANSWER calls, e.g. by retrying up to 5 times each waiting 10 minutes between each attempt. Note that we create no lists for this campaign.
    • We start the new campaign; having no numbers, it should immediately turn yellow on the Live page to tell you it’s idling.

    If we start sending calls to the queue and we try and leave any numbers, we will see that a new list will be created on WombatDialer under the name “callback/AUTO” and that will contain the numbers and attributes like:

     Number:     5551235
     Attributes: orgQ:400   when:121115-153402
    

    Those numbers are NOT immediately called, but WD will wait for some agent to be present and active on queue “401” so that they can be called back. This way, the call-center manager can monitor the current call backlog and decide who and when it is to join the callback queue.

    Further improvements

    • If there is a caller-id on the call, you could ask the caller whether to use it as the number to be called back
    • You could add time limits to the WD campaign so that you are sure that no calls are made otside acceptable periods

    See also

     
  3. News and User Manual… at last

    We have been working for a while on improving the WombatDialer experience. So in versions 0.5.0 to 0.5.7 we fixed many glitches in the user interface and made the user experience way smoother to follow. We thank the many people who tested WombatDialer and posted error reports so we could improve (you know who you are!).

    WombatDialer has been in production use in three medium sites for a couple of months now (adding to our initial pilot site), having 50 to 100 agents each, and has been exensively used as a robodialer and a power dialer. So we expect it to be essentially stable and usable. No major issues have been found in the dialer itself so far. We welcome all comments and suggestions.

    As an added benefit, we now have an initial draft of the User Manual online - it should be enough to document the basic concepts and the APIs in a systematic fashion. You can find it in HTML or PDF formats on the manuals page.

    We had a lot of good feedback and suggestions at the Astricon 2012, so stay tuned!

     
  4. WombatDialer and QueueMetrics

    The WombatDialer can be used as a stand-alone product for message broadcating, but it was built to integrate easily with QueueMetrics, the premier call-center monitoring and reporting tool for the Asterisk PBX. WombatDialer and QueueMetrics do different things, but together can be a very powerful call-center solution.

    • WombatDialer is able to use a Queue as and end-point in order to connect calls to a set of agents
    • QueueMetrics is able to monitor extensively the queue and provides a convenient agent interface that works well with WombatDialer

    In this example, we improve the scenario described in Feeding Wombats, one carrot at a time imagining that the want to:

    • use a custom CRM interface so that agents can immediately see the name of the person being called and can open up an external CRM application for each client so they can gather donation data
    • monitor each agent’s performance
    • use a dynamic list of people to be called so that as soon as you know of an interesting lead, you can add it to the list of persons to be called.

    You can have WombatDialer and QueueMetrics installed on the same server, unless you have a very high load or a very high number of lines.

    As a first step, we’ll have to create a small interface script that will be our CRM application. We will call it wombatPopup.php and will store it on one of our servers as http://10.10.5.10/lenz/wombatPopup.php

      Plain Wombat Agent Panel<hr>
      <?
      $number = $_REQUEST["caller"];
      $agent  = $_REQUEST["agent"];
      $unique = $_REQUEST["unique"];
    
      preg_match('/#(\d+)\s(.+)/', $number, $matches);
      $id = $matches[1];
      $name = $matches[2];
      ?>
    
      Person is: <?= $name ?> (ID #<?= $id ?>)<p>
      Agent is: <?= $agent ?> <p>
      Call unique is: <?= $unique ?>
    

    This page basically displays the person’s name and ID, so we can display it immediately - or this could redirect to an external CRM application.

    At the Asterisk level, if you have not already done so, create a queue “999” with the correct parameters to be monitored by Wombat - see Queue end-points in Wombat . Then edit your extensions_custom.conf file so that you have an extension “1235” that leads to the queue:

       [from-internal-custom]
       ….
       exten => 1235,1,Answer
       exten => 1235,n,Set(CALLERID(num)=#${ID} ${PERS})
       exten => 1235,n,Goto(from-internal,999,1)
    

    This rewrites the incoming caller-id for the queue to e.g. “#1234 John_Doe”, so this is what the agent sees - even before the agent pop-up is opened. This also is recorded in QueueMetrics, so this is what you will see when you run call reports. Note that if you run FreePBX you cannot call the queue directly using the Queue() command but you’ll have to go through its dialplan in order to have all parameters correctly set.

    In QueueMetrics, set the following properties in configuration.properties:

        realtime.agent_autoopenurl=true
        default.crmapp=
    

    Then create a queue “999” and set its Queue URL to:

        http://10.10.5.10/lenz/wombatPopup.php?caller=[C]&unique=[U]&agent=[A]
    

    This tells QueueMetrics that it has to enable a screen-pop for calls coming in through that queue.

    Now log on to WombatDialer; create an EndPoint of type Queue set for queue 999, and its entry point in the dialplan to 1235@from-internal-custom. Do not forget to set the “Boost factor” to 1 and the “maximum queue length” to 2.

    Then create a campaign called “QmSample” that idles on termination.

    Set the trunks, the EP we just created, add no lists and define any reschedule rules you need. The end result should look like the following:

    Now start the campaign. It will go in status IDLE immediately, as it has no numbers to dial, and you will see it all yellow in the Live page of WombatDialer.

    At this point, it is time for your agents to log in in QueueMetrics. Have them log-in to their Agent’s page, and from there log them on to queue 999. At this point, make sure that each agent’s browser allows QueueMetrics to open pop-up windows (this is usually disabled in modern browsers).

    Now, for each call you’d like to be started, send an HTTP request to WombatDialer that looks like the following one (we do this through the Linux shell, but there is nothing preventing you to script this in some other way:

     curl "http://10.10.5.18:8080/wombat/api/calls/index.jsp
           ?op=addcall
           &campaign=QmSample
           &number=2000136
           &attrs=ID:2301,PERS:John_Doe"
    

    Note that you associate two parameters: ID that is a unique id used by your CRM and PERS that is the called person’s name. You could also add additional parameters you may need, e.g. a person’s class or their thelephone number.

    What happens now is that when the call goes through, its caller-id is rewritten as “#2301 John_Doe” as soon as it reaches Asterisk. When your agent receives the call, they will reload the agent’s page and the pop-up will be immediately opened.

    In the pop-up, you parse the caller field and extract your CRM id, so you can use this for your external application to display the correct data.

    From the agent’s page you can also manually open other forms for recent calls. The agent will also see the person’s name in QueueMetrics, so this makes their life easier. The agent may also set a manual status code for each call through QueueMetrics, e.g. if the sale was successful or not, and this lets you measure your agent’s performance. You may also use QueueMetrics’s extensive QA monitoring features to analyze calls and improve the process.

    Analyzing outbound campaigns

    If you set your campaign to have QM_COMPATIBLE logging, you will find data abpout two different queues on QueueMetrics:

    • If you run a report for queue “QmSample”, you will see all calls that Wombat attempted - the successful as well as the unsuccessful ones. This is basicall the activity that WombatDialer performed and the actual telephone usage durations. In a real-life scenario, the vast majority of calls will be unanswered.
    • If you run a report for queue “999”, you will see activty about calls that were successfully connected and were actually queued to be answred by agents, You would expect to have a very low unanswered rate here - if it is high, it means something is not working as expected. You will of course have some lost calls, e.g. because the called person hung up before the agent was connected.
    • The difference between the number of successful calls in “QmSample” and the total number of calls in “999” are calls that were hung-up before reaching the queue, e.g. during an initial IVR phase.
     
  5. Understanding queue end-points in Wombat

    An end-point of type queue in Wombat tries to determine the number of available channels based on the number of available agents on the queue it is observing. An agent is considered available if it is logged on to the queue, is not paused and is not currently in conversation.

    After getting the number of available agents, it multiplies it by the “boost factor” (that is used to account for the success rate in connecting the numbers to be dialed) and tries to schedule as many calls. Therefore, if you have e.g. 7 available agents and a boost factor of 1.3, it will try to connect to 9 numbers at once (7 x 1.3 = 9.1).

    It will also enforce two limits:

    • If there are more than “max waiting calls” waiting on a queue, it will not try and place new calls - in theory there should never be calls queued, as they follow the number of availble agents, but it is possible that either some agent logs off after being counted to place calls or some calls reach a queue without passing through Wombat. This also acts as a counterbalance to high “boost factor” values.
    • it will never place more than “max channels” calls on the queue - this lets you use a shared queue where some calls come from inbound activity and some come from Wombat itself. Of course you can turn this off by setting “max channel” to a value higher than the total number of agents on the queue.

    It is also important to notice that the queue is used only as a way to know how many calls can be placed on a queue, but calls will still be transferred to a point in the dial-plan that should lead to the queue. This lets you execute dial-plan logic (e.g. playing pre-recorded messages or running IVRs) on the calls it just placed.

    In order to use Wombat effectively with a queue, the following guidelines are best followed:

    • though Wombat would work with static member channels, if you want your calls to go through to agents who may or may not be available (e.g. some days they may be sick) it is strongly advisable to use dynamic agents who log on and off from the queue.
    • as an agent cannot be physically available at all times during the day, it is important that they have a way to pause themselves, be it to run “wrap up” activities after calls or to take breaks. The QueueMetrics web interface offers an excellent panel that lets you add pause codes as well
    • the queue must provide events to Wombat about agent activities. Therefore you must set “eventswhencalled=true” - otherwise the queue will be unobservable. It is also important that extension presence is correctly observed - e.g. if an end-point is busy because the agent is doing a personal call, its queue status should immediately reflect this. Whenther this happens or not on your system is a matter of Asterisk version and type of channel that is used to reach the agent - with recent versions of Asterisk and SIP channels this should work automatically.
    • the queue should connect calls to agent as efficiently as posssible when there are multiple calls waiting and multiple avavilable agents, so it should have the “autofill” option set to true.

    In order to run a campaign with a Queue endpoint, it is best to:

    • create a campaign with a Queue endpoint. You may create it IDLE and add no call lists, so the campaign does not actually do anything until fed some numbers.
    • run that campaign
    • reload the Dialer status in order to see if the queue is being observed (you have to click on the reload icon manually each time). If the queue is present, you should see it something saying “Free 4 of 7 W:2”. This means that Wombat is seeing 7 agents connected of which 4 are free (where 4 is the result of multiplying the actual number of observd channels by its boost factor), and that there are 2 calls waiting on the queue.
    • try and log on, log off, pause and unpause an agent. You should see the number of free and available channels. Try also sending calls to the queue and see if the number of agents and of waiting calls is correct.
    • try also placing calls from some agent extensions and see if the number of free channels reflects this correctly.

    The Queue functionality of Wombat lets you use Wombat as a powerful progressive dialer and can lead to very complex integration scenarios, but as it involves actual people being called and answering the phone, it is better to understand it well before actually using it in production.

    (Source: wombatdialer.com)