PHP-SEO
Vortrag online unter
www.sblum.de/#!seocampixx2013

Quelltext online unter
github.com/sebastianblum/seocampi
xx2013                                  Sebastian Blum
sebastian blum           www.sblum.de     13.03.2013     1
Agenda

a) PHP-Proxy
   blogger.com Free-Blog in einem
   Unterverzeichnis hosten

b) Conversion-Tracking
   genaue Conversion-Messung mit eigener
   Applikation


sebastian blum      www.sblum.de   13.03.2013   2
PHP-Proxy

 BLOGGER.COM IN
 UNTERVERZEICHNIS HOSTEN

sebastian blum   www.sblum.de   13.03.2013   3
blogger.com in Unterverzeichnis hosten
  Grundidee
  Ein einfacher Blog wird bei blogger.com erstellt und
  anschließend komplett als Unterseite in eine
  bestehende Domain eingebunden.

  Vorteile
  • Kein Hosting der Seite => Beim Hoster einfachstes
    Grundmodell möglich (PHP ohne Datenbank), ab
    1,90 Euro im Monat bei hetzner.de
  • Keine Installation des Blog-Systems notwendig
  • Keine Datenbank-Installation notwendig
  • Keine Sicherheitupdates notwendig
sebastian blum          www.sblum.de   13.03.2013        4
blogger.com in Unterverzeichnis hosten
  Grundidee
  Ein einfacher Blog wird bei blogger.com erstellt und
  anschließend komplett als Unterseite in eine
  bestehende Domain eingebunden.

  Einsatzszenarien
  • Eigene Seite um einfachen Blog / Newsfeed
    ergänzen
  • Domain-Parking: Seiten vor-projektieren
  • Verschiedene IPs und Provider
  • Kein Netzwerkeffekt
sebastian blum          www.sblum.de   13.03.2013        5
Blogs in Unterverzeichnis hosten




sebastian blum     www.sblum.de   13.03.2013   6
blogger.com in Unterverzeichnis hosten
  Anpassungen im Blog

  Damit kein Duplicate Content entsteht, muss der
  Free-Blog entweder auf noindex gesetzt werden oder
  der Canonical-Tag auf das richtige Ziel zeigen.

  Beispiel: http://seo-campixx-13.blogspot.de/
        => http://seocampixx.sebastianblum.com/blog




sebastian blum        www.sblum.de   13.03.2013    7
blogger.com in Unterverzeichnis hosten
  Blog




sebastian blum    www.sblum.de   13.03.2013   8
blogger.com hosten - PHP-Skript (Übersicht)
$blog = $app['controllers_factory'];

$blog->get('/{year}/{month}/{slug}', function ($year, $month, $slug) use ($app) {
    $originUrl = rtrim(implode('/', array('http://seo-campixx-13.blogspot.de', $year, $month, $slug)), '/');

   // Request from blogger.com
   $ch = curl_init($originUrl);
   curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
   curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
   $htmlResponse = curl_exec($ch);
   $httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
   $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);

   // Change Url
   $htmlResponse = preg_replace('#http://seo-campixx-13.blogspot.(:?com|de)/#', 'http://' . $app['request']->getHttpHost() . '/blog/',
   $htmlResponse);

   // Change Meta-Tag Robots
   $htmlResponse = str_replace("'noindex,nofollow'", "'index,follow'", $htmlResponse);

    return new Response($htmlResponse, $httpStatusCode, array('Content-Type' => $contentType));
})
->value('year', null)
->value('month', null)
->value('slug', null)
->bind('blog')
;

$blog->get('/', function () use ($app) {
    return $app->redirect('/blog');
})
;                                                                                                 (Mit Micro-Framework Silex)
return $blog;



sebastian blum                                          www.sblum.de                     13.03.2013                              9
blogger.com hosten - PHP-Skript /1
$blog = $app['controllers_factory'];

$blog->get('/{year}/{month}/{slug}', function ($year, $month,
$slug) use ($app) {
    $originUrl = rtrim(implode('/', array('http://seo-campixx-
     13.blogspot.de', $year, $month, $slug)), '/');

    // Request from blogger.com
    $ch = curl_init($originUrl);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    $htmlResponse = curl_exec($ch);
    $httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);

                                                 (Mit Micro-Framework Silex)



sebastian blum             www.sblum.de    13.03.2013                      10
blogger.com hosten - PHP-Skript /2
    // Change Url
    $htmlResponse = preg_replace('#http://seo-campixx-
     13.blogspot.(:?com|de)/#', 'http://' . $app['request']
     ->getHttpHost() . '/blog/', $htmlResponse);

    // Change Meta-Tag Robots
    $htmlResponse = str_replace("'noindex,nofollow'",
     "'index,follow'", $htmlResponse);

    return new
Response($htmlResponse, $httpStatusCode,
     array('Content-Type' => $contentType));
})
->value('year', null)
->value('month', null)
->value('slug', null)                            (Mit Micro-Framework Silex)
->bind('blog')
;
sebastian blum              www.sblum.de   13.03.2013                      11
blogger.com hosten - PHP-Skript /3
 Controller aktivieren:
 $app->mount('/blog', include 'blog.php');




                                           (Mit Micro-Framework Silex)



sebastian blum        www.sblum.de   13.03.2013                      12
Blogs in Unterverzeichnis hosten
  Erweiterte Einsatzmöglichkeiten

  Eine Wordpress-Multisite-Installation kann bequem
  auf einem eigenem Server installiert werden.
  Auf die Satelliten-Seiten wird lediglich ein einfaches
  PHP-Proxy-Skript kopiert:

  • Ein zentraler Login
  • Wordpress-Aktualisierungen aller Blogs
    gleichzeitig
  • Verschiedene Anbieter, IPs, Nameserver
sebastian blum          www.sblum.de   13.03.2013      13
Blogs in Unterverzeichnis hosten




sebastian blum     www.sblum.de   13.03.2013   14
Blogs in Unterverzeichnis hosten
  Erweiterte Einsatzmöglichkeiten

  Landing-Pages
  Bestimmte Seiten aus einem CMS als Single-Site auf
  einer eigenen Domain bereitstellen, um z.B. einen
  anderen AdWords-Account verwenden zu können.




sebastian blum         www.sblum.de   13.03.2013       15
PHP-Tracking

 CONVERSION-TRACKING FÜR
 ONLINE-SHOPS

sebastian blum   www.sblum.de   13.03.2013   16
Conversion Tracking für Online-Shops
 Warum nicht per Google Analytics?


 • GA bietet lediglich Conversions pro Kampagne oder
   Quelle
 • Diese Conversions pro Kampagnen reichen nicht
   aus, um den genauen Erfolg und Wert der
   einzelnen Keywords & Anzeigen zu messen




sebastian blum        www.sblum.de   13.03.2013    17
Conversion Tracking für Online-Shops




sebastian blum    www.sblum.de   13.03.2013   18
Conversion Tracking für Online-Shops
 Offene Fragen


 • Welches Keyword hat genau welchen Erfolg?
 • Welche Keywords führen zu Transaktionen, welche
   nicht?


                 individuelle Lösung notwendig



sebastian blum               www.sblum.de   13.03.2013   19
Conversion Tracking für Online-Shops
  Ausgangssituation
  Shopbetreiber schalten Google AdWords Anzeigen
  und wollen verfolgen, welche Keywords zu welchem
  erfolgreich verkauften Produkt geführt haben.

  Vorteile des PHP-basierten Trackings
  • Die Shopsoftware wird nicht angepasst, stattdessen
    wird eine zusätzliche Applikation gebaut
  • Die gezielte Werbeschaltung kann durch einfachen
    CSV-Export analysiert werden
  • Genaue Gewinnermittlung für jedes Keyword
sebastian blum         www.sblum.de   13.03.2013     20
Conversion Tracking für Online-Shops
  Die Tracking-Schritte




sebastian blum        www.sblum.de   13.03.2013   21
Conversion Tracking für Online-Shops
  Die Tracking-Schritte in einer Beispiel-
  Programmierung


   seocampixx.sebastianblum.com/shop/
   google




sebastian blum         www.sblum.de   13.03.2013   22
1.




sebastian blum   www.sblum.de   13.03.2013   23
Conversion Tracking - Parameter
  Statische Parameter
  campaign = Kampagnenname der AdWords-Gruppe

  Dynamische Value-Track AdWords Parameter
  Im Beispiel sind es {matchtype} und {keyword}

     Weitere Beispiele
  {creative} eindeutige ID der Anzeige
  {device}    Mobil, Tablet, Desktop oder Laptop

  Google ersetzt die Platzhalter bei der Anzeige
sebastian blum          www.sblum.de   13.03.2013   24
2.




sebastian blum   www.sblum.de   13.03.2013   25
Conversion Tracking – Firebug




sebastian blum    www.sblum.de   13.03.2013   26
Conversion Tracking – Javascript /1

var urlQueryString = window.location.search.substring(1),
   queryParameters = urlQueryString.split('&'),
   trackingParameters = [ "campaign", "keyword", "matchtype" ];
if (urlQueryString.length && queryParameters.length) {
 trackingData.params = {};
 for (var i = 0; i < queryParameters.length; i++)
   var queryParameter = queryParameters[i].split('=');
   if (queryParameter[0].substr(0,4) == 'utm_' ||
            $.inArray( queryParameter[0], trackingParameters ) >= 0 ) {
             trackingData.params[ queryParameter[0] ] =
                 decodeURIComponent(
                      ( queryParameter[1] + "“ ).replace(/+/g, '%20')
                 );
        }

sebastian blum                    www.sblum.de    13.03.2013             27
3.




sebastian blum   www.sblum.de   13.03.2013   28
Conversion Tracking – Firebug




sebastian blum    www.sblum.de   13.03.2013   29
Conversion Tracking – Firebug / JSON




sebastian blum    www.sblum.de   13.03.2013   30
Conversion Tracking – Javascript /2

if ( $( "#shoppingcart" ).size() === 1 ) {
    trackingData.items = [];
    $( "#shoppingcart tr.item" ).each(function() {
          var $this = $( this );
          trackingData.items.push({ count: $this.find( "td:eq(0)"
           ).text(), title: $this.find( "td:eq(1)" ).text(), price:
             $this.find( "td:eq(2)").text() });
    });
}




sebastian blum                 www.sblum.de   13.03.2013            31
4.




sebastian blum   www.sblum.de   13.03.2013   32
Conversion Tracking – Firebug




sebastian blum    www.sblum.de   13.03.2013   33
Conversion Tracking – Javascript /3

if ( $( "#conversion-tracking-successfull" ).size() === 1 ) {
       trackingData.successfull = $( "#conversion-tracking-
                 successfull" ).data(); }




sebastian blum                 www.sblum.de   13.03.2013        34
Conversion Tracking für Online-Shops
  Eine Conversion als JSON-Datei gespeichert




sebastian blum      www.sblum.de   13.03.2013   35
Conversion Tracking für Online-Shops
  5.




sebastian blum    www.sblum.de   13.03.2013   36
Conversion Tracking für Online-Shops
  5.
params.          params.     params.     items.0.         items.0.
campaign         matchtype   keyword     count            title
Amazon-              exakt   Amazon            1          Beispiel-
Brand                        Online-Shop                  Artikel des
                                                          Shops

items.0.         items.1.    items.1.       items.1.      successfull.
price            count       title          price         profit
49,99                  1     zweiter            19,99           10
                             Artikel


sebastian blum               www.sblum.de    13.03.2013           37
Conversion Tracking für Online-Shops
  Das PHP-Skript

• Daten aus den drei Schritten werden in der Session
  gespeichert
• Wenn Kauf erfolgreich abgeschlossen wurde, wird
  die Conversion mit den Session-Daten in eine JSON-
  Datei gespeichert




sebastian blum         www.sblum.de   13.03.2013       38
PHP Skript conversion.php
$conversion = $app['controllers_factory'];

$conversion->post('/track', function (Request $request) use ($app) {
  foreach (array('params', 'items', 'successfull') as $key) {
    if (null !== $data = $request->get($key)) {
        $app['session']->set($key, $data);
    }
  }

 if (null !== $request->get('successfull')) {
     $json = $app['serializer']->serialize($app['session']->all(), 'json');

     $path = __DIR__ . '/../export/' . ($app['debug'] ? 'dev' : 'prod') . '/';
     if (!file_exists($path)) {
         mkdir($path, 0777);
     }

     file_put_contents($path . $app['session']->getId() . '.json', $json);
 }

 return new Response();
})
->bind('conversion')
;

return $conversion;
 sebastian blum                                       www.sblum.de               13.03.2013   39
Conversion Tracking - Export

• JSON-Daten der gespeicherten Conversion können
  für die Auswertung als CSV-Datei exportiert werden
• Die gespeicherten JSON-Objekte müssen hierfür
  normalisiert werden:
    Keine Verschachtelung
      und
    Alle Zeilen müssen die gleichen Spalten beinhalten



sebastian blum          www.sblum.de   13.03.2013    40
PHP Skript export.php
$export = $app['controllers_factory'];

$export->get('/', function () use ($app) {
   $path = __DIR__ . '/../export/' . ($app['debug'] ? 'dev' :
     'prod') . '/';
   $jsonFiles = glob($path . '*.json');

  $csvResponse = $app['export']($jsonFiles);

  return new Response($csvResponse, 201, array('Content-Type' =>
    'text/csv', 'Content-Disposition' => 'attachment;
    filename="export.'.date("Ymd-Hi").'.csv"'));
})
->bind('export')
;

return $export;

sebastian blum              www.sblum.de   13.03.2013           41
PHP Skript ExportServiceProvider.php
class ExportServiceProvider implements ServiceProviderInterface
{
   public function register(Application $app)
   {
       $app['export'] = $app->protect(function (array $jsonFiles) use
       ($app) {

              $exportModel = new ExportModel();
              foreach ($jsonFiles as $jsonFile) {
                  $data = json_decode(file_get_contents($jsonFile), true);
                  $exportModel->add($data);
              }

              return $exportModel;
        });
    }

    public function boot(Application $app)
    {
    }
}
sebastian blum                       www.sblum.de   13.03.2013           42
PHP Skript ExportModel.php
public function __toString()
   {
       $fp = fopen("php://memory", 'r+');
       $first = true;

      foreach ($this->data as $data) {
          if (true === $first) {
              $keys = array_keys($data);
              sort($keys);
              fputcsv($fp, $keys, ';');
              $first = false;
          }

          ksort($data);
          fputcsv($fp, $data, ';');
      }

      rewind($fp);

      return stream_get_contents($fp);
  }




 sebastian blum                    www.sblum.de   13.03.2013   43
Fazit PHP Conversion-Tracking

•   Genaues Tracking mit Gewinnberechnung möglich
•   Genaue Verfolgung der Conversion
•   Rückschlüsse auf Kaufverhalten
•   Leichte Optimierung der Keywords




sebastian blum         www.sblum.de   13.03.2013    44
Kontakt

Sebastian Blum

E-Mail: sb@sblum.de
Telefon: +49 8167 / 696 608

Vortrag online unter
www.sblum.de/#!seocampixx2013




sebastian blum                www.sblum.de   13.03.2013   45

PHP-SEO Vortrag SEOCampixx 2013 von Sebastian Blum

  • 1.
    PHP-SEO Vortrag online unter www.sblum.de/#!seocampixx2013 Quelltextonline unter github.com/sebastianblum/seocampi xx2013 Sebastian Blum sebastian blum www.sblum.de 13.03.2013 1
  • 2.
    Agenda a) PHP-Proxy blogger.com Free-Blog in einem Unterverzeichnis hosten b) Conversion-Tracking genaue Conversion-Messung mit eigener Applikation sebastian blum www.sblum.de 13.03.2013 2
  • 3.
    PHP-Proxy BLOGGER.COM IN UNTERVERZEICHNIS HOSTEN sebastian blum www.sblum.de 13.03.2013 3
  • 4.
    blogger.com in Unterverzeichnishosten Grundidee Ein einfacher Blog wird bei blogger.com erstellt und anschließend komplett als Unterseite in eine bestehende Domain eingebunden. Vorteile • Kein Hosting der Seite => Beim Hoster einfachstes Grundmodell möglich (PHP ohne Datenbank), ab 1,90 Euro im Monat bei hetzner.de • Keine Installation des Blog-Systems notwendig • Keine Datenbank-Installation notwendig • Keine Sicherheitupdates notwendig sebastian blum www.sblum.de 13.03.2013 4
  • 5.
    blogger.com in Unterverzeichnishosten Grundidee Ein einfacher Blog wird bei blogger.com erstellt und anschließend komplett als Unterseite in eine bestehende Domain eingebunden. Einsatzszenarien • Eigene Seite um einfachen Blog / Newsfeed ergänzen • Domain-Parking: Seiten vor-projektieren • Verschiedene IPs und Provider • Kein Netzwerkeffekt sebastian blum www.sblum.de 13.03.2013 5
  • 6.
    Blogs in Unterverzeichnishosten sebastian blum www.sblum.de 13.03.2013 6
  • 7.
    blogger.com in Unterverzeichnishosten Anpassungen im Blog Damit kein Duplicate Content entsteht, muss der Free-Blog entweder auf noindex gesetzt werden oder der Canonical-Tag auf das richtige Ziel zeigen. Beispiel: http://seo-campixx-13.blogspot.de/ => http://seocampixx.sebastianblum.com/blog sebastian blum www.sblum.de 13.03.2013 7
  • 8.
    blogger.com in Unterverzeichnishosten Blog sebastian blum www.sblum.de 13.03.2013 8
  • 9.
    blogger.com hosten -PHP-Skript (Übersicht) $blog = $app['controllers_factory']; $blog->get('/{year}/{month}/{slug}', function ($year, $month, $slug) use ($app) { $originUrl = rtrim(implode('/', array('http://seo-campixx-13.blogspot.de', $year, $month, $slug)), '/'); // Request from blogger.com $ch = curl_init($originUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); $htmlResponse = curl_exec($ch); $httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE); // Change Url $htmlResponse = preg_replace('#http://seo-campixx-13.blogspot.(:?com|de)/#', 'http://' . $app['request']->getHttpHost() . '/blog/', $htmlResponse); // Change Meta-Tag Robots $htmlResponse = str_replace("'noindex,nofollow'", "'index,follow'", $htmlResponse); return new Response($htmlResponse, $httpStatusCode, array('Content-Type' => $contentType)); }) ->value('year', null) ->value('month', null) ->value('slug', null) ->bind('blog') ; $blog->get('/', function () use ($app) { return $app->redirect('/blog'); }) ; (Mit Micro-Framework Silex) return $blog; sebastian blum www.sblum.de 13.03.2013 9
  • 10.
    blogger.com hosten -PHP-Skript /1 $blog = $app['controllers_factory']; $blog->get('/{year}/{month}/{slug}', function ($year, $month, $slug) use ($app) { $originUrl = rtrim(implode('/', array('http://seo-campixx- 13.blogspot.de', $year, $month, $slug)), '/'); // Request from blogger.com $ch = curl_init($originUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); $htmlResponse = curl_exec($ch); $httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE); (Mit Micro-Framework Silex) sebastian blum www.sblum.de 13.03.2013 10
  • 11.
    blogger.com hosten -PHP-Skript /2 // Change Url $htmlResponse = preg_replace('#http://seo-campixx- 13.blogspot.(:?com|de)/#', 'http://' . $app['request'] ->getHttpHost() . '/blog/', $htmlResponse); // Change Meta-Tag Robots $htmlResponse = str_replace("'noindex,nofollow'", "'index,follow'", $htmlResponse); return new Response($htmlResponse, $httpStatusCode, array('Content-Type' => $contentType)); }) ->value('year', null) ->value('month', null) ->value('slug', null) (Mit Micro-Framework Silex) ->bind('blog') ; sebastian blum www.sblum.de 13.03.2013 11
  • 12.
    blogger.com hosten -PHP-Skript /3 Controller aktivieren: $app->mount('/blog', include 'blog.php'); (Mit Micro-Framework Silex) sebastian blum www.sblum.de 13.03.2013 12
  • 13.
    Blogs in Unterverzeichnishosten Erweiterte Einsatzmöglichkeiten Eine Wordpress-Multisite-Installation kann bequem auf einem eigenem Server installiert werden. Auf die Satelliten-Seiten wird lediglich ein einfaches PHP-Proxy-Skript kopiert: • Ein zentraler Login • Wordpress-Aktualisierungen aller Blogs gleichzeitig • Verschiedene Anbieter, IPs, Nameserver sebastian blum www.sblum.de 13.03.2013 13
  • 14.
    Blogs in Unterverzeichnishosten sebastian blum www.sblum.de 13.03.2013 14
  • 15.
    Blogs in Unterverzeichnishosten Erweiterte Einsatzmöglichkeiten Landing-Pages Bestimmte Seiten aus einem CMS als Single-Site auf einer eigenen Domain bereitstellen, um z.B. einen anderen AdWords-Account verwenden zu können. sebastian blum www.sblum.de 13.03.2013 15
  • 16.
    PHP-Tracking CONVERSION-TRACKING FÜR ONLINE-SHOPS sebastian blum www.sblum.de 13.03.2013 16
  • 17.
    Conversion Tracking fürOnline-Shops Warum nicht per Google Analytics? • GA bietet lediglich Conversions pro Kampagne oder Quelle • Diese Conversions pro Kampagnen reichen nicht aus, um den genauen Erfolg und Wert der einzelnen Keywords & Anzeigen zu messen sebastian blum www.sblum.de 13.03.2013 17
  • 18.
    Conversion Tracking fürOnline-Shops sebastian blum www.sblum.de 13.03.2013 18
  • 19.
    Conversion Tracking fürOnline-Shops Offene Fragen • Welches Keyword hat genau welchen Erfolg? • Welche Keywords führen zu Transaktionen, welche nicht? individuelle Lösung notwendig sebastian blum www.sblum.de 13.03.2013 19
  • 20.
    Conversion Tracking fürOnline-Shops Ausgangssituation Shopbetreiber schalten Google AdWords Anzeigen und wollen verfolgen, welche Keywords zu welchem erfolgreich verkauften Produkt geführt haben. Vorteile des PHP-basierten Trackings • Die Shopsoftware wird nicht angepasst, stattdessen wird eine zusätzliche Applikation gebaut • Die gezielte Werbeschaltung kann durch einfachen CSV-Export analysiert werden • Genaue Gewinnermittlung für jedes Keyword sebastian blum www.sblum.de 13.03.2013 20
  • 21.
    Conversion Tracking fürOnline-Shops Die Tracking-Schritte sebastian blum www.sblum.de 13.03.2013 21
  • 22.
    Conversion Tracking fürOnline-Shops Die Tracking-Schritte in einer Beispiel- Programmierung seocampixx.sebastianblum.com/shop/ google sebastian blum www.sblum.de 13.03.2013 22
  • 23.
    1. sebastian blum www.sblum.de 13.03.2013 23
  • 24.
    Conversion Tracking -Parameter Statische Parameter campaign = Kampagnenname der AdWords-Gruppe Dynamische Value-Track AdWords Parameter Im Beispiel sind es {matchtype} und {keyword} Weitere Beispiele {creative} eindeutige ID der Anzeige {device} Mobil, Tablet, Desktop oder Laptop Google ersetzt die Platzhalter bei der Anzeige sebastian blum www.sblum.de 13.03.2013 24
  • 25.
    2. sebastian blum www.sblum.de 13.03.2013 25
  • 26.
    Conversion Tracking –Firebug sebastian blum www.sblum.de 13.03.2013 26
  • 27.
    Conversion Tracking –Javascript /1 var urlQueryString = window.location.search.substring(1), queryParameters = urlQueryString.split('&'), trackingParameters = [ "campaign", "keyword", "matchtype" ]; if (urlQueryString.length && queryParameters.length) { trackingData.params = {}; for (var i = 0; i < queryParameters.length; i++) var queryParameter = queryParameters[i].split('='); if (queryParameter[0].substr(0,4) == 'utm_' || $.inArray( queryParameter[0], trackingParameters ) >= 0 ) { trackingData.params[ queryParameter[0] ] = decodeURIComponent( ( queryParameter[1] + "“ ).replace(/+/g, '%20') ); } sebastian blum www.sblum.de 13.03.2013 27
  • 28.
    3. sebastian blum www.sblum.de 13.03.2013 28
  • 29.
    Conversion Tracking –Firebug sebastian blum www.sblum.de 13.03.2013 29
  • 30.
    Conversion Tracking –Firebug / JSON sebastian blum www.sblum.de 13.03.2013 30
  • 31.
    Conversion Tracking –Javascript /2 if ( $( "#shoppingcart" ).size() === 1 ) { trackingData.items = []; $( "#shoppingcart tr.item" ).each(function() { var $this = $( this ); trackingData.items.push({ count: $this.find( "td:eq(0)" ).text(), title: $this.find( "td:eq(1)" ).text(), price: $this.find( "td:eq(2)").text() }); }); } sebastian blum www.sblum.de 13.03.2013 31
  • 32.
    4. sebastian blum www.sblum.de 13.03.2013 32
  • 33.
    Conversion Tracking –Firebug sebastian blum www.sblum.de 13.03.2013 33
  • 34.
    Conversion Tracking –Javascript /3 if ( $( "#conversion-tracking-successfull" ).size() === 1 ) { trackingData.successfull = $( "#conversion-tracking- successfull" ).data(); } sebastian blum www.sblum.de 13.03.2013 34
  • 35.
    Conversion Tracking fürOnline-Shops Eine Conversion als JSON-Datei gespeichert sebastian blum www.sblum.de 13.03.2013 35
  • 36.
    Conversion Tracking fürOnline-Shops 5. sebastian blum www.sblum.de 13.03.2013 36
  • 37.
    Conversion Tracking fürOnline-Shops 5. params. params. params. items.0. items.0. campaign matchtype keyword count title Amazon- exakt Amazon 1 Beispiel- Brand Online-Shop Artikel des Shops items.0. items.1. items.1. items.1. successfull. price count title price profit 49,99 1 zweiter 19,99 10 Artikel sebastian blum www.sblum.de 13.03.2013 37
  • 38.
    Conversion Tracking fürOnline-Shops Das PHP-Skript • Daten aus den drei Schritten werden in der Session gespeichert • Wenn Kauf erfolgreich abgeschlossen wurde, wird die Conversion mit den Session-Daten in eine JSON- Datei gespeichert sebastian blum www.sblum.de 13.03.2013 38
  • 39.
    PHP Skript conversion.php $conversion= $app['controllers_factory']; $conversion->post('/track', function (Request $request) use ($app) { foreach (array('params', 'items', 'successfull') as $key) { if (null !== $data = $request->get($key)) { $app['session']->set($key, $data); } } if (null !== $request->get('successfull')) { $json = $app['serializer']->serialize($app['session']->all(), 'json'); $path = __DIR__ . '/../export/' . ($app['debug'] ? 'dev' : 'prod') . '/'; if (!file_exists($path)) { mkdir($path, 0777); } file_put_contents($path . $app['session']->getId() . '.json', $json); } return new Response(); }) ->bind('conversion') ; return $conversion; sebastian blum www.sblum.de 13.03.2013 39
  • 40.
    Conversion Tracking -Export • JSON-Daten der gespeicherten Conversion können für die Auswertung als CSV-Datei exportiert werden • Die gespeicherten JSON-Objekte müssen hierfür normalisiert werden:  Keine Verschachtelung und  Alle Zeilen müssen die gleichen Spalten beinhalten sebastian blum www.sblum.de 13.03.2013 40
  • 41.
    PHP Skript export.php $export= $app['controllers_factory']; $export->get('/', function () use ($app) { $path = __DIR__ . '/../export/' . ($app['debug'] ? 'dev' : 'prod') . '/'; $jsonFiles = glob($path . '*.json'); $csvResponse = $app['export']($jsonFiles); return new Response($csvResponse, 201, array('Content-Type' => 'text/csv', 'Content-Disposition' => 'attachment; filename="export.'.date("Ymd-Hi").'.csv"')); }) ->bind('export') ; return $export; sebastian blum www.sblum.de 13.03.2013 41
  • 42.
    PHP Skript ExportServiceProvider.php classExportServiceProvider implements ServiceProviderInterface { public function register(Application $app) { $app['export'] = $app->protect(function (array $jsonFiles) use ($app) { $exportModel = new ExportModel(); foreach ($jsonFiles as $jsonFile) { $data = json_decode(file_get_contents($jsonFile), true); $exportModel->add($data); } return $exportModel; }); } public function boot(Application $app) { } } sebastian blum www.sblum.de 13.03.2013 42
  • 43.
    PHP Skript ExportModel.php publicfunction __toString() { $fp = fopen("php://memory", 'r+'); $first = true; foreach ($this->data as $data) { if (true === $first) { $keys = array_keys($data); sort($keys); fputcsv($fp, $keys, ';'); $first = false; } ksort($data); fputcsv($fp, $data, ';'); } rewind($fp); return stream_get_contents($fp); } sebastian blum www.sblum.de 13.03.2013 43
  • 44.
    Fazit PHP Conversion-Tracking • Genaues Tracking mit Gewinnberechnung möglich • Genaue Verfolgung der Conversion • Rückschlüsse auf Kaufverhalten • Leichte Optimierung der Keywords sebastian blum www.sblum.de 13.03.2013 44
  • 45.
    Kontakt Sebastian Blum E-Mail: sb@sblum.de Telefon:+49 8167 / 696 608 Vortrag online unter www.sblum.de/#!seocampixx2013 sebastian blum www.sblum.de 13.03.2013 45