ZoomInfo’s FormComplete plugin is... potentially pretty cool. 😀 (I take care not to endorse any products here, though I didn’t say anything bad, which is a good sign!)
FormComplete delivers DiscoverOrg enrichment data directly into form fields, so starting from just an email address, you can get most — or even all — of the form fields pre-filled, in B2B at least.
(Note: this is separate from (a) pre-filling form data from Marketo for known leads and from (b) the web browser’s ability to autofill from previously stored data.)
The problem, as one of my clients put it well, is that it can be kind of creepy. Seeing your personal data evidently loading from a mysterious service, especially if you know you don’t have that data saved in the browser, ain’t so good:
(The inverse relationship between creepiness and friction can extend to activity tracking as well. But I digress.)
Much better would be having fields that are populated by FormComplete/DiscoverOrg not show up at all. So all fields other than Email are hidden to start, and only those that remain empty after the lookup, if any, are unhidden:
So I set out to reverse-engineer the ZoomInfo logic (since it’s sparsely documented, to put it kindly) and hook it into the Marketo Forms 2.0 JS API and came up with something pretty good.
The setup within ZoomInfo — you have to be at least a trial customer — involves getting a unique formId
for their embed code (that ZoomInfo form ID is not related to the Marketo form ID) and telling them which fields you want to return.
Their pricing, I believe, is based on how much firmographic/technographic info you want, so in this case we’ll start with the most basic tier: First, Last, Phone, Title, and Company.
No need for anything too fancy in Form Editor. Just sure all the possible ZoomInfo fields are on the form (they won’t be dynamically injected, so they need to be in Form Editor explicitly).
The fields may or may not be marked Required, and potentially some could be Hidden. The assumption in the code is that any non-Hidden field that’s set up in ZI, but for which ZI doesn’t have data, will be shown to the end user.
Ergo, if Company is a Text field on the form, and ZI doesn’t know the person’s Company, then Company is revealed so they can fill it in.
If you want to send ZI’s info to Marketo whether it’s empty or not, and never show it to the end user, then you’d set the field as Hidden in Form Editor, not Text.
A prerequisite for any such project is pinpoint, client-side control over the visibility of fields that are set to always-on, always-visible in Form Editor — that is, not in the Progressive Profiling block, and not of type Hidden.
And the way to get that control is the FormsPlus-Tag JS library, available from this link: teknkl-formsplus-tag-0.2.3.js. Download the file to your server — please don’t try to serve it from my CDN, it’s not guaranteed to be cross-domain-linkable — and include it as a remote <script>
anywhere after the Forms 2.0 embed code and it’ll make you very happy.
FormsPlus-Tag adds a data-wrapper-for
attribute to the rows and columns of the form DOM. The value is a space-delimited list of all the fields that are inside the element. (In the example below, it’s a single-column form, but it also works with multi-column forms, where the value would be like data-wrapper-for="Email FirstName LastName"
, just like a class
attribute.)
This simple addition to the markup allows you to hide rows and columns using CSS styles. For a simple, admittedly off-topic example: imagine you want to dynamically hide the Company if some other conditions on the page (not just on the form!) are met.
You could add a class no-company
to the <form>
element before you load FormsPlus-Tag, and have this CSS:
.mktoForm {
visibility: hidden;
position: absolute;
}
.mktoForm[data-initial-wrapper-tagging-complete="true"] {
visibility: visible;
position: static;
}
.mktoForm.no-company > .mktoFormRow[data-wrapper-for~=Company] {
display: none;
}
Note the .mktoForm
as a whole is hidden until FormsPlus-Tag has added its special “I’m done tagging” flag, data-initial-wrapper-tagging-complete="true"
, to the form element. Otherwise, people would see Company for a moment before it disappears. You don’t want that!
FormsPlus-Tag also does a lot more than this, but I don’t want to get bogged down today. The important thing is we do have a way to selectively unhide fields. Now over to ZoomInfo.
Turned out there were 2 different things to hack away at on the ZoomInfo side:
<input>
s with the values, even though it had fired the callback and seemingly passed control over to JS.I’ll just dip a bit into each area.
Figuring out the callback logic was pretty easy: it’s not publicly documented, but it is built-in. So I didn’t need to hack the Ajax call or anything. You can add a callbacks.onMatch
function to the global window._zi
object, before injecting the ZoomInfo script:
window._zi = {
callbacks: {
onMatch: function(ziFieldsObj){
// do something with the fields in ziFieldsObj (a JS Object)
}
}
};
The harder part, surprisingly, was stopping ZI from filling fields. Normally, you assume a callback function would let you return false;
or set dontDoYourDefaultThing = true;
or something like that to stop the out-of-the-box behavior from happening. But there’s no such function here, it just assumes you want it to fill the fields anyway!
A little more peering at their code showed a pretty easy workaround. If you set the attribute data-hasusertyped
to "true"
on an element, ZoomInfo thinks the person has overridden the ZoomInfo-supplied data with their own. So you can just add that attribute to all fields to start out. That gives you complete control from JS.
You’ll need the teknkl-formsplus-tag-0.2.3.js file provided above, and these 2 ZoomInfo-specific files:
teknkl-zoominfo-smartreveal-1.0.1.css
teknkl-zoominfo-smartreveal-1.0.1.js
As with the FormsPlus-tag file, please download and re-upload to your own server.
The CSS is very simple. I wanted a smooth reveal of the empty fields instead of just blasting them into view, so it transition
-s the height. You’ll be able to tweak/remove that effect if you know CSS.
The JS is quite precise and I don’t recommend modifying it on your own. If something doesn’t make sense or seems to be missing just ask me. It also has a number of advanced, optional behaviors that aren’t likely to be necessary. (I’d thought during development that the UX might be weird in some edge cases. Turned out those cases were covered but I left the advanced code in there anyway.)
To deploy the solution, include the 3 remote files in the following order, after a li’l config block:
<script>
window.smartZIRevealUserConfig = {
ziManagedFields : [
"Email",
"FirstName",
"LastName",
"Phone",
"Title",
"Company"
],
ziLookupField : "Email",
ziFormId : "s8YcuR7L0CVxStvxZ2wH"
};
</script>
<link id="teknkl-ZoomInfo-CSS-1.0.1" rel="stylesheet" href="https://yourserver.example.com/teknkl-zoominfo-smartreveal-1.0.1.css">
<script id="teknklFormsPlus-Tag-0.2.3" src="https://yourserver.example.com/teknkl-formsplus-tag-0.2.3.js"></script>
<script id="teknklZoomInfo-JS-1.0.1" src="https://yourserver.example.com/teknkl-zoominfo-smartreveal-1.0.1.js"></script>
(This above completely replaces the default ZoomInfo-provided embed code.)
The config block is simple. ziManagedFields
are all the same fields you set up in ZoomInfo’s app. ziLookupField
is almost certainly going to be capital-E Email
, but hey, there might be some weird exception, so it’s configurable. ziformId
is the ZoomInfo-assigned form ID (remember, nothing to do with the Marketo form ID).
There’s also a special “developer-only” mode (not my creation — it’s a ZoomInfo feature, but the code lets you enable it easily). Enter dev mode by adding the special hash #dev
to your page URL. In this mode, you can use 1 of 3 test addresses:
full-match@zoominfo.com
partial-match@zoominfo.com
no-match@zoominfo.com
Each of those addresses sends back a selection of hard-coded fields, so you can see what happens when/some/none of the fields are filled. Dev mode doesn't count any API calls/rate limits against your ZoomInfo subscription, which is great!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.