Add Geolocation Information to Your Contact Record

Here’s my solution for adding geolocation information to your contact’s record, from a signup web form locally hosted on your own website. I combined the technique from three other examples found via a Google search, that didn’t do exactly what I needed and modified them to this current solution.

Freegeoip.net
http://www.freegeoip.net
The open source freegeoip.net service allows you grab the IP address and lookup ISP (Internet Service Provider) locality without alerting the user, unlike Google’s geolocation service that prompts the user to give permission to provide their IP. If this is an ethical issue for you or your customers, then this isn’t the appropriate solution. Freegeoip.net has their own usage agreement and number of lookups restrictions as outlined on their website.

Here is a list of available geolocation fields offered by freegeoip.net though their true availability will vary depending on each actual lookup providing data, which won’t always happen in a full dataset.

  • City
  • Region / State (Abbreviation)
  • Region / State (Full Name)
  • Postal Code / ZIP
  • Area code
  • Latitude
  • Longitude
  • Country (Abbreviation)
  • Country (Full Name)
  • IP Address

Create an Infusionsoft Campaign
Create an Infusionsoft campaign with a signup web form and add the hidden fields (assigning blank values) you wish to capture.

I placed the captured geolocation information into the Optional Address fields already created in Infusionsoft to avoid overwriting the actual street or billing addresses with these temporary location values. You could of course create your own custom fields to place these geolocation data values into.

Infusionsoft Optional Street Fields
(the one’s I used in this web form capture example)

inf_field_City3
inf_field_State3
inf_field_PostalCode3
inf_field_Country3

Infusionsoft Custom Field
To capture the IP address you need to create a custom field for a Contact that I called “IP Address”. This field value then is seen as “_IPAddress” when referenced by your web form code. Note the significant underscore in front.

inf_custom_IPAddress

The Geolocation Lookup JQuery Script
Place this script on the web page where your locally hosted web form resides. I placed it at the top of the page before the rest of the form code starts so the geolocation lookup is executed first. This script is what makes everything else work.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
jQuery.ajax( {
  url: '//freegeoip.net/json/',
  type: 'POST',
  dataType: 'jsonp',
  success: function(location) {
    // Update hidden form field variable values
    $('#City3').val(location.city);
    $('#State3').val(location.region_code);
    $('#PostalCode3').val(location.zipcode);
    $('#Country3').val(location.country_name);
    $('#_IPAddress').val(location.ip);
  }
} );
</script>

Web Form Hidden Fields
Add these hidden fields into your locally hosted web form code. If you wish to capture additional fields then add in the appropriate Infusionsoft field & ID names. You can find them by testing your web form from within Infusionsoft’s campaign and looking at the source code to see the hidden field values created.

<input name="inf_field_City3" id="City3" type="hidden" value="" />
<input name="inf_field_State3" id="State3" type="hidden" value="" />
<input name="inf_field_PostalCode3" id="PostalCode3" type="hidden" value="" />
<input name="inf_field_Country3" id="Country3" type="hidden" value="" />
<input name="inf_custom_IPAddress" id="_IPAddress" type="hidden" value="" />

Web Form Other Code
You can use the (styled or un-styled) web form code created by the Infusionsoft campaign and insert on your own website’s page but need to add the hidden fields you wish to capture data for into the form code.

Note the input ID’s match the JQuery script ID’s so when JQuery runs it updates the hidden field values (matching on ID) with the one’s found by the geolocation lookup service. Then when the form is submitted both visible and invisible field values are posted to the Contact record in Infusionsoft.

Heh presto your contact’s optional address fields now have values populated showing their approximate location based on ISP and IP Address lookup. They could of course be using a VPN but this is an imperfect collection method to help you get an idea of where your customer’s are coming from.

The IP Address is populated into your custom field, whichever tab you have placed that field into. I created one called “Geolocation” to make things separate and clear.

Things to Watch Out For
Make sure you have the campaign Published to allow the transfer of the data into the field values. Additionally, make sure you have the same hidden fields created in the campaign form as you are sending via the locally hosted web form otherwise the data does not transfer and you wonder why things aren’t working. Both mistakes that I made and Infusionsoft tech support helped me to figure out.

5 Likes

Excellent post Alastair.

A few years ago I did a Geolocation API script for someone, but they used Maxmind (IP Geolocation and Online Fraud Prevention | MaxMind) for the IP Address Location lookup. Maxmind requires payment, which puts off people from using it.

Your solution is great, and Freegeoip.net allows 15,000 requests per hour. Which is very reasonable, and useful for developers as well.

2 Likes

Hi Pav,

You are most welcome, I am glad if the solution helps you or other Infusionsoft users/developers.

IPv6 Issue
One consideration I found with testing is when the IP address is IPv6 then only the IP Address & Country are the returned values, at least when I was testing via a VPN on my computer to see the results when logged in from different countries.

However at the same time Infusionsoft was able to see the IPv4 version of the address, as shown in the form completion confirmation email, so I am not 100% sure if this was just a local issue during testing or if IPv6 addresses will be correctly translated into IPv4 results allowing better location lookup.

Repeat Signups
Another point to consider is if your contact fills out this or another web form using this geolocation code then the optional address & IP Address fields are updated each time a web form is completed, overwriting the first time values. This isn’t a bug or a fault only a consideration if you HAVE to keep the source address.

Built-in Geolocation
Infusionsoft’s own code automatically grabs the original country language & timezone when a contact is first created and is populated on the Contact first screen under the Global Information section. I know they are doing this to allow sending of campaign emails via time zone as an option.

I wish I knew their back-end IP Address field value to save capturing it in a custom created field. If the IP Address is being given on the confirmation email then they are capturing it for certain already.

Aly

2 Likes

Here are the Google search resources that gave ideas and inspiration to put together this particular solution. All the resources are useful in and of themselves, if you wish to do something similar but different. I claim no originality in my coding solution, just the combination of ideas to meet my needs.

https://blog.novaksolutions.com/tips/get-your-visitors-city-and-state-without-even-asking-for-it/
http://tomnunamaker.com/how-to-capture-ip-address-in-an-infusionsoft-hosted-web-form/

Have a great day!

Aly

1 Like

An update on this code to now include setting of Time Zone.

Many thanks and kudos to @Adrian_Tobey for giving the answer of how to adding the Time Zone to a contact record. Modifying his API technique for external web form use plus using www.freegeoip.net rather than the need for the JavaScript time zone lookup.

Here is the modified jQuery script with the added JSON time_zone variable name pulling from freegeoip.net.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
jQuery.ajax( {
  url: '//freegeoip.net/json/',
  type: 'POST',
  dataType: 'jsonp',
  success: function(location) {
    // Update hidden form field variable values
    $('#City3').val(location.city);
    $('#State3').val(location.region_code);
    $('#PostalCode3').val(location.zipcode);
    $('#Country3').val(location.country_name);
    **$('#TimeZone').val(location.time_zone);**
    $('#_IPAddress').val(location.ip);
  }
} );
</script>

Here’s the modified web form hidden fields to include the Infusionsoft Field inf_field_TimeZone value.

<input name="inf_field_City3" id="City3" type="hidden" value="" />
<input name="inf_field_State3" id="State3" type="hidden" value="" />
<input name="inf_field_PostalCode3" id="PostalCode3" type="hidden" value="" />
<input name="inf_field_Country3" id="Country3" type="hidden" value="" />
**<input name="inf_field_TimeZone" id="TimeZone" type="hidden" value=""/>**
<input name="inf_custom_IPAddress" id="_IPAddress" type="hidden" value="" />
1 Like

Hi Aly,

Great solution, thanks!
I will test it this weekend.

You say you wish you knew where IS stores the IP value they catch when someone fills a form. If you go to Marketing >> Reports >> Web Form Tracking Report, you will get the IP of everyone who has filled a form. Of course this report logs every single optin, so there are a lot of dupes. But that doesn’t matter in my case.

So what I did is just export those reports and only keep Contact ID and IP address, then reimport it to UPDATE the contact records through Admin >> Data Cleanup >> Modify Existing Records. Import the list by syncing it on the “Infusionsoft Contact ID” (very important). This way the contact records are updated. The IP will go in a custom field you have previously set up (or any regular field you want for that matter). If we use the regular list import function, we will simply create a contact record with a new Contact ID, and there will be no way we can merge the new data with the contact records.

Yes, I know, this is a manual method, not practical for everyday use, but to catch up on past optins after we have implemented your method is perfect. I updated more than 10 000 of my contact this way. A breeze!

An idea of a next step, if I didn’t had your solution, would be to create a php script on my server that would pull out that data through API then push it to the contact record the same way.

Thanks for your input !
Bruno Fortin

Hi Bruno,

You are most welcome, I am glad if it helps you.

The solution is working great for myself. The only downside is when people come in through an IP6 address the Free Geo lookup does not translate that automatically into an IP4 address. Have tested taking these IP6 addresses and manually running them through a converter to give an IP4 but sometimes they don’t resolve.

Somehow Infusionsoft’s forms are accurately capturing the IP4 address in all cases. So I have been manually editing records.

If you have any code that can do the conversion consistently accurately I would love to see it. You would likely have to run the JavaScript on the client side (unless you have server access) so it gets too complicated for my liking.

The manual export then import solution may be a solution to partially automate updating records after IP6 to IP4 conversions.

I would say about 20% of people capture with an IP6 address in my experience.

The last point is if they have JavaScript turned off then the geolocation capture does not work. I am looking into modifying our form code to block the form submission, only allowing it if they have JavaScript enabled. Here is a great link with some good ideas.

https://www.codediesel.com/javascript/prevent-form-submissions-with-javascript-disabled/

Aly

Hi Again Aly,

IPV6 doesn’t cause a big problem for me, as long as it can efficiently convert to country equivalent, that’s pretty much all I need. It seems like your javascript will return IP V6 and country anyway in this case, so I’m ok I guess.

I need to find what country my optins come from so I can mail country specifiy offers and not bother my other international clients/prospects.

In my case, I wouldn’t block the optin if it’s an IPV6 address. Not willing to loose a potential sale just to get the stats right.

Same for deactivated javascript. A prospect is a prospect and the money is in the list :wink:

I guess it all depends on each specific use we have, right!

I’ll see if I still need an API to manage the stored IPs and the case being, I will let you know what it can do. It will most definitely be a server side script (mandatory for API use), maybe a Wordpress plugin, in order to simplify management.

Thanks for your time!
Bruno

Hi @Alastair_Greenstreet (and for everyone else),

I need to make you aware that the Freegeoip End Point will stop working on July 1st, 2018.

If you are using the service, you will see the following message:
""deprecation_message": "This API endpoint is deprecated and will stop working on July 1st, 2018. For more information please visit: GitHub - apilayer/freegeoip: IP geolocation web server

You will need to go to their new “ipstack” website (https://ipstack.com/) and set up an account to obtain an API Key. There is documentation on how to use PHP and Javascript versions of their End Points.

NOTE: There is a new gotcha with this new service. Unfortunately the Free Account does not support “https://” protocol, unless you pay for the Premium Service. That means if you have a HTTPS website you cannot use the HTTP protocol via the Javascript way. You will have to go down the PHP route instead.

@Pav

Thank you so much for this heads-up, I had no idea till you gave me the pointer. Will investigate the alternative solutions.

Alastair

Hi Pav,

Looks to me like its worth paying the annual fee for SSL access and using their code with the API key you are given with a license.

I don’t see an easier way to integrate geolocation with the contact record & order forms than this service. Its the ease of the jQuery json integration into web forms and order forms that gives the advantage over other solutions.

I looked at a bunch of WordPress geolocation plugins but none of them seemed to offer a way to easily integrate the results with Infusionsoft forms.

Time to pay the money for the service is my view.

Also one modification I would encourage everyone to make is create their own custom inf_custom_TimeZone field. I found after more use that if the lookup result failed Infusionsoft would do a secondary validation requiring a valid value for timezone to be entered, blocking the form from being submitted. With a custom field this block goes away even if a timezone value can’t be returned.

Aly

Hi Everyone,

New Web Form Code
Here is one example of updated code that works with the paid version of ipstack.

Where “xxx…” equals the unique paid API access code you obtain via the paid subscription.

There are many ways to do this, this being just one example that works for my needs. Please modify the code to return the API field values that suit your needs.

Note:
For clarity and ease of future updating (if the API key value changes) the code example separates the API access key value and assigns it to the variable access_key. Then includes that value into the URL query string.

The ‘/check’ parameter tells api.ipstack.com to dynamically query for the ip address of the person filling out the form, rather than specifying the ip address manually in the URL query string.

The ‘&callback’ parameter specifies the results are returned wrapped into a function. The name of the specified function in this case is ‘data’.

The ‘&output=json’ parameter specifies the results are returned in JSON format rather than XML. JSON is the default format but when specifying the result set is returned wrapped in a function you have to specificy set the output format.

Sub-set Parameters
Where a desired value is part of a sub-set of API results, for example time zone (code) might give a value of EDT (Eastern Daylight Time) you have to specify the exact field value, for example:

time_zone.code

Rather than just time_zone as in the original freegeoip.net code.

You need to check the documentation to see which data results need this sub-set specification. The basic data set values do not but the time zone, currency, connection & security data set field values do.

Custom _TimeZone Field
Experience taught me to use a custom _TimeZone field value rather than the original solution of posting the result back into the system TimeZone field.

The problem being when the time zone lookup didn’t validate with Infusionsoft’s accepted time zone values, the input was rejected, stopping the web form from submitting.

By using a custom field the value is always accepted, there not being any validation so the web form is never prevented from submitting.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
// set your access key
var access_key = 'xxxxxxxxxxxxxxxxxxxxxxxxxx';
jQuery.ajax( {
	url: 'https://api.ipstack.com/check?access_key=' + access_key + '&callback=data' + '&output=json', 
	type: 'POST',
	dataType: 'jsonp',
	success: function(data) {
		// Update hidden form field variable values
		$('#City3').val(data.city);
		$('#State3').val(data.region_code);
		$('#PostalCode3').val(data.zip);
		$('#Country3').val(data.country_name);
		$('#_TimeZone0').val(data.time_zone.code);
		$('#_IPAddress').val(data.ip);
	}
} );
</script>

Hope this helps everyone.

Alastair

Found one crazy adjustment needed to the new code for a certain retrieved value from IPStack.com

Problem Description
If you are trying to retrieve: time_zone.id
(Giving output in the format, for example “America/New York”)

All five main web browsers take the retrieved value from IPStack.com and automatically convert it to the format, for example “EDT” or “EST” upon assigning it to the hidden INPUT field value. This drove me crazy till I figured it out.

Solution
The fix is to assign the retrieved value to a variable first then set the INPUT field value to the variable value. This preserves the correct text format as “America/New York”.

var time_zone_text = (data.time_zone.id);
$('#_TimeZone0').val(time_zone_text);

The full updated code including this fix is shown below.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
// set your access key
var access_key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxx';
jQuery.ajax( {
	url: 'https://api.ipstack.com/check?access_key=' + access_key + '&callback=data' + '&output=json', 
	type: 'POST',
	dataType: 'jsonp',
	success: function(data) {
		// Update hidden form field variable values
		$('#City3').val(data.city);
		$('#State3').val(data.region_code);
		$('#PostalCode3').val(data.zip);
		$('#Country3').val(data.country_name);
		var time_zone_text = (data.time_zone.id);
		$('#_TimeZone0').val(time_zone_text);
		$('#_IPAddress').val(data.ip);
	}
} );
</script>

If you are retrieving time_zone.code then you don’t need this fix for that retrieved data is already in the format “EDT” or “EST”.

Alastair

Vpn connection should be set perfectely. The best way to do this is by checking different providers and testing different software. Here’s a good list of them click here.

1 Like

Hi Everyone,

Just an update on this solution.

Time and experience has taught the need to use custom fields for all geolocation data you wish to collect but especially on fields that are VALIDATED on Infusionsoft’s end.

  • IP Address
  • Time Zone
  • City
  • State
  • Postal Code
  • Country

If you use the pre-built Infusionsoft optional address 3 fields that I initially recommended then occasionally the COUNTRY won’t validate between the values Infusionsoft has in its country table and the values that IPStack returns. This is rare but it does happen.

The validation mismatch causes the form submission TO FAIL for anyone in that country.

For example:

Netherlands (the) - Infusionsoft Value in Optional Address fields
Netherlands - IPStack Value (returned)

Infusionsoft Country Value
Geolocation-Infusionsoft

IPStack Value (Returned via Script)
Placed values on their own custom Geolocation tab.
Geolocation-IPStack

Answer
The answer is simply to create custom fields for all geolocation data you wish to capture, format them as TEXT and do not validate their values so they accept any value returned by IPStack.

Obviously these custom fields are going to have different names so need to be updated in your script, for example here are my field values, yours will vary.

Example Code

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
// set your access key
var access_key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
jQuery.ajax( {
	url: 'https://api.ipstack.com/check?access_key=' + access_key + '&callback=data' + '&output=json', 
	type: 'POST',
	dataType: 'jsonp',
	success: function(data) {
		// Update hidden form field variable values
		$('#_City1').val(data.city);
		$('#_State1').val(data.region_code);
		$('#_PostalCode1').val(data.zip);
		$('#_Country1').val(data.country_name);
		var time_zone_text = (data.time_zone.id);
		$('#_TimeZone0').val(time_zone_text);
		$('#_IPAddress').val(data.ip);
	}
} );

Then for the form fields.

<input name="inf_form_xid" type="hidden" value="xxxxxxxxxxxxxxxxxxxxxx" />
<input name="inf_form_name" type="hidden" value="Your form name goes here" />
<input name="infusionsoft_version" type="hidden" value="1.69.0.71" />
<input name="inf_custom_City1" id="_City1" type="hidden" value="" />
<input name="inf_custom_State1" id="_State1" type="hidden" value="" />
<input name="inf_custom_PostalCode1" id="_PostalCode1" type="hidden" value="" />
<input name="inf_custom_Country1" id="_Country1" type="hidden" value="" />
<input name="inf_custom_TimeZone0" id="_TimeZone0" type="hidden" value="" />
<input name="inf_custom_IPAddress" id="_IPAddress" type="hidden" value="" />

As always I hope this helps people.

Alastair

SCRATCH THIS SOLUTION, at least for now.

The fix for this is beyond my coding abilities so any community support is welcomed from able programmers.

Unfortunately some unscrupulous people have scraped the API key as its in plain sight in the HTML code. Security lesson 1:1 but you learn the hard way.

Until I can figure out a way to call the API key and apply it to the hidden form fields upon submission, without allowing the source code to be saved and the API value revealed this method is insecure.

Your only option is to reset your API session key to prevent pirated use of your paid ipStack subscription and figure out a different way.

Sorry for this SNAFU, I’m not a high level programmer.

Aly

Hi Alastair,

Taking a look online, I have come across this article that lists other Geolocation Tracking Services.

https://ahmadawais.com/best-api-geolocating-an-ip-address/

Having a quick look, there is the dp-ip service: Free Easy-to-Use & Up-to-Date IP Geolocation API | DB-IP
This JS Fiddle page shows an example of it in action: DB-IP API demo - JSFiddle - Code Playground
At least that does not expose an API Key, but has limitations.

You can try going through the other services listed to see if it fits your needs.

Hope that helps.

Hi Pav,

Less Than 1000 Lookups
Thank you for the pointer, they are great resources links and if you need fewer than 1000 geo-lookups a day the db-ip.com option would work great without needing an API key call so be easy to implement in the Javascript code for web & order forms. Definitely an option but unfortunately we do between 1-2000 geo-loookups a day so go over their free limit.

Sessions / Environment Variables / DB Storage / Encryption / Authorization Services
I am likely going to hire a programmer who can figure out a decent solution to this lookup both on a WordPress PHP coded site and (if possible) in a straight Javascript. What I’m reading is the need to use CSRF sessions, or environment variables, database storage, encryption or some such combination of techniques.

A better technique is to use an authorization service but this requires real programming skills.

Server Side API Key Lookup
Most importantly you need the API key submission to be done via server side lookup. However we don’t have server side access, so likely are going to have to find some kind of compromise solution.

Time to pay someone for security!

Alastair

.

Post removed at the request of the original poster