07-29-2020 09:59 AM
Hello All,
I'm working on a CallBack option for customer's who don't want to wait on hold. Basically, holding their place in the queue for the next available agent. I'm using the example found at the link below. But, have a few questions regarding the example.
I'm sort of ignoring the Leave a Message portion, as we already have something like that setup to send a caller to voicemail.
After the caller is Queued and the caller presses the 1 key, I send the caller to the portion of the script for the Call Back steps. Right now, I am able to successfully prompt the user for a call back number, which I then capture and read back to the caller to confirm. If the number is good, then a Terminate step.
Then, what I believe you're supposed to do is run a Place Call step to a new Script/Application containing a simple icd script with a Select Resource step. The Place Call step also has a Get Digit String (*under the Successful branch of Place Call) which waits for an Agent's input (*with a press one option to be connected).
This Place Call step hits the Unsuccessful branch. The example from the URL above just says to have the 2nd script's trigger to be a part of a different Call Control Group then the original script the caller was queued in. But, does that Call Control Group need to be a "outbound" Group Type for this to work? I don't appear to have that option when creating a new Call Control Group, so I assume we're not licensed for this. But, I did read something about Direct Preview Outbound, which doesn't require an extra license.
I have the MIVR logs from one of these test calls if needed. This is the first time we're trying anything outbound from UCCX so I'm not sure what's required.
Thanks in Advance,
Matt
Solved! Go to Solution.
07-31-2020 09:14 AM - edited 12-16-2020 09:44 AM
EDIT: I edited this post like 10 times to keep tweaking it. Sorry about that.
First off, you cannot save the caller's position in queue with UCCX callback. It's unfortunate, but it's just not possible right now.
For script 2, all you really need is this:
Script 2
Start
Accept (--Triggering Contact--)
Select Resource (--Triggering Contact--, "YourCSQName")
Connected
End
Queued
Delay 43200 sec
End
Notice that I prevent a loop from happening in the Queued branch by using a 12 hour delay. 12 Hours being the CUCM default setting for maximum call duration, at which point CUCM will drop the call.
You cannot avoid looping in Script 1 however, because it basically needs to poll something to understand when it can move to the next step, e.g., connecting to the caller. However, care should still be taken here, because too long of a call with too quick of a loop cycle will start failing your calls, and callers will never get a callback.
As an aide in slowing down the loop cycle, you can manipulate the prompt which plays in the Get Digit String step to be longer, repeat it self, and/or mix in a Delay Prompt (E.g., dp[5000]) to create some space between playouts.
Script 1 (cb is a Prompt variable)
contact = Place Call (to "1234")
Successful
Wait For Agent:
CED = Get Digit String (contact, cb + cb + cb + cb + cb + cb + cb + cb + cb +cb)
Timeout
Goto Wait For Agent
EDIT: 2020-12-16 - Added Wait For Agent label. Thank you Jim-J for bringing this to my attention.
Script 1
contact = Place Call (to "1234")
Successful
Wait For Agent:
ewt = Get Reporting Statistics (contact, Expected Wait Time)
CED = Get Digit String (contact, dp[ewt * 1000] + cb + cb + cb + cb + cb + cb + cb + cb + cb +cb)
Timeout
Goto Wait For Agent
Back to Script 2 though, the way I showed it, it will statically assign the target CSQ every time. This may or may not work for you. It typically needs dynamic assignment in my experience. In which case, the Contact created in Script 1, is actually the same Contact as --Triggering Contact-- in Script 2. This is convenient, because it allows you to Set Enterprise Call Info for the Contact in Script 1, while you can then Get Enterprise Call Info in Script 2. E.g. Pass the target CSQ name from one script to the other.
Just be careful about creating a race condition here. That is when Script 2 thinks it's able to read the value of the CSQ too soon, but Script 1 hasn't finished writing it yet. So, you can either just delay a little at the start of Script 2, just after Accept, or you can write a small polling interval loop, checking if the CSQ has been set yet.
Script 1
contact = Place Call (to "1234")
Successful
Set Enterprise Call Info (contact) Variables Used:csq
...
Script 2
Start
Accept (--Triggering Contact--)
Delay 5 sec
csq = Get Enterprise Call Info (--Triggering Contact--, "csq", --Scalar--, -- All --)
Select Resource (--Triggering Contact--, csq)
Connected
End
Queued
Delay 43200 sec
End
Script 1
contact = Place Call (to "1234")
Successful
Set Enterprise Call Info (contact) Variables Used:csq
...
Script 2
Start
Accept (--Triggering Contact--)
Check for CSQ:
csq = Get Enterprise Call Info (--Triggering Contact--, "csq", --Scalar--, -- All --)
If (csq == null || csq.isEmpty()) Then
True
Delay 5 sec
Goto Check for CSQ
False
Select Resource (--Triggering Contact--, csq)
Connected
End
Queued
Delay 43200 sec
End
In some cases, like even in yours, the Agent might connect to Script 1 (the pretend caller) and be at a point in the Get Digit String step where the Agent hears silence for a while. In which case, you might employee the following strategy, though it's a trade off in that you'll loop more often.
Script 1
contact = Place Call (to "1234")
Successful
Set Enterprise Call Info (contact) Variables Used:csq
Goto Wait for Agent
/* ...other outcomes handled here... */
Wait For Agent:
is_answered = Get Enterprise Call Info (contact, "is_answered", --Scalar--, -- All --)
If (! is_answered) Then
True
Delay 10 sec
Goto Wait For Agent
False
Interact With Agent:
/* ...do and say what you want to the Agent, you have them on the line... */
Script 2
Start
Accept (--Triggering Contact--)
Delay 5 sec
Select Resource (--Triggering Contact--, csq)
Connected
Set Enterprise Call Info (--Triggering Contact--) Variables used:is_answered
End
Queued
Delay 43200 sec
End
07-29-2020 06:16 PM
It's been a bit since I played with it, but no the CCG is just like just first CCG it doesn't have to be outbound. You're not really doing traditional outbound aka dialer. You're actually having the agent make an outbound call as if there were to pick up the phone an dial it manually.
david
07-29-2020 10:38 PM
07-30-2020 12:03 PM
Hey, thanks for the replies.
*See screenshot below of CallBack portion from Script 1...
Ok, so I figured out the issue where the Place Call step was hitting the Unsuccessful branch. The CSS used by the CTI Route Point did not contain the Partition used by the CTI Port. So I added that Partition to the CSS and Place Call now hits Successful.
If I then take an Agent that has the Skills needed in Script 1, and make them go Ready, that Agent rings and is now at the Get Digit String step under the Label WaitForAgentCallBack. The Get Digit String step just asks the Agent to press any number to be connected to the Customer. This is now working to call the customer.
But, if I wait more then just a couple of seconds to make the Agent go Ready, the Get Digit String step times-out almost immediately when the Agent picks up. However, if as soon as the script hits Get Digit String I make the Agent go Ready, they ring and can hear the Prompt from Get Digit String except for the first couple of words, which makes me think this step is already playing a prompt before any Agent is available...
Lastly, I'm a little confused about the purpose of Script 2, which is the Trigger that the Place Call step is dialing. What is the purpose of Script 2? I see in the URL example from my OP, it says Script 2 should just have an Accept Step + a Select Resource step. Since Script 1 is where we're waiting for an Agent to become available, I'm not sure what to do in Script 2...
Thanks Again,
Matt
07-30-2020 07:05 PM
"...which makes me think this step is already playing a prompt before any Agent is available..."
That's exactly how that works. It's blindly just looping a prompt saying "press any key to continue" because there's no intelligence to know when you have the human on the line.
So, for callback, UCCX must call itself. Script 1 is like the customer calling in, and Script 2 is like your queuing logic to route the call to the next available Agent. Think of Script 1 as a person and Script 2 as a traditional script you write to handle calls. Only, since it's a robot calling you, you don't need the pleasantries normally used like "Thank you for calling..." and "Please hold for the next available..." I mean, who am I to say you don't need that. Go ahead and tell it a story for all I care. Maybe UCCX has feelings?
07-31-2020 08:36 AM
Hey Anthony, thanks for the reply. Very much appreciated.
Ok, I'll add GoTos within the Enter Digit String step for the Unsuccessful and Timeout branches to restart that step. That makes sense, thank you.
As for Script 2... And this might be a personal preference, but maybe there's Pros to doing it a certain way. But, in Script 1 there are already Select Resource steps that have been queued up to the caller. So if I wanted to keep those same resources available to this caller, would I just use some bogus CSQ (*or if the CSQ needs to exist to not get errors, create a CSQ that has no Agents assigned to it) in order to just use those original Agent Resources from Script 1? Assuming this would preserve the caller's spot in the Queue.
Or, if we decide we want a separate skill to answer these calls, I'm guessing I would just Dequeue the caller from those already selected resources, and then use a new CallBack_CSQ containing separate skills in Script 2.Does that sound correct?
Thanks Again for the reply!
-Matt
07-31-2020 09:14 AM - edited 12-16-2020 09:44 AM
EDIT: I edited this post like 10 times to keep tweaking it. Sorry about that.
First off, you cannot save the caller's position in queue with UCCX callback. It's unfortunate, but it's just not possible right now.
For script 2, all you really need is this:
Script 2
Start
Accept (--Triggering Contact--)
Select Resource (--Triggering Contact--, "YourCSQName")
Connected
End
Queued
Delay 43200 sec
End
Notice that I prevent a loop from happening in the Queued branch by using a 12 hour delay. 12 Hours being the CUCM default setting for maximum call duration, at which point CUCM will drop the call.
You cannot avoid looping in Script 1 however, because it basically needs to poll something to understand when it can move to the next step, e.g., connecting to the caller. However, care should still be taken here, because too long of a call with too quick of a loop cycle will start failing your calls, and callers will never get a callback.
As an aide in slowing down the loop cycle, you can manipulate the prompt which plays in the Get Digit String step to be longer, repeat it self, and/or mix in a Delay Prompt (E.g., dp[5000]) to create some space between playouts.
Script 1 (cb is a Prompt variable)
contact = Place Call (to "1234")
Successful
Wait For Agent:
CED = Get Digit String (contact, cb + cb + cb + cb + cb + cb + cb + cb + cb +cb)
Timeout
Goto Wait For Agent
EDIT: 2020-12-16 - Added Wait For Agent label. Thank you Jim-J for bringing this to my attention.
Script 1
contact = Place Call (to "1234")
Successful
Wait For Agent:
ewt = Get Reporting Statistics (contact, Expected Wait Time)
CED = Get Digit String (contact, dp[ewt * 1000] + cb + cb + cb + cb + cb + cb + cb + cb + cb +cb)
Timeout
Goto Wait For Agent
Back to Script 2 though, the way I showed it, it will statically assign the target CSQ every time. This may or may not work for you. It typically needs dynamic assignment in my experience. In which case, the Contact created in Script 1, is actually the same Contact as --Triggering Contact-- in Script 2. This is convenient, because it allows you to Set Enterprise Call Info for the Contact in Script 1, while you can then Get Enterprise Call Info in Script 2. E.g. Pass the target CSQ name from one script to the other.
Just be careful about creating a race condition here. That is when Script 2 thinks it's able to read the value of the CSQ too soon, but Script 1 hasn't finished writing it yet. So, you can either just delay a little at the start of Script 2, just after Accept, or you can write a small polling interval loop, checking if the CSQ has been set yet.
Script 1
contact = Place Call (to "1234")
Successful
Set Enterprise Call Info (contact) Variables Used:csq
...
Script 2
Start
Accept (--Triggering Contact--)
Delay 5 sec
csq = Get Enterprise Call Info (--Triggering Contact--, "csq", --Scalar--, -- All --)
Select Resource (--Triggering Contact--, csq)
Connected
End
Queued
Delay 43200 sec
End
Script 1
contact = Place Call (to "1234")
Successful
Set Enterprise Call Info (contact) Variables Used:csq
...
Script 2
Start
Accept (--Triggering Contact--)
Check for CSQ:
csq = Get Enterprise Call Info (--Triggering Contact--, "csq", --Scalar--, -- All --)
If (csq == null || csq.isEmpty()) Then
True
Delay 5 sec
Goto Check for CSQ
False
Select Resource (--Triggering Contact--, csq)
Connected
End
Queued
Delay 43200 sec
End
In some cases, like even in yours, the Agent might connect to Script 1 (the pretend caller) and be at a point in the Get Digit String step where the Agent hears silence for a while. In which case, you might employee the following strategy, though it's a trade off in that you'll loop more often.
Script 1
contact = Place Call (to "1234")
Successful
Set Enterprise Call Info (contact) Variables Used:csq
Goto Wait for Agent
/* ...other outcomes handled here... */
Wait For Agent:
is_answered = Get Enterprise Call Info (contact, "is_answered", --Scalar--, -- All --)
If (! is_answered) Then
True
Delay 10 sec
Goto Wait For Agent
False
Interact With Agent:
/* ...do and say what you want to the Agent, you have them on the line... */
Script 2
Start
Accept (--Triggering Contact--)
Delay 5 sec
Select Resource (--Triggering Contact--, csq)
Connected
Set Enterprise Call Info (--Triggering Contact--) Variables used:is_answered
End
Queued
Delay 43200 sec
End
08-03-2020 09:04 AM
08-03-2020 09:59 AM
12-16-2020 09:07 AM
@Anthony Holloway Thanks for sharing this super detailed and helpful post!
In "Script 1 (cb is a Prompt variable)" I assume there's supposed to be a "Wait For Agent" label right after "Successful"?
12-16-2020 09:45 AM
You nailed it Jim! I just edited my post to reflect the label. Thanks for the compliments too!
10-08-2024 11:24 AM - edited 10-08-2024 11:29 AM
Hi @Anthony Holloway. Hope you are doing good. sorry to get the conversation started like this, I have been trying to get the callback script working but the callback only works internally. when it comes to 10 digit it gives me an error message with automated voice "The system is having problems" and hangs up. I have attached the screenshot of the setup. Our prefix dialing is with #. Please reply with any resolution. Thank you!!
10-08-2024 02:51 PM
I'm pretty sure you cannot redirect to any phone number beginning with a * or #. Check the doc excerpt here:
Source https://developer.cisco.com/docs/contact-center-express/call-redirect-step/#call-redirect-step
10-09-2024 12:16 PM - edited 10-09-2024 12:57 PM
@Anthony Holloway Thanks for the reply. our prefix starts with #, so I added it there. before that I tried not to use the # but still gave me the same error. I was testing In jabber as it makes a call without using #. Call goes to the agent. Agent presses 1 to route the call, but it directly goes to unsuccessful and ends it giving the automated error message that the system is having problems.
is there anything I can change? Been trying for a long time but getting the same error. Also I'm using the same CCG for both triggers
Discover and save your favorite ideas. Come back to expert answers, step-by-step guides, recent topics, and more.
New here? Get started with these tips. How to use Community New member guide