© 2015 X2Engine Inc.
Web Lead Capture via API (legacy; pre-3.5.6)
Contents
Introduction
This version the Web Lead API is only compatible with X2CRM versions <= 3.5.6
Our web lead from editor allows for some solid forms that the average user can put on their website without much issue. Little to no development knowledge is required, and the form integrates perfectly with X2 from a web lead standpoint as well as our web tracker. But for some users, this isn't enough. Many websites already have forms in use that they don't want to sacrifice or change, but still want all of the features of X2 integration. The good news is that with some basic development knowledge this is a very doable project. This article will walk you through setting up a custom web lead capture script which will take POST data from your web lead form and enter it into X2 via API. The later sections of the article will cover some advanced customizations to make the form work better for you.
The Basics
The first thing you'll need to do is create some form of capture script, and call it whatever you like. I tend to use things like "contactForm" to be very clear what it is. This script should go onto the same webserver as your X2CRM installation so that cookies can be properly set, but it doesn't need to be in the same folder. You'll also need to make sure that the "APIModel.php" class file is somewhere accessible. This file is provided in protected/models/ of your X2 installation, and can be copied to anywhere you like. So, what does this capture script currently look like?
<?php
require 'APIModel.php';
$attributes = $_POST;
That's about it for now. The first thing we do is include the APIModel class, which will allow for easy use of X2's API. This class is heavily documented and provides a variety of wrapper methods for common X2 API functions. It also behaves in many ways just like a regular model, so if you have any X2 development experience you'll likely feel right at home.
The next steps in this process are to initialize the API Model correctly. To do that, you'll need three things:
- The username of a user with permission to create Contacts
- The user API key of that same user
- The URL of your X2 installation.
The first is easy to obtain, and I recommend using "admin" as it's simpler. From there, go to the "Users" page, click on "admin" in the grid, and select "Update User" from the left sidebar menu. You should see a field called API Key. You can set this to whatever you want, but they're randomly generated upon user creation. For example, mine on my development server at the time of this writing is "7uoHGRIBlb0lKym56ieiDf3c7idzCCP7"
The API Model takes 3 parameters for its constructor. You may be able to guess that they are the username, API key, and URL of the server. So now our code should look something like this:
$contact = new APIModel('admin','7uoHGRIBlb0lKym56ieiDf3c7idzCCP7','www.host.domain/path/to/x2');
That's the most important step to get right. If you don't properly set up your API model, all of the requests will fail and this whole process will be useless. Please double check you have entered in the information correctly.
Now we need to be able to set the data of our Contact. Most pre-built forms do not follow the same naming conventions of the database columns in X2. As such, I like to build a field map that will translate the information in the POST data into usable information by X2. If all your field names match ours exactly, then this step isn't required and you can simply say $contact->attributes = $attributes;
$fieldMap = array( // This map should be of the format 'your_fieldname'=>'x2_fieldname',
'first_name'=>'firstName',
'last_name'=>'lastName',
'mobile'=>'phone2',
'information'=>'backgroundInfo',
);
foreach($attributes as $key=>$value){
if(isset($fieldMap[$key])){
$contact->{$fieldMap[$key]}=$value; // Found in field map, used mapped attribute
}else{
$contact->$key=$value; // No match anywhere, assume it's a Contact attribute
}
}
This code will now loop through your POST data and set them to the Contact attributes based on your field map. Note that if a match isn't found in the map, it assumes the names are the same in your form as they are in X2.
The last component of the custom form is submitting the data, setting the tracking cookie, and redirecting. The tracking cookie is used for the web tracker which is a part of our professional edition. Even if you're running open source it might be worth setting this so you can have the cookies stored in case you upgrade in the future. You can do these like so:
$contact->contactCreate(); // Call API to create contact
if(!empty($contact->trackingKey)){
setcookie('x2_key',$contact->trackingKey,time()+31536000,'/path/to/x2','host.domain'); // Set cookie
}
Header('Location: host.domain/redirect'); // Redirect to homepage
And be sure to replace '/path/to/x2' with your web path, 'host.domain' with your server URL, and the redirect with whatever URL you want visitors to be sent to after filling out the form. Now, if we put it all together, the final product should look something like this:
<?php
require 'APIModel.php';
$attributes = $_POST;
$contact = new APIModel('admin','7uoHGRIBlb0lKym56ieiDf3c7idzCCP7','www.host.domain/path/to/x2');
$fieldMap = array( // This map should be of the format 'your_fieldname'=>'x2_fieldname',
'first_name'=>'firstName',
'last_name'=>'lastName',
'mobile'=>'phone2',
'information'=>'backgroundInfo',
);
foreach($attributes as $key=>$value){
if(isset($fieldMap[$key])){
$contact->{$fieldMap[$key]}=$value; // Found in field map, used mapped attribute
}else{
$contact->$key=$value; // No match anywhere, assume it's a Contact attribute
}
}
$contact->contactCreate(); // Call API to create contact
if(!empty($contact->trackingKey)){
setcookie('x2_key',$contact->trackingKey,time()+31536000,'/path/to/x2','host.domain'); // Set cookie
}
Header('Location: host.domain/redirect'); // Redirect to homepage
And that's it! For a basic web lead capture script, this is all we need. The code listed here should be totally functional to copy and paste over to your own server, as long you define your own field map, configure the APIModel constructor, and replace URLs properly. However, it's pretty basic and there's at least one extra feature that might be required to work correctly.
Advanced Topics
TODO: Add this section
Duplicate Handling
The basic script doesn't have any sort of handling for finding people who submit the form more than once. Instead of simply creating duplicate records, you can do a few little tricks to make this part of the lead script smarter. First things first, we need a way to check for a duplicate Contact. Before you set any attributes on the Contact model which is the code that has: foreach($attributes as $key=>$value){ you'll want to add this:
$contact->email=$attributes['email'];
$contact->contactLookup();
if($contact->responseCode!='404'){
// Code to handle duplicates here.
}
First, we set the email of the Contact because that's the primary way to look for duplicates. Then we call the "contactLookup" function which does exactly what it says--looks up a Contact. If we can't find any, the response code will be a 404. So all we do then is make our if statement check if the response was something other than a 404 and handle the duplicate in here! There's a few different ways we can deal with that. All of the code in the following blocks starts at the response code check. The first is a simple redirect, ignoring the duplicate record, which would look like this:
if($contact->responseCode!='404'){
Header("Location: host.domain");
}
Replacing "host.domain" with your own redirect location. The next step is a little more advanced, which would be to instead detect empty fields in the Contact record and fill them with any submitted data, while preserving data already on the record. The code to do that would look something more like this:
if($contact->responseCode!='404'){
foreach($attributes as $key => $value){ // Try to set any empty attributes
if(isset($fieldMap[$key]) && empty($contact->{$fieldMap[$key]})){ // Check if value is empty + found in field map
$contact->{$fieldMap[$key]} = $value; // Found in field map, used mapped attribute
}elseif(empty($contact->$key)){ // Just check if value is empty
$contact->$key = $value; // No match in field map, assume it's a Contact attribute
}
}
$contact->contactUpdate();
}
Adding Tags
Lead Logging
Custom Redirects
Advanced Final Product
With all the bells and whistles! TODO: Add this