Wednesday, September 26, 2012

Facebook Insights using Graph API & Google Visualization: Area Chart

          The Facebook Insights reports can be integrated to external websites by any programming languages such as PHP, Java, JavaScript, apex, .net, etc. through Graph API. I have integrated the Insights report to SalesForce Visualforce Pages by Apex with jQuery. Google Visualization: Area Chart is used to draw chart.

      I have used a combination of Graph API Insights requests and a set of Facebook Query Language(FQL) requests to create a monthly report.

1. Creating the chart
  



   The following requests are used for geting data from Facebook.

   For "People Talking About This" :

        https://graph.facebook.com/[pageId]/insights/page_storytellers/week?since=[startTime]&until=[endTime]&access_token=[accessToken]

   For "People Reached" :

        https://graph.facebook.com/[pageId]/insights/page_impressions_unique/week?since=[startTime]&until=[endTime]&access_token=[accessToken]

   *** startTime, endTime are in Unix timestamps based on midnight in PST described in UTC.

      A multidimensional JavaScript array has been created from the resulted json for the Google Visualization: Area Chart. I have added custom toll tip and formatted date labels in the chart. The JavaScript code as below:

 // Prepare chart data  for series 1


     chartData = new Array();
     jQuery.each(jsonData.values, function(i, item) {
            dataArray = new Array();
            dataArray[0] = formatDate(item.end_time);
            dataArray[1] = item.value;
            dataArray[2] = getToolTipText(item.end_time, item.value, 'People Talking About This');
            chartData[i]= dataArray;
        });


 // function to draw chart

   function drawChart() {
        var data = new google.visualization.DataTable();
        data.addColumn('string', 'Date'); // Implicit domain label col.
        data.addColumn('number', 'People Talking About This'); // Implicit series 1 data col.
        data.addColumn({type:'string', role:'tooltip'}); // Implicit tool tip 1 data col.
        data.addColumn('number', 'Weekly Total Reach'); // Implicit series 2 data col.
        data.addColumn({type:'string', role:'tooltip'});// Implicit tool tip 2 data col.
        data.addRows(chartData);

        var options = {
            width: 900,
            height: 350,
            colors: ['#FF9900', '#3B5998'],
            vAxis: { gridlines: { color : '#fff'}, logScale: true},
            hAxis: {  showTextEvery : 7 },
            pointSize: 4,
            legend: {position: 'top', textStyle: {fontSize: 14}},
            tooltip: {textStyle: {fontSize: 12}}
        };

        var chart = new google.visualization.AreaChart(document.getElementById('chart_div'));
        chart.draw(data, options);
}



function getToolTipText(endDate, value, text){
    toolTipText = 'custom tooltip';
    return toolTipText;
}

** function formatDate in Some JavaScript Date Formatting Tips 

2. Page Posts table list




    Unfortunately I can't get the stream data and insight data together in a single FQL query. So I have used a FQL multi query to get the stream data and insight data together and used a iterating loop to make  stream data with the corresponding insight data. The used FQL as follows

    {"pageStream": "SELECT post_id, substr(message, 0, 50), type, created_time,attachment.name
                    FROM stream
                    WHERE source_id = [pageId]
                        AND created_time <= [endTime]
                        AND created_time >= [stratTime]
                        AND type != ''
                    LIMIT 0, 30;",
    "pageInsight": "SELECT object_id, metric, value, end_time
                    FROM insights
                    WHERE object_id IN (SELECT post_id FROM #pageStream)
                        AND metric IN ('post_engaged_users','post_storytellers', 'post_impressions_unique')
                        AND period = period('lifetime');"}

*** startTime, endTime are in Unix timestamps based on midnight in PST described in UTC.

3. Page fan count comparison

   Another thing that I have done  Page like count comparison with previous month. Here also I am used a multi query to get both the counts together

     {"currentCount": "SELECT object_id, metric, value, end_time
                       FROM insights
                       WHERE object_id  = [pageId]
                            AND metric IN ('page_fans')
                            AND period = period('lifetime')
                            AND end_time = end_time_date('2012-8-31')",
    "previousCount": "SELECT object_id, metric, value, end_time
                      FROM insights
                      WHERE object_id  = [pageId]
                        AND metric IN ('page_fans')
                        AND period = period('lifetime')
                        AND end_time = end_time_date('2012-7-30')"}

  
  Reference: 
    https://developers.facebook.com/docs/reference/fql/insights/
    https://developers.facebook.com/docs/reference/api/insights/
    https://developers.google.com/chart/interactive/docs/gallery/areachart

Some JavaScript Date Formatting Tips


1. Date formatting from date string

    strDate =  "2012-08-02T07:00:00+0000"; // For Eg

    function formatDate(strDate){
        var monthNames = new Array("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec");
        var date = new Date(strDate);
        return monthNames[date.getMonth()]+ ' '+ date.getDate();
    }


 2. Date formatting from time stamp

function timeStampToDate(timeStamp){
    var date = new Date(timeStamp * 1000);
    return (date.getMonth() +1 )+ '/'+ date.getDate()+'/'+ date.getFullYear();
}

3. Week start or week end for a day

  function getWeekDay(date, day){
    var targetDay;
    var currentDay = new Date(endDate);
    if(day == 'next'){
        // add 6 days
        targetDay = new Date(currentDay.getTime() + (86400000 * 6 ));
        // 24*60*60*1000 = 86400000 (day in milliseconds)
    }else{ // previous
        // subtract 6 days
        targetDay = new Date(currentDay.getTime() - (86400000 * 6 ));
        // 24*60*60*1000 = 86400000 (day in milliseconds)
    }
    return targetDay
   }

Reference:

http://www.javascriptkit.com/jsref/date.shtml

NB: This for my future reference