Build a Custom Reporting Tool with the Google Analytics API and the CodeIgniter PHP Framework

This is the first part of a 2 part article on how to build a custom reporting tool with the Google Analytics Data Export API and CodeIgniter (plus a few additional open source libraries).

Overview
The purpose of our tool will be to connect to the Google Analytics Data Export API, return information for any given Analytics account, and convert that information into an auto generated PDF report. The reporting tool will be built on top of version 2.02 Reactor of the CodeIgniter PHP framework (http://codeigniter.com/). CodeIgniter requires PHP 5.1.6 or greater. Documentation for CodeIgniter itself is available from the CodeIgniter website and is also included with the application. In order to facilitate maintenance the standard CodeIgniter file structure will be adhered to. This means that the important components of the application will reside in the following locations:

- application/controllers/ (all controller files)
- application/views/ (all view files)
- application/helpers/ (custom helper files)
- application/libraries/ (external libraries used in the application)

In addition we will add the following structure to our application:

- application/db/ (sql file for application)
- themes/css/ (css files for application)
- themes/js/ (js files for application)
- themes/images/ (images used for app theme)
- images/ (content images not related to theming)
- reports/ (where the generated reports are saved)

These are the configuration and core files we will need to modify or create:

- application/core/MY_Controller.php
- application/config/ion_auth.php
- application/config/config.php
- application/config/constants.php
- application/config/autoload.php

External Libraries
The application will require the following external open source PHP libraries:
- Ion Auth (https://github.com/benedmunds/CodeIgniter-Ion-Auth)
- GAPI Google Analytics API PHP Interface (http://code.google.com/p/gapi-google-analytics-php-interface/)
- gChart PHP (http://code.google.com/p/gchartphp/)
- TCPDF (modified configuration – http://www.tcpdf.org/)

Additionally, on the front end jQuery and jQuery UI will be used.

General Application Flow
The application will follow the standard CodeIgniter MVC implementation. The user will first be presented by a login screen that handles authentication using the Ion Auth library. The user then signs in to a Google Account which connects to the Google Data Export API using the open source GAPI PHP library. We will name the main report generation controller select_report.php and place it in application/controllers/. We will use AJAX calls to create the various sections of the report and we will place those methods in application/views/ and name that file select_report_ajax.php. Most of our other controllers will serve the purpose connecting with the Google API and returning portions of data to these files.

PDF Report Generation
The generation of PDF reports will be handled by the TCPDF open source PHP library. Chart rendering will be handled by the Google Visualization API through the open source gChart PHP wrapper. Once the AJAX calls return each portion of the report selected by the user, we will pass this HTML to the ajax_print_pdf.php controller which processes the markup and converts it into a PDF report. These reports will be saved in the /reports directory and the user’s browser will then be redirected to the current report using javascript.

The code will follow in part 2 of this article.

Posted in Web Development | 1 Comment

PHP Variables and Memory

Adam Charnock writes an interesting article on PHP variables, references and memory use:

The Truth About PHP Variables

Posted in PHP, Web Development | Leave a comment

Apache Mod_Rewrite Tip: Redirect Domain to Language Subfolder

How to insert a segment into your URLs using Apache mod_rewrite and htaccess:

RewriteRule ^index\.php(.*)?$ /en/index\.php$1 [R=301]
Posted in Apache, Mod_Rewrite, Web Development | Leave a comment

How to get Python running on Apache and WAMPServer (Win 7)

If for the sake of convenience you are running a preconfigured WAMPServer setup like me, this is how you can add Python to the package. For the purposes of this post, I’m assuming you are running a recent version of WAMPServer from http://www.wampserver.com (I’m running version 2.0).

1. Download and install Python from http://www.python.org (I used the Python 2.7.1 Installer)

2. Download mod_wsgi for your version of Apache from http://code.google.com/p/modwsg/

I’m running Apache 2.2 so I downloaded mod_wsgi-win32-ap22py27-3.3.so

3. Rename the file you downloaded mod_wsgi.so and drop it the modules/ folder of your Apache installation in WAMPServer

4. Add the following line to your httpd.conf:

LoadModule wsgi_module modules/mod_wsgi.so

5. Create a test directory (C:/wamp/www/python in my case) and a test file (test.py) that contains the following:

def application(environ, start_response):
    status = '200 OK'
    output = 'Hello World!'

    response_headers = [('Content-type', 'text/plain'),
    ('Content-Length', str(len(output)))]

    start_response(status, response_headers)
    return [output]

Note: It’s probably best to write out the above, rather than copying and pasting, as indentation and encoding are important for Python scripts.

6. Add the following directive to httpd.conf:

<Directory “C:/wamp/www/python”>
Options ExecCGI
AddHandler wsgi-script .py
Order allow,deny
Allow from all
</Directory>

7. Go to http://localhost/python/test.py and you should see “Hello World”

Posted in Apache, Python, Web Development | Leave a comment

Reconfigure Page Layout Based on Window Width

How to reconfigure a layout based on window (viewport) width.  You can see this in action at www.capellahotels.com (as long as your resolution is at least 1330px).

jQuery(document).ready(function($) {

    // move main content depending on viewport width
    adjustWidths(1330,1000);

    // adjust width/main content each time the viewport is resized
    var TO = false;
    jQuery(window).resize(function() {
        if(TO !== false) {
            clearTimeout(TO);
        }
        TO = setTimeout(function(){adjustWidths(1330,1000)}, 300);
    });

}); // End Document Ready

function adjustWidths(necWidth,minHolderWidth) {

    mainContentArea = jQuery('div#main-content');
    holderDiv = jQuery('div#holder');
    flashContainer = jQuery('div#flash-container');
    bookingMask = jQuery('div#booking-mask');
    viewPortWidth = jQuery(window).width();

    if (viewPortWidth > minHolderWidth) {
        holderDiv.width(viewPortWidth);
        flashContainer.css({'width' : '100%'});
    } else {
        holderDiv.width(minHolderWidth);
        flashContainer.css({'width' : '1000px'});
    }

    if (viewPortWidth > necWidth) {
        mainContentArea.width(220);
        mainContentArea.css({
            "margin-left" : "885px",
            "margin-top" : "140px",
            "margin-bottom" : "180px",
            "padding-right" : "20px"
        });
    } else {
        mainContentArea.width(600);
        mainContentArea.css({
            "margin-left" : "230px",
            "margin-top" : "660px",
            "margin-bottom" : "80px",
            "min-height" : "180px"
        });
    }

}
Posted in Web Development, jQuery | 2 Comments

Add Onclick Events to All Outbound Links with jQuery Depending on Domain

This is a really simple way to add an onclick event to all links using jQuery, matching the domain. This could come in really handy if you want to organize your Google Analytics code in so that it adds event tracking to links, and organizes it nicely by domain or product ID, for example.

// add onclick event to all outbound links
jQuery('a').each(function() {
    var link = jQuery(this);
    var href = link.attr('href');

    // check to see if the link is external (begins with http and is not the current domain)
    if ( (href.match(/^http/)) && (!href.match(document.domain)) ) {

        // if it is domain 1 do something
        if (href.match(/domain1\.com/)) {
            link.click(function() {
                // some code...
            });
        // otherwise do something else
        } else {
            link.click(function() {
                // some other code...
            });
        }

    }
});
Posted in Web Development | Leave a comment

Limit Lightbox Effect to Image Files Using jQuery

On a recent site build I had open all images attached to a new post in Fancybox, while opening all PDF files the standard way (in the browser window).

Because of some limitations in the CMS that was implemented, it was impossible to do this on the server side.

Fortunately this was quite easy to achieve using jQuery. The following code assumes you are using Fancybox to look for a rel=”lightbox” attribute.

Anything with a rel=”lightbox” attribute, which is also in our array of acceptable image extensions, will then be opened using Fancybox (which by the way is my current favorite as far as modal windows go).  You could, of course, easily adapt this to work with other modal window scripts.

jQuery(document).ready(function() {
    // an array containing the extensions we want to open in Lightbox / Fancybox, etc
    var extArray = ['gif','png','jpg','jpeg'];

    jQuery('[rel^=lightbox]').each(function(i) {
        // split the HREF into parts
        var currLinkElems = jQuery(this).attr('href').split('.')
        // get the last part (the file extension)
        var ext = currLinkElems[currLinkElems.length-1]

        // if the extension is in our previously defined array open it in Fancybox
        if(jQuery.inArray(ext, extArray)) {
            jQuery(this).fancybox();
        }

    })
});
Posted in Javascript, Web Development, jQuery | 1 Comment