Tutorial: How to add forms to Store-Locator plugin in WordPress

Yesterday I had to add some custom forms to a WordPress plugin called Google Maps Store Locator for WordPress (version 1.2.28) and found it’s not as straight-forward as one might expect. After about forty-five minutes of digging through all of the plugin’s files, I located four that were of use to me:

  • /store-locator/view-locations.php
  • /store-locator/add-locations.php
  • /store-locator/generate-xml.php
  • /store-locator/js/store-locator.js

By making additions to these four files as well as the store-locator database, you can add custom form fields to the plugin that actually store data and, of course, display this data to the user!

Step 1: Add custom fields (or “columns”) to the wp_store_locator table

We need to add columns to the table named wp_store_locator in our WordPress database so that our custom info can be stored somewhere. We are going to add our columns after the last column in the table (which should be named sl_neat_title).

So, using phpMyAdmin or any other database administration tool, add your custom columns. For this tutorial, I’m going to add sl_creditcard and sl_giftcard to keep track of which stores allow the use of credit cards or gift cards. Notice that I included the sl_ prefix. This is necessary because the plugin expects every column in the table to have this prefix.

Note: From now on when you see “creditcard” or “giftcard” OR “sl_creditcard” or “sl_giftcard” OR “Credit Card” or “Gift Card” this is where you can insert the names of your custom fields.

Before adding the custom fields

Above: Database table wp_store_locator before adding custom fields

Above: Database table wp_store_locator after adding the fields sl_creditcard and sl_giftcard

Above: Database table wp_store_locator after adding custom fields

Step 2: Modify view-locations.php, and add-locations.php

We need to modify these two files so the custom forms and info show up in the admin panel when the admin tries to add, edit, remove, or view locations.

In add-locations.php we must append our custom form field HTML. Opening the file initially and looking at lines 98 to 100 you will see:

“.__(”Hours”, $text_domain).”<br><input name=’sl_hours’><br><br>
“.__(”Phone”, $text_domain).”<br><input name=’sl_phone’><br><br>
“.__(”Image (shown on map with location)”, $text_domain).”<br><input name=’sl_image’><br><br>

To add form fields for the fields we added to the database (sl_creditcard and sl_giftcard), simply do the following:

“.__(”Hours”, $text_domain).”<br><input name=’sl_hours’><br><br>
“.__(”Phone”, $text_domain).”<br><input name=’sl_phone’><br><br>
“.__(”Credit Card“, $text_domain).”<br><input name=’sl_creditcard‘><br><br>
“.__(”Gift Card“, $text_domain).”<br><input name=’sl_giftcard‘><br><br>
“.__(”Image (shown on map with location)”, $text_domain).”<br><input name=’sl_image’><br><br>

Next, in view-locations.php, we will have to make three additions. First, on lines 153 to 155 find:

<th><a href='".ereg_replace("&o=$_GET[o]&d=$_GET[d]", "", $_SERVER[REQUEST_URI])."&o=sl_hours&d=$d'>".__("Hours", $text_domain)."</th>
<th><a href='".ereg_replace("&o=$_GET[o]&d=$_GET[d]", "", $_SERVER[REQUEST_URI])."&o=sl_phone&d=$d'>".__("Phone", $text_domain)."</a></th>
<th><a href='".ereg_replace("&o=$_GET[o]&d=$_GET[d]", "", $_SERVER[REQUEST_URI])."&o=sl_image&d=$d'>".__("Image", $text_domain)."</a></th>";

And do the following:

<th><a href='".ereg_replace("&o=$_GET[o]&d=$_GET[d]", "", $_SERVER[REQUEST_URI])."&o=sl_hours&d=$d'>".__("Hours", $text_domain)."</th>
<th><a href='".ereg_replace("&o=$_GET[o]&d=$_GET[d]", "", $_SERVER[REQUEST_URI])."&o=sl_phone&d=$d'>".__("Phone", $text_domain)."</a></th>
<th><a href='".ereg_replace("&o=$_GET[o]&d=$_GET[d]", "", $_SERVER[REQUEST_URI])."&o=sl_creditcard&d=$d'>".__("Credit Card", $text_domain)."</a></th>
<th><a href='".ereg_replace("&o=$_GET[o]&d=$_GET[d]", "", $_SERVER[REQUEST_URI])."&o=sl_giftcard&d=$d'>".__("Gift Card", $text_domain)."</a></th>
<th><a href='".ereg_replace("&o=$_GET[o]&d=$_GET[d]", "", $_SERVER[REQUEST_URI])."&o=sl_image&d=$d'>".__("Image", $text_domain)."</a></th>";

Then on lines 189 to 191 find:

<td><input name=’hours-$value[sl_id]‘ value=’$value[sl_hours]‘></td>
<td><input name=’phone-$value[sl_id]‘ value=’$value[sl_phone]‘></td>
<td><input name=’image-$value[sl_id]‘ value=’$value[sl_image]‘></td>”;

And do the following:

<td><input name=’hours-$value[sl_id]‘ value=’$value[sl_hours]‘></td>
<td><input name=’phone-$value[sl_id]‘ value=’$value[sl_phone]‘></td>
<td><input name=’creditcard-$value[sl_id]‘ value=’$value[sl_creditcard]‘></td>
<td><input name=’giftcard-$value[sl_id]‘ value=’$value[sl_giftcard]‘></td>
<td><input name=’image-$value[sl_id]‘ value=’$value[sl_image]‘></td>”;

Then on lines 217 to 219 find:

<td>$value[sl_hours]</td>
<td>$value[sl_phone]</td>
<td>$value[sl_image]</td>”;

And do the following:

<td>$value[sl_hours]</td>
<td>$value[sl_phone]</td>
<td>$value[sl_creditcard]</td>
<td>$value[sl_giftcard]</td>
<td>$value[sl_image]</td>”;

Whew! Feel free to upload the files you just worked on. You can view the fruits of your labor by going to your WordPress Dashboard and clicking “Manage Locations” or “Add Locations” under the “Store Locator” menu. Your custom fields should show up like this:

Result of adding code to add-locations.php

Above: Result of adding code to add-locations.php


Result of adding code to view-locations.php

Above: Result of adding code to view-locations.php

Step 3: Modify generate-xml.php and store-locator.js

We need to modify these two files so our custom info shows up on the front end when the user interacts with the actual “store locator.”

Modifying generate-xml.php is a bit more tricky than duplicating HTML (like we did previously) because we must add our custom fields (sl_creditcard and sl_giftcard) to a SQL query. But follow along closely and everything should turn out well!

Open generate-xml.php and on line 43 find:

$query = sprintf(”SELECT sl_address, sl_store, sl_city, sl_state, sl_zip, sl_latitude, sl_longitude, sl_description, sl_url, sl_hours, sl_phone, sl_image,( $multiplier * acos( cos( radians(’%s’) ) * cos( radians( sl_latitude ) ) * cos( radians( sl_longitude ) – radians(’%s’) ) + sin( radians(’%s’) ) * sin( radians( sl_latitude ) ) ) ) AS sl_distance FROM “.$wpdb->prefix.”store_locator HAVING sl_distance < ‘%s’ ORDER BY sl_distance”,

And do the following:

$query = sprintf(”SELECT sl_address, sl_store, sl_city, sl_state, sl_zip, sl_latitude, sl_longitude, sl_description, sl_url, sl_hours, sl_phone, sl_image, sl_creditcard, sl_giftcard,( $multiplier * acos( cos( radians(’%s’) ) * cos( radians( sl_latitude ) ) * cos( radians( sl_longitude ) – radians(’%s’) ) + sin( radians(’%s’) ) * sin( radians( sl_latitude ) ) ) ) AS sl_distance FROM “.$wpdb->prefix.”store_locator HAVING sl_distance < ‘%s’ ORDER BY sl_distance”,

Then, on line 69 to 72 find:

echo ‘hours=”‘ . parseToXML($row['sl_hours']) . ‘” ‘;
echo ‘phone=”‘ . $row['sl_phone'] . ‘” ‘;
echo ‘image=”‘ . $row['sl_image'] . ‘” ‘;
echo “/>\n”;

And do the following:

echo ‘hours=”‘ . parseToXML($row['sl_hours']) . ‘” ‘;
echo ‘phone=”‘ . $row['sl_phone'] . ‘” ‘;
echo ‘image=”‘ . $row['sl_image'] . ‘” ‘;
echo ‘creditcard=”‘ . $row['sl_creditcard'] . ‘” ‘;
echo ‘giftcard=”‘ . $row['sl_giftcard'] . ‘” ‘;

echo “/>\n”;

Okay, we’re almost there! All that’s left is store-locator.js

Open store-locator.js and on lines 61 to 63 find:

var hours = markers[i].getAttribute(’hours’);
var phone = markers[i].getAttribute(’phone’);
var image = markers[i].getAttribute(’image’);

And do the following:

var hours = markers[i].getAttribute(’hours’);
var phone = markers[i].getAttribute(’phone’);
var creditcard = markers[i].getAttribute(’creditcard‘);
var giftcard = markers[i].getAttribute(’giftcard‘);

var image = markers[i].getAttribute(’image’);

Then, on line 66 find:

var marker = createMarker(point, name, address, “”, description, url, hours, phone, image);

And do the following:

var marker = createMarker(point, name, address, “”, description, url, hours, phone, creditcard, giftcard, image);

Then, on lines 139 to 141 find:

var hours = markers[i].getAttribute(’hours’);
var phone = markers[i].getAttribute(’phone’);
var image = markers[i].getAttribute(’image’);

And do the following:

var hours = markers[i].getAttribute(’hours’);
var phone = markers[i].getAttribute(’phone’);
var creditcard = markers[i].getAttribute(’creditcard‘);
var giftcard = markers[i].getAttribute(’giftcard‘);

var image = markers[i].getAttribute(’image’);

Then, on lines 143 find:

var marker = createMarker(point, name, address, homeAddress, description, url, hours, phone, image);

And do the following:

var marker = createMarker(point, name, address, homeAddress, description, url, hours, phone, creditcard, giftcard, image);

Then, on lines 145 find:

var sidebarEntry = createSidebarEntry(marker, name, address, distance, homeAddress, url);

And do the following:

var sidebarEntry = createSidebarEntry(marker, name, address, distance, homeAddress, url, creditcard, giftcard);

Then, on lines 154 find:

function createMarker(point, name, address, homeAddress, description, url, hours, phone, image) {

And do the following:

function createMarker(point, name, address, homeAddress, description, url, hours, phone, creditcard, giftcard, image) {

Then, on lines 163 to 164 find:

if (hours!=”") {more_html+=”<br/><b>Hours:</b> “+hours;} else {hours=”"}
if (phone!=”") {more_html+=”<br/><b>Phone:</b> “+phone;} else {phone=”"}

And do the following:

if (hours!=”") {more_html+=”<br/><b>Hours:</b> “+hours;} else {hours=”"}
if (phone!=”") {more_html+=”<br/><b>Phone:</b> “+phone;} else {phone=”"}
if (creditcard!=”") {more_html+=”<br/><b>Credit Card:</b> “+creditcard;} else {creditcard=”"}
if (giftcard!=”") {more_html+=”<br/><b>Gift Card:</b> “+giftcard;} else {giftcard=”"}

Then, on line 188 find:

function createSidebarEntry(marker, name, address, distance, homeAddress, url) {

And do the following:

function createSidebarEntry(marker, name, address, distance, homeAddress, url, creditcard, giftcard) {

Then, on line 197 find:

var html = ‘<center><table width=”96%” cellpadding=”4px” cellspacing=”0″ class=”searchResultsTable”><tr><td width=”30%” style=”padding-right:4px” valign=”top”><b>’ + name + ‘</b><br>’ + distance.toFixed(1) + ‘ ‘ + sl_distance_unit + ‘</td><td width=”40%” valign=”top”>’ + street + ‘<br/>’ + city + state_zip +’ </td><td width=”30%” valign=”top” style=”text-align:right”>’ + link + ‘<a href=”http://’ + sl_google_map_domain + ‘/maps?saddr=’ + homeAddress + ‘&daddr=’ + address + ‘” target=”_blank” class=”storelocatorlink”>Directions</a></td></tr></table></center>’;

And do the following:

var html = ‘<center><table width=”96%” cellpadding=”4px” cellspacing=”0″ class=”searchResultsTable”><tr><td width=”30%” style=”padding-right:4px” valign=”top”><b>’ + name + ‘</b><br>’ + distance.toFixed(1) + ‘ ‘ + sl_distance_unit + ‘<br>Credit Card: ‘ + creditcard + ‘<br>Gift Card: ‘ + giftcard + ‘</td><td width=”40%” valign=”top”>’ + street + ‘<br/>’ + city + state_zip +’ </td><td width=”30%” valign=”top” style=”text-align:right”>’ + link + ‘<a href=”http://’ + sl_google_map_domain + ‘/maps?saddr=’ + homeAddress + ‘&daddr=’ + address + ‘” target=”_blank” class=”storelocatorlink”>Directions</a></td></tr></table></center>’;

Congratulations, if you’ve followed the steps correctly your custom fields should be showing up on the front end like this:

Above: Our custom fields on the front end!

Above: Our custom fields on the front end!

This tutorial was written by Joel Kuczmarski, a web designer in Chicago working for Blue Print Design Studio. Send any personal comments or questions to joelk [at] blueprintds [dot] com

11 Responses to “Tutorial: How to add forms to Store-Locator plugin in WordPress”


  1. Thomas said:

    Awesome. Will give this a go when I get a chance. Thanks!


  2. Great Tut!!!
    Was very helpfull, thanks a lot for sharing.


  3. Thanks for the tips – check out our store locator too http://www.prometheussprings.com/stores


  4. This was helpful. I’m looking to set this up, but use WP_Posts database with custom fields instead of a new table.

    This works better for my implementation because I want an SEO-friendly individual page for each location and also access to functions only available on posts/pages.

    I’m thinking I could change similar pages in SL to look to and add to the Posts table in a specific category instead of this separate table. Does this sound possible and/or is their a better solution?


  5. Thomas said:

    Any thoughts on where we could implement adsense map units into this plugin per these instructions:

    http://code.google.com/apis/maps/documentation/services.html#AdvertisingAdUnit


  6. I’ve been searching for this kind of tut for quite some time. Thank you. One request, could you add a pdf of this tutorial. Due to vision issues I need to print stuff like this and with the “print this” feature the end result is so small I can’t hardly see it let alone read it. Thanks again for the great tutorial.


  7. I’ve just started my search for a WP compatible store locator plugin and found your tutorial about adding custom fields. Thanks for a great detailed post!

    What I am wondering about this plugin is the ability to add custom fields to search on. I’ll jump over to the plugin forum and have a look.


  8. Thanks for the tutorial, it helps a lot :)

    I would like to add more interactivity to the map, which is to allow user to add their store(point) visually on the map (the point will then stored in the database)- user should field all the neccessary details first (similiar to what we fill in the admin panel in ‘add location’).

    Apart from that, user can search according to categories/attributes (can choose more than 1). Example is user want to search for ‘restaurant’ and ‘furniture’ at the same time, so that the result will only show the store/business with the desired attributes.

    How could i do that?

    Please advice which file should i modify and tips on the coding part.

    Best regards,
    Faliq


  9. Josephine said:

    do you know by chance how to remove the search form and also display all the list of stores? Just wonder.


  10. Very excellent tutorial, it worked like a champ. I do have one question about it though.

    In the view under the map, my fields have more text in them than yours, therefore my text wraps many times and its kind of hard to view. It looks like there is 3 columns and its bound to the width of the first column.

    Is there a way to display my text the full width of the 3 columns?

    Thanks,
    Jake


  11. Great Tutorial… Thanks for sharing.

Leave a Comment!