Tuesday, April 9, 2013

Create Web Widget in iFrame

Do you want to create widgets that can deliver different content based on visitor's browser and location? It is not that difficult. In this tutorial I'll assume that you have a basic knowledge of JSON, XML and jQuery.
This tutorial assumes that you have cURL and simpleXML functions enabled on your web server.

The main problem is to beat same origin policy - page in iFrame and parent page must be from same domain unless you use JSON to create and load an iFrame element with HTML page from your web server.
Now you can make widgets that for your site just like Twitter does.
First you need to embed widget's small JavaScript code. Check out highlighted line in file index.html:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Page with widget</title>
<style type="text/css">
body {
 font-family:"Palatino Linotype", "Book Antiqua", Palatino, serif;
}
#header {
 background-color:#999;
}
#footer {
 background-color:#999;
}
</style>
</head>
<body>
<div id="container">
  <div id="header">
    <h1>Header</h1>
  </div>
<div id="mainContent">
<h2>Check out this info:</h2>
<script type="text/javascript" src="http://maxh.heliohost.org/redirect.js"></script>

</div>
  <!-- end #main -->
  <div id="footer">
    <p>Footer</p>
    <!-- end #footer -->
  </div>
  <!-- end #container -->
</div>
</body>
</html>
Now we describe files on our server in web root folder.
Next we need to examine the most important portions of file redirect.js:
document.write('<div id="widget4me"></div>');
...
var jsonp_url = "http:///loader.php?&callback=?";
$.getJSON(jsonp_url, function(data) {
  $("#widget4me").html(data.html);
});
In the above snippet we create a div, later in function the div gets HTML code via JSON. Now that makes possible to do cross site scripting.
Next file is loader.php and here's the complete source code:
<?php
header('content-type: application/json; charset=utf-8');
$h = "<iframe  height='400px' width='500px'  src='http://maxh.heliohost.org/widget.php'>switch on javascript</iframe>";
$arr = array ('html'=>$h);
$json = json_encode($arr);
$callback = $_GET[callback];
echo $callback . '(' . $json . ')';
?>
Highlighted line above shows URL of page from our server is loaded into iFrame.
For next file you need to get API keys from http://developer.quova.com/member/register from Quova geo targeting service and place them in file widget.php - see green lines in listing below. With cURL you send to the API the visitor's IP address and API returns you an XML string with data about user's location (country, city, latitude longitude...), ISP, and type of connection (mobile, cable...) and many other stuff.
With SimpleXML you print necessary data. In production you use that data to serve content based on location and connection speed we here just print the parameters.
Now let's examine file widget.php:
<html>
<head>
<title>GeoTargeting Widget</title>
// Load JavaScript function for cookie handling and unique id generator
<script type="text/javascript" src="http://maxh.heliohost.org/functions.js"></script>
<script type="text/javascript">
// Check if visitor is here for first time
var cm = Get_Cookie("visitor");
if (cm!=null && cm!="")
   {
   document.write("Welcome again user with id:" + cm);
   }
 else
   {
   var rnd = randomID(20);
   document.write("First time here");
   Set_Cookie("visitor",rnd,365);
   }
</script>
</head>
<body>
<hr/>The widget collected following data from GeoLocating API:<br/>
<?php
$ipin = $_SERVER['REMOTE_ADDR'];
$ch = curl_init();
$ver = 'v1/';
$method = 'ipinfo/';
$apikey = '';
$secret = '';
$timestamp = gmdate('U'); // 1200603038
$sig = md5($apikey . $secret . $timestamp);
$service = 'http://api.quova.com/';
curl_setopt($ch, CURLOPT_URL, $service . $ver. $method. $ipin . '?apikey=' . $apikey . '&sig='.$sig . '&format=xml');
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$data = curl_exec($ch);
$headers = curl_getinfo($ch);

// close curl
curl_close($ch);

// return XML data
if ($headers['http_code'] != '200') {
   echo "An error has occurred accessing this IP";
  return false;
} else {
$xml = simplexml_load_string($data);
 foreach ($xml->Network as $item) {
  $h = "Connection:".$item->connection_type."<br/>Speed:".$item->line_speed."<br/>";
 }
// Parse and print data from API
 $xml = simplexml_load_string($data);
 foreach ($xml->Location as $item) {
  $h = $h . "Country:" . $item->CountryData->country."<br/>";
                $h = $h . "State:" . $item->StateData->state."<br/>";
                $h = $h . "City:" . $item->CityData->city."<br/>";
                $h = $h . "Area Code:" . $item->CityData->area_code."<br/>";
                $h = $h . "Latitude:" . $item->latitude."<br/>";
                $h = $h . "Longitude:" . $item->longitude."<br/>";
 }
        $h = $h . "<hr/>PHP collected following info:<br/>IP:$ipin<br/> languages:";
// Print language and referer
        $h = $h . "{$_SERVER['HTTP_ACCEPT_LANGUAGE']} <br/> and reffer:{$_SERVER['HTTP_REFERER']}<br/>";
// Determine keywords used to get to parent page
 $parts = parse_url($_SERVER['HTTP_REFERER']);
 if (isset($parts['query'])) {
     parse_str($parts['query'], $parts['query']);
 }
 $h =$h . "Keywords used to get to the this page(if any):".$parts[query][q];
    echo $h;
}
?>
</body>
</html>
Please read comments for additional info.
In JavaScript block we determine if user is for the first time here and if it is a cookie with random id is assigned.
Keep in mind that license from Quova gets you 2 calls per second and 1000 calls for a day. If your site gets more traffic you need to get a commercial solution.
This tutorial works in IE 7, IE 8, IE 9, Chrome, FireFox, Opera and Safari.

No comments:

Post a Comment