4 Steps GPS Tracking System With PHP Javascript (Free Download)

Welcome to a tutorial on how to create a GPS tracking system with PHP and Javascript. Need to track where a vehicle is at? Where an order is, or just making sure that it has been delivered to the right place?

A basic GPS tracking system with PHP and Javascript requires the following components:

  1. A database table to record the last known locations.
  2. PHP library and endpoint to accept and manage the location updates.
  3. A webpage or application to send the rider’s current GPS location to the server.
  4. Lastly, an admin page to track all the riders.

Let us walk through a simple example in this guide – Read on!

ⓘ I have included a zip file with all the source code at the start of this tutorial, so you don’t have to copy-paste everything… Or if you just want to dive straight in.

 

 

TABLE OF CONTENTS

 

DOWNLOAD & NOTES

Firstly, here is the download link to the example code as promised.

 

QUICK NOTES

  • Create a database and import 1-database.sql.
  • Change the database settings in 2-lib-track.php to your own.
  • Access 4a-track.html for the client/rider tracking page, and 4b-admin.html for the demo admin page.
  • Take extra note that GPS geolocation requires https:// to work properly. http://localhost is an exception for testing.
If you spot a bug, feel free to comment below. I try to answer short questions too, but it is one person versus the entire world… If you need answers urgently, please check out my list of websites to get help with programming.

 

EXAMPLE CODE DOWNLOAD

Click here to download the source code, I have released it under the MIT license, so feel free to build on top of it or use it in your own project.

 

 

PHP MYSQL GPS TRACKING

All right, let us now get into the details of a GPS tracking system with PHP and MYSQL.

 

PART 1) DATABASE – LAST KNOWN LOCATION

1-database.sql
CREATE TABLE `gps_track` (
  `rider_id` bigint(20) NOT NULL,
  `track_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `track_lng` decimal(11,7) NOT NULL,
  `track_lat` decimal(11,7) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

ALTER TABLE `gps_track`
  ADD PRIMARY KEY (`rider_id`),
  ADD KEY `track_time` (`track_time`);
Field Description
rider_id Primary key, the rider ID… Or the ID of whatever you want to track.
track_time Time the rider last “checked in”.
track_lng Longitude.
track_lat Latitude.

Yep, that is all we need. Just a table to store the last-known locations of the riders.

 

PART 2) GPS TRACKING PHP LIBRARY

2-lib-track.php
<?php
class Track {
  // (A) CONSTRUCTOR - CONNECT TO DATABASE
  public $pdo = null;
  public $stmt = null;
  public $error = "";
  function __construct () { try {
    $this->pdo = new PDO(
      "mysql:host=".DB_HOST.";dbname=".DB_NAME.";charset=".DB_CHARSET, 
      DB_USER, DB_PASSWORD, [
      PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
      PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
    ]);
  } catch (Exception $ex) { exit($ex->getMessage()); }}

  // (B) DESTRUCTOR - CLOSE CONNECTION
  function __destruct () {
    if ($this->stmt !== null) { $this->stmt = null; }
    if ($this->pdo !== null) { $this->pdo = null; }
  }

  // (C) HELPER FUNCTION - EXECUTE SQL QUERY
  function query ($sql, $data=null) {
    $this->stmt = $this->pdo->prepare($sql);
    $this->stmt->execute($data);
  }
 
  // (D) UPDATE RIDER COORDINATES
  function update ($id, $lng, $lat) {
    $this->query(
      "REPLACE INTO `gps_track` (`rider_id`, `track_time`, `track_lng`, `track_lat`) VALUES (?, ?, ?, ?)",
      [$id, date("Y-m-d H:i:s"), $lng, $lat]
    );
    return true;
  }
 
  // (E) GET RIDER(S) COORDINATES
  function get ($id=null) {
    $this->query(
      "SELECT * FROM `gps_track`" . ($id==null ? "" : " WHERE `rider_id`=?"),
      $id==null ? null : [$id]
    );
    return $this->stmt->fetchAll();
  }
}
 
// (F) DATABASE SETTINGS - CHANGE THESE TO YOUR OWN!
define("DB_HOST", "localhost");
define("DB_NAME", "test");
define("DB_CHARSET", "utf8");
define("DB_USER", "root");
define("DB_PASSWORD", "");
 
// (G) START!
$_TRACK = new Track();

This one looks intimidating at first, but keep calm and analyze slowly.

  • (A, B, G) When $_TRACK = new Track() is created, the constructor will automatically connect to the database. The destructor closes the connection.
  • (C) query() is a simple helper function that runs an SQL query.
  • (D & E) There are only 2 “actual GPS tracking” functions.
    • update() records a rider’s GPS coordinates.
    • get() returns the rider’s last known coordinates.
  • (F) Self-explanatory. Remember to change the database settings to your own.

 

 

PART 3) AJAX ENDPOINT

3-ajax-track.php
<?php
if (isset($_POST["req"])) {
  require "2-lib-track.php";
  switch ($_POST["req"]) {
    // (A) INVALID REQUEST
    default: echo "Invalid request."; break;

    // (B) UPDATE RIDER LOCATION
    case "update":
      echo $_TRACK->update($_POST["id"], $_POST["lng"], $_POST["lat"])
        ? "OK" : $_TRACK->error ;
      break;

    // (C) GET RIDER(S) LAST KNOWN LOCATION
    case "get":
      echo json_encode($_TRACK->get(isset($_POST["id"]) ? $_POST["id"] : null));
      break;
  }
}

The core library is not going to work by itself, so here is the AJAX endpoint. How it works is very simple – Just pass in a $_POST["req"] to specify the request, followed by the required parameters.

Request Description
update Update the location of the given rider. Parameters:

  • rider_id
  • lng
  • lat
get Get the last known location of a given rider. Parameters:

  • rider_id Optional, send nothing to get all riders.

 

 

PART 4) HTML TRACKING PAGES

4A) RIDER TRACKING PAGE

4a-track.html
<div class="row">
  <div class="title">Updated</div>
  <div class="data" id="date"></div>
</div>
<div class="row">
  <div class="title">Latitude, Longitude</div>
  <div class="data">
    <span id="lat"></span>, <span id="lng"></span>
  </div>
</div>

This dummy tracker page is for the delivery staff. Pretty straightforward, it just displays the current GPS coordinates.

 

4a-track.js
var track = {
  // (A) INIT
  rider : 999,   // rider id - fixed to 999 for demo
  delay : 10000, // delay between gps update (ms)
  timer : null,  // interval timer
  hDate : null,  // html date
  hLat : null,   // html latitude
  hLng : null,   // html longitude
  init : () => {
    // (A1) GET HTML
    track.hDate = document.getElementById("date");
    track.hLat = document.getElementById("lat");
    track.hLng = document.getElementById("lng");

    // (A2) START TRACKING
    track.update();
    track.timer = setInterval(track.update, track.delay);
  },

  // (B) SEND CURRENT LOCATION TO SERVER
  update : () => navigator.geolocation.getCurrentPosition(
    pos => {
      // (B1) LOCATION DATA
      var data = new FormData();
      data.append("req", "update");
      data.append("id", track.rider);
      data.append("lat", pos.coords.latitude);
      data.append("lng", pos.coords.longitude);

      // (B2) AJAX SEND TO SERVER
      fetch("3-ajax-track.php", { method:"POST", body:data })
      .then(res => res.text())
      .then(txt => { if (txt=="OK") {
        let now = new Date();
        track.hDate.innerHTML = now.toString();
        track.hLat.innerHTML = pos.coords.latitude;
        track.hLng.innerHTML = pos.coords.longitude;
      } else { track.error(txt); }})
      .catch(err => track.error(err));
    },
    err => track.error(err)
  ),

  // (C) HELPER - ERROR HANDLER
  error : err => {
    console.error(err);
    alert("An error has occured, open the developer's console.");
    clearInterval(track.timer);
  }
};
window.onload = track.init;

The Javascript seems massive once again, but do a quick trace and it should explain itself:

  1. track.init() Runs on page load. Get the HTML elements, create a timer and start tracking on intervals.
  2. track.update() Get the GPS coordinates. Upload them to the server, and update the HTML interface.
  3. track.error() A helper function to deal with errors.

 

 

4B) ADMIN TRACKING PAGE

4b-admin.html
<div id="wrapper"></div>

This dummy admin page fetches the locations of all riders and shows them. In your own project, you may want to display a “nice map” and show where the riders are at.

 

4b-admin.js
var track = {
  // (A) INIT
  delay : 10000, // delay between location refresh
  timer : null, // interval timer
  hWrap : null, // html <div> wrapper
  init : () => {
    track.hMap = document.getElementById("wrapper");
    track.show();
    track.timer = setInterval(track.show, track.delay);
  },
 
  // (B) GET DATA FROM SERVER AND UPDATE MAP
  show : () => {
    // (B1) DATA
    var data = new FormData();
    data.append("req", "get");
 
    // (B2) AJAX FETCH
    fetch("3-ajax-track.php", { method:"POST", body:data })
    .then(res => res.json())
    .then(data => { for (let r of data) {
      let row = document.createElement("div");
      row.className = "row";
      row.innerHTML = 
        `<div class="title">[${r.track_time}] Rider ${r.rider_id}</div>
         <div class="data">${r.track_lat}, ${r.track_lng}</div>`;
      track.hWrap.appendChild(row);
    }})
    .catch(err => track.error(err));
  },
 
  // (C) HELPER - ERROR HANDLER
  error : err => {
    console.error(err);
    alert("An error has occured, open the developer's console.");
    clearInterval(track.timer);
  }
};
window.onload = track.init;
  1. track.init() Runs on page load. Get the HTML elements, starts updating the page in intervals.
  2. track.show() Get data from the server and update the HTML.
  3. track.error() Helper function to deal with errors.

 

 

EXTRA BITS & LINKS

That’s all for the tutorial, and here are a few small extras and links that may be useful to you.

 

IMPROVEMENT IDEAS

  • Map Integration – There are over a dozen map services at the time of writing. See the links below, and pick your poison. I also have a tutorial on using Mapbox, follow the “Get GPS & Generate Map” link below.
  • User/Admin/Rider Login – Secure the AJAX endpoint and pages. See the links below if you don’t have a login system.
  • Tracking History – If you want to keep the travel history.
    • Change the database, set rider_id and track_time as composite primary keys. Better to add a trip_id too.
    • Change the PHP library function update(), simply INSERT a new entry instead of REPLACE.
    • Of course, function get() needs to be updated as well.
    • Be sure to disclose that you are keeping the travel history in the company policy/agreement. Privacy laws can be a pain in some regions.

 

NOT REAL-TIME TRACKING?

Of course, this is not a real-time system. While it is possible to do so, we have to consider the technical limitations and if it is worth doing.

  • Firstly, real-time will drain out the smartphone batteries fast.
  • Secondly, you will need a powerful network infrastructure to support a lot of “always-on” socket connections.
  • Lastly, a very robust server system that is capable of crunching real-time data.

So aye… If someone is willing to shell out that kind of money and thinks that it is beneficial for their business – Then why not?

 

COMPATIBILITY CHECKS

This example works with most modern browsers.

 

LINKS & REFERENCES

 

YOUTUBE TUTORIAL

 

THE END

Thank you for reading, and we have come to the end of this guide. I hope that it has helped you with your project, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!

29 thoughts on “4 Steps GPS Tracking System With PHP Javascript (Free Download)”

    1. Not too sure if leaving an email to invite spam is a good idea… But I will respect that.

      Anyway, go through the entire tutorial and what you are looking for is already there.

  1. Thank you very much you’ve been so helpful
    i have to do a symfony project about geo-tracking application which include dealing with alerts like geofencing, eco-driving and fuel saving.
    if you make a tutorial about these issues that would be very kind of you and thank you again sharing the knowledge is better than sharing monney.

    1. Edit – OpenStreetMap does not provide “direct end-user service”. Look for other map providers such as Mapbox and Thnuderforest that uses maps from OpenStreetMap.

    1. That is a very difficult question, all already answered in the “quick start” section. If you are really new, please do some of your own research and play around with the basic server management stuff first – Set up a simple HTML page, create a database, import dummy database, etc…

Leave a Comment

Your email address will not be published. Required fields are marked *