IVR: Finding Extension Associated With Option

I forget the post I was going off of, but I found a walkthrough on basically recording the options a caller chose when in an IVR and sending it to a CSV file. I am just setting up a web page using PHP and reading from that CSV to show information (call’s timestamp, the caller, the call duration, which IVR it was, and what option they chose).

I’ve been looking around and not sure if I’m missing an obvious variable, but is there a variable that holds the extension that is associated with the option the caller chose? As in, if the caller entered 2, in the sample IVR I’m working with, that is associated with and will transfer the caller to extension 2121. How can I grab that 2121 extension if there’s a handy variable with that information? I thought maybe ${CDR(dst)}, but that just returns “s”


(Edited to add link to where I was following steps from (post #4): How to store ivr’s DTMF choices as text document - FreePBX - FreePBX Community Forums)

Maybe ${AMPUSER}

Hmm, that one didn’t seem to work. Just a blank spot after the last comma (I put the ______ in for emphasis):

Mar 17 2023 07:58:02 AM,5092226543,5094913796,4,ivr-3,2,______

Providing Great Debug - Support Services - Documentation (freepbx.org)

Provide a log of one of the calls, we can see which variable to use.

Hopefully this paste works and it has the information that’s relevant. Pretty sure I set this paste to not expire.

FreePBX_2023-03-17 - Pastebin.com


Looks like ${EXTTOCALL} might work.

No luck on that one either. Is it because of the order of things? This is how the overwritten dialplan code looks for selecting the options:

exten => 2,1,system(echo “$(date +‘%b %-d %Y %I:%M:%S %p’),${CALLERID(num)},${CALLERID(dnid)},${CDR(billsec)},${IVR_CONTEXT},${EXTEN},${__EXTTOCALL}” >> /var/www/html/ivr-admin/ivr-results.csv)
exten => 2,n,Set(__ivrreturn=0)
exten => 2,n(ivrsel-2),Goto(from-did-direct,2121,1)

As you can see, the file writing happens before the last line:

exten => 2,n(ivrsel-2),Goto(from-did-direct,2121,1)

Which is where those variables are populated with 2121. Before that, the variables wouldn’t exist yet, or they would just be empty, if I’m thinking correctly?

Also I keep forgetting to ask, how do I make the text formatted like code, rather than what I end up doing which is like a quote or something?

There’s a button in the editor

You can also enclose a whole block between tipple back tics


1 Like

If you use dynamic routes instead of an IVR, you can save the caller’s DTMF input into a channel variable, which is not exactly what you’re after but might be easier to work with.

It is not a normal variable that is people populated here, it is the actual working extension number, which is a property of the channel itself, not a channel variable. There is a variable that accesses this, but it is really a function, it is ${EXTEN}.

I did try that before, but with my limited knowledge of dialplan coding it didn’t quite get me what I wanted (by the way, the tutorials you’ve put out over time have been very valuable, they’ve helped me quite a lot in spots!)

The ${EXTEN} variable just gives me the selected option, not the endpoint that that option corresponds to / the caller was transferred to when selecting that option.

One thing that I’ve been trying out is running grep through exec() (I’m using PHP for this page) on /var/log/asterisk/full* on IVR entries. It’s getting me what I want (the extension that goes with the option essentially), though I’m having a hard time lining up in the corresponding table entries (after some PHP regex I filled an array with the menu option and corresponding endpoint, but I’m trying to find some magic offset maybe to display the correct things in the table - not all the endpoints match up with what’s in the actual IVR - for example the 10th entry in the table):

The GoTo sets ${EXTEN}. It may get changed later.

The 2121 is stored in the dialplan here. When it executes the context, extension, and priority are set to those values, and the next dialplan line executed would see ${EXTEN} set to 2121.

The dialplan will have been created using the contents of one of FreePBX’s database tables.

I was still having trouble accessing ${EXTEN}, still just gives me “s.” It may be my still relatively new dialplan programming experiences.

I did get a SQL connection from the PHP page to the Asterisk CDR database:

SELECT calldate, src, did, billsec, dst FROM asteriskcdrdb.cdr WHERE did IN ('DID 1', 'DID 2', 'DID 3') ORDER BY calldate DESC

Weird thing (or maybe not weird - again, I’m still not 100% familiar with the ins and outs of Asterisk) is in the dialplan if I have it put ${CDR(dst)} into the ivr-results.csv file, it puts “s,” but if I pull the cdr column from the database, it gives me the actual extension that it was transferred to (which is what I want). Thinking about this more, I’m assuming it’s because the inserting into the CSV file happens before the GoTo line is performed, so it just puts “s” in there since that’s where the caller last got to. For reference, to make things more readable, the “Released by caller” is displayed if the destination is “s” (the caller never selected an option, just hung up); “Released by system” (not shown in screenshot) is if the destination is “t” / timed out.

My best guess is it shows the actual DTMF they input if the caller (in all these cases, the caller is me) hangs up after choosing the option but before being sent over, but I could be wrong. I’m unsure of what the cause is for why it sometimes shows the extension, as it does in the last three rows above.

The value written to the database is the value of ${EXTEN} at the point when the call hung up.

In your code fragment, that value isn’t in a variable, because it is actually in the code. It may get copied to a variable later. Getting a log for a call should show a Set application call, if that is the case. I don’t believe there is any introspection feature that would allow the dialplan to read a value from the dialplan.

The translation from option to destination is in the FreePBX database and this is the SQL used to read them:

The same file generates the dialplan you quoted.

I don’t think the internal FreePBX database is guaranteed interface, so this might, but probably won’t change, without warning, between versions.

After a few more days of working on this, I’m closer to where I want to be. I’m trying to figure out how not all the calls to the IVR are categorized as such (as in, it doesn’t show the call went to ivr-6, for example, but just shows the call went to the final extension).

Some of them are being categorized correctly, that’s why in the first row the “Call Result” column shows “2 → 7502” (the caller selected option 2, which corresponds to extension 7502. But many of them, for example the second row, just shows 5000 (which corresponds I think to option two for that particular IVR).

To kind of get around that, I did a SQL query where DID in (‘DID_FOR_IVR-1’, "DID_FOR_IVR-2’, etc.). That seemed to help at least grab all the calls that are IVR calls. But just trying to find out why some of them just show the extension the caller actually was transferred to based on the selection, vs. the option they selected. I’m getting the corresponding extension by joining the asteriskcdrdb.cdr table onto the asterisk.ivr_entries table.

Thinking about it this is probably more of a SQL question at this point so we can probably just let this thread die out.

I have this all working as I want now! I was curious if anyone was willing to take a look at the code I have to make sure it’s not bloated, has any potential security risks, or would have potential performance issues (right now on our test system just have three IVRs and I’m the only one test calling, other than a couple random people that happen to call our DIDs)? Or if anyone is interested in using it too - at least for my purposes it’s useful to see this information, don’t know if it would be useful for others as well.

I would like to incorporate it into my FreePBX dashboard (I did use the module builder, but haven’t had luck with the signing process so keep getting notifications that there’s an unsigned module).

<?php $servername = “localhost”; $username = “USERNAME”; $password = "PA - Pastebin.com

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.