PHP: Geotargeting von Inhalten zwecks regionaler Anpassung
Geotargeting ist die Bezeichnung für das selektive (Nicht-)Zugänglichmachen von Webinhalten, je nachdem, aus welcher geographischen Region der Nutzer die Anfrage an die entsprechende Website stellt. Bekannt und in der Netzgemeinde berüchtigt ist diese Technologie beispielsweise bei YouTube-Videos, die aus urheberrechtlichen Gründen in Deutschland nicht abgespielt werden können. Aber auch zur Personalisierung von Werbung und der Auswahl der passendsten Suchtreffer setzt Google Geotargeting ein. Fernseh- und Radiosender ermöglichen oft Livestreams ihrer Programminhalte, dürfen aufgrund der Rechtslage aber oft ebenfalls die Verbreitung dieser Streams nur auf bestimmte Länder beschränken. Als Feature erlaubt es Geotargeting freilich auch, Inhalte einer Website ganz direkt auf Kunden des jeweils anfragenden Landes abzustimmen. Denkbar sind - verbunden mit der ebenfalls möglichen Abfrage der Browsersprache im User-Agent - zusätzliche Hinweise oder Artikel in der Landessprache.
Welche Gründe man auch haben mag, Geotargeting einzusetzen - technisch steht und fällt dessen Realisierung mit einer umfassenden Datenbank, die IP-Adressräume geographisch zuzuordnen in der Lage ist. Eine solche Datenbank stellt freundlicherweise das US-Unternehmen MaxMind unter folgendem URL zur Verfügung:
→
http://www.maxmind.com/en/geolite
Dort wird unter der Open-Source-Lizenz
Creative Commons Attribution-ShareAlike 3.0 Unported License eine entpackt etwa 12 MB große CSV-Datei zum Download angeboten. Die Nutzung der Datenbank ist kostenlos, den Lizenzbedingungen wird laut Downloadseite dadurch Genüge getan, in Werbe- und Dokumentationstexten, die Features oder die Benutzung der Datenbank hervorheben, die Herkunft der Daten deutlich zu erwähnen. Nach den Angaben des Unternehmens ist diese Datenbank nicht ganz so genau wie die ebenfalls erhältliche kommerzielle Version, aber garantiert dennoch eine 99,5-prozentige Trefferquote bei der richtigen Zuordnung von IPs zu Staaten.
Laden wir die "GeoLite Country"-Daten nun im CSV-Format als ZIP-Datei herunter. Wir erhalten eine 2,3 MB große, gepackte Datei namens
GeoIPCountryCSV.zip. Diese benennen wir schon einmal vorbereitend auf einen späteren MySQL-Import um in
GeoIPCountryCSV.csv.zip.
Im folgenden gehen wir davon aus, dass wir bereits eine leere MySQL-Datenbank namens
geodata vorliegen haben, die bisher keine Tabellen enthält, aber bereits einen User
geouser mit dem Passwort
123456 (dies natürlich nur zu Demonstrationszwecken!) kennt und mittels phpMyAdmin verwaltet wird.
Diese Datenbank füllen wir jetzt. Als erstes erstellen wir eine Tabelle mit dem Namen
geotable und sechs Feldern, die den Spalten der CSV-Datei entsprechen (siehe auch Abb. 1):
- IP_START (VARCHAR 50) - Start des IP-Adressbereichs als String
- IP_END (VARCHAR 50) - Ende des IP-Adressbereichs als String
- IP_START_LONG (DOUBLE) - Start des IP-Adressbereichs als doppelt präzise Gleitkommazahl
- IP_END_LONG (DOUBLE) - Ende des IP-Adressbereichs als doppelt präzise Gleitkommazahl
- CTRY_CODE (VARCHAR 2) - ISO-Code des zugehörigen Staates
- CTRY_LONG (VARCHAR 50) - Bezeichnung des zugehörigen Staates in Langform

Abb. 1: Einrichtung der Tabelle
geotable in phpMyAdmin.
Nun zu den eigentlichen Daten. Wir nutzen dazu die Import-Funktion von phpMyAdmin, importieren
GeoIPCountryCSV.csv.zip und wählen (Abb. 2) folgende Einstellungen (wichtig ist vor allem,
\n als Zeilentrenner zu definieren):

Abb. 2: Import-Einstellungen für die CSV-Datei.
Falls der Import fehlschlägt, sollte geprüft werden, ob die PHP-Direktiven
post_max_size und
upload_max_filesize in der
php.ini so gesetzt sind, dass sie die Übertragung von Dateien zulassen, die größer als 2048 KB sind, und diese Direktiven dann ggf. angepasst werden.
Im Erfolgsfall meldet sich phpMyAdmin damit zurück, etwa 170000 Datensätze importiert zu haben. Damit sind die Arbeiten an der Datenbank auch schon abgeschlossen, wie ein Blick in die Tabelle zeigt (Abb. 3):

Abb. 3: Erfolgreicher Import in die Tabelle
geotable.
Die Daten können nun in PHP ausgelesen und verwertet werden. Schauen wir uns einmal dieses Codebeispiel an:
01: 02: 03: 04: 05: 06: 07: 08: 09: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27:
| <?php
$db_server = "127.0.0.1";
$db_name = "geodata";
$db_user = "geouser";
$db_pswd = "123456";
$db_link = mysql_connect($db_server, $db_user, $db_pswd) or die('Fehler '.mysql_error());
mysql_select_db($db_name) or die('Fehler bei der Datenbankauswahl.');
$ip = $_SERVER["REMOTE_ADDR"];
$querytext = "SELECT ctry_code,ctry_long FROM geotable ";
$querytext .= "WHERE IP_START_LONG<=inet_aton('".$ip."') AND IP_END_LONG>=inet_aton('".$ip."')";
$query = mysql_query($querytext);
$ctry_array = mysql_fetch_array($query);
$ctry_name = $ctry_array['ctry_long'];
$ctry_short = $ctry_array['ctry_code'];
echo "Land: ".$ctry_name."<br />";
echo "Abkürzung: ".$ctry_short."<br />";
mysql_close($db_link);
?> |
Nachdem also mit den entsprechenden Credentials ein Datenbanklink auf den Localhost geöffnet wurde, wird ein MySQL-Query formuliert, der jenen Datensatz heraussucht, der mit seinen Start- und Endbereichsangaben (repräsentiert in
double-Form) die IP des Nutzers (konvertiert durch die MySQL-
inet_aton-Funktion) "umschließt". Da die Adressbereiche disjunkt sind, sich also nicht überlappen, können wir sicher sein, dass nur eine einzige Zeile zurückgegeben wird. Im Array
$ctry_array stehen nach Abfrage dann die Felder
ctry_long und
ctry_code, die nun beliebig ausgelesen und weiter eingesetzt werden können. Im Beispiel beschränken wir uns nur darauf, die Inhalte der beiden Felder auszugeben. Wir könnten aber auch problemlos eine Funktion schreiben, die für alle Benutzer, für die
$ctry_short == "ES" (Spanien) ist, die Begrüßung "¡ Hola, muy buenas tardes !" ausgibt und vieles mehr.