Knowledge Base · Call Tracking

How do I set up Dynamic Number Insertion (DNI)?

This article covers installing the phone-number-swap script that shows each visitor the right tracking number for the channel that brought them in — for one location or several.

Read this whole article before installing. Always add the script in staging first, confirm it behaves correctly, then publish to the live site.

What's different from the old script

The old DNI script is retired. The new one does the same job — swap the displayed number for ad-attributed visitors — but it's simpler to install and covers more cases automatically. If you've installed the old version before, here's what changed:

Old script

  • Whole script pasted into custom code, one copy per site
  • Only detected Google Ads, via a custom ?network=g parameter
  • Single & multi-location used two different code blocks
  • Phone number format had to match exactly, or replacement could fail
  • Tracking flag never expired once set

New script

  • One hosted script + a short config block, same for every site
  • Reads standard utm_source — Google, Facebook, or any channel you define
  • Single & multi-location use the identical setup, just a longer config
  • Matches parens, dashes, dots, or bare digits automatically
  • Attribution expires after a config-set window, then falls back to the default number

01Preparation

If you're unsure about anything below, contact the technology team before publishing to a live site.

02Identify the phone number(s) on the site

Before installing, note every place the phone number appears:

You no longer need to standardize formatting first. The new script recognizes (954) 972-4208, 954-972-4208, 954.972.4208, 9549724208, and versions with a leading 1 or +1 — all as the same number. Whatever format each instance is already in, that's the format it stays in after swapping.

If the site has more than one location, note which number belongs to which office — you'll list each one separately in the config.

03Open the WebFlow custom code settings

  1. Log in to WebFlow and open the site's project.
  2. Decide the scope. For a single page, open that page's Settings (gear icon) from the Pages panel. For the whole site, go to Project Settings → Custom Code instead.
  3. Find the footer field. You'll paste the install snippet into Before </body> tag (page-level) or the Footer Code section (site-wide).

04Add the script and config

Unlike the old script, you're not pasting in the whole program — the script itself is hosted and shared across every site. You only add a small config block, then load the script:

Single-location site

Before </body> tag
<script>
  window.DNS_CONFIG = {
    expirationDays: 30,
    groups: [
      {
        name: "Main",
        defaultNumber: "(000) 111-2222",
        utmMap: {
          google: "(000) 333-4444",
          facebook: "(000) 555-6666"
        }
      }
    ]
  };
</script>
<script src="https://dni-script.dentalmarketing.com/dynamic-number-swap.js"></script>

Multi-location site

Add one object to groups per office. Everything else about the install is identical:

Before </body> tag
<script>
  window.DNS_CONFIG = {
    expirationDays: 30,
    groups: [
      {
        name: "Miami",
        defaultNumber: "(111) 111-1111",
        utmMap: {
          google: "(222) 222-2222",
          facebook: "(333) 333-3333"
        }
      },
      {
        name: "Tampa",
        defaultNumber: "(444) 444-4444",
        utmMap: {
          google: "(555) 555-5555",
          facebook: "(666) 666-6666"
        }
      },
      {
        name: "Orlando",
        defaultNumber: "(777) 777-7777",
        utmMap: {
          google: "(888) 888-8888"
        }
      }
    ]
  };
</script>
<script src="https://dni-script.dentalmarketing.com/dynamic-number-swap.js"></script>
Every visitor's channel applies to every location at once. If someone arrives via ?utm_source=google, Miami's number swaps to Miami's Google number and Tampa's swaps to Tampa's Google number, in the same page load. You don't need separate logic per office — the script matches each location's own current number on the page and looks up the right replacement for it.

A location doesn't need a mapping for every channel — Orlando above only tracks Google. Any channel without an entry just keeps showing that location's defaultNumber.

05Config field reference

FieldRequiredDescription
expirationDays Yes How many days a visitor's channel is remembered across page views before the site reverts to default numbers. 30 is a reasonable starting point for most call-tracking windows.
groups Yes One entry per phone number on the site. At least one is required, even for a single-location site.
groups[].name Recommended A label for the location, for your own reference. Must be different for every group on the same site.
groups[].defaultNumber Yes The number currently live on the site for this location, in any format.
groups[].utmMap Yes (can be empty) Maps a utm_source value (lowercase) to the call-tracking number to show for that channel.

06Testing

  1. Test with a tracked URL. Open the page with ?utm_source=google appended (e.g. https://www.example.com/?utm_source=google) and confirm every visible instance of the number changes, in whatever format it was already in — and that any tel: links update too.
  2. Test page navigation. Click through to other pages on the site and confirm the tracking number keeps showing, without the parameter in the URL.
  3. Test with no parameter. Open the site fresh (or in a private window) with no utm_source at all, and confirm the original number is shown.
  4. Test each channel you configured (?utm_source=facebook, etc.) the same way.

07Troubleshooting

Number isn't swapping

Right location swaps, wrong number appears

Changes not visible

08Maintenance

Adding a location

Add a new object to the groups array, following the same shape as the others. Separate it from the previous entry with a comma, and give it a name no other group on the site is using.

Removing a location

Delete its entire object, from the opening { to the closing }. If it wasn't the last entry in the array, remove the trailing comma too.

Updating a number

Edit the relevant defaultNumber or utmMap value in place, then re-publish. No other part of the config needs to change.