<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>jensbits.com &#187; Google</title>
	<atom:link href="http://www.jensbits.com/tag/google/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.jensbits.com</link>
	<description></description>
	<lastBuildDate>Wed, 21 Jul 2010 03:44:48 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Google Analytics Data Export API with Google Chart Visualizations</title>
		<link>http://www.jensbits.com/2010/06/23/google-analytics-data-export-api-with-google-chart-visualizations-2/</link>
		<comments>http://www.jensbits.com/2010/06/23/google-analytics-data-export-api-with-google-chart-visualizations-2/#comments</comments>
		<pubDate>Wed, 23 Jun 2010 06:45:54 +0000</pubDate>
		<dc:creator>jen</dc:creator>
				<category><![CDATA[Google Analytics]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Google]]></category>

		<guid isPermaLink="false">http://www.jensbits.com/?p=769</guid>
		<description><![CDATA[You can punch into the Google Analytics Data Export API, pull out some stats, and stuff them into some nice graphical charts using Google Chart Visualizations. This demo is done in PHP. Authenticate the User The user can authenticate via the ClientLogin or using the AuthSub login which is actually more secure. For the ClientLogin, [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>You can punch into the Google Analytics Data Export API, pull out some stats, and stuff them into some nice graphical charts using Google Chart Visualizations. This demo is done in PHP.<br />
<img src="/images/googlechartviz.gif" alt="Google Chart Visualizations" /></p>
<h2>Authenticate the User</h2>
<p>The user can authenticate via the ClientLogin or using the AuthSub login which is actually more secure. For the ClientLogin, a typical username/password form is used. For the AuthSub login a link is used to send the user to Google to log in. Both are shown below. Normally you would use one or the other.</p>
<pre class="brush: php;">
&lt;form name=&quot;loginForm&quot; action=&quot;&lt;?php echo $_SERVER['PHP_SELF']; ?&gt;&quot; method=&quot;post&quot;&gt;
		    &lt;label for=&quot;email&quot;&gt;Gmail:&lt;/label&gt;
		    &lt;input id=&quot;email&quot; type=&quot;text&quot; name=&quot;email&quot; /&gt;
		    &lt;label for=&quot;password&quot;&gt;Password:&lt;/label&gt;
		    &lt;input type=&quot;password&quot; name=&quot;password&quot; id=&quot;password&quot;/&gt;
		    &lt;br /&gt;&lt;br /&gt;
		    &lt;button type=&quot;submit&quot; id=&quot;submitLogin&quot;&gt;Submit&lt;/button&gt;
		&lt;/form&gt;
        &lt;p&gt;&lt;a class=&quot;button&quot; href=&quot;https://www.google.com/accounts/AuthSubRequest?next=http://www.jensbits.com/demos/ga/app/&amp;scope=https://www.google.com/analytics/feeds/&amp;secure=0&amp;session=1&quot;&gt;Or,authenticate using AuthSub through Google.&lt;/a&gt;&lt;/p&gt;
</pre>
<p>And, of course, the two authentication methods use different http calls to return a token that can be used to access the API.</p>
<pre class="brush: php;">
//ClientLogin: try to log in and get session token for multiple API calls
if(isset($_POST['email']) &amp;&amp; isset($_POST['password'])){
	$_SESSION['sessionToken'] = googleLogin($_POST['email'],$_POST['password']);
}
//AuthSub: exchange token for session token so multiple calls can be made to api
if(isset($_REQUEST['token'])){
	$_SESSION['authSub'] = true;
	$_SESSION['sessionToken'] = get_session_token($_REQUEST['token']);
}

//returns sessionToken for multiple calls to API
function googleLogin($email,$passwd){

    $clientlogin_url = &quot;https://www.google.com/accounts/ClientLogin&quot;;
     $clientlogin_post = array(
    &quot;accountType&quot; =&gt; &quot;GOOGLE&quot;,
    &quot;Email&quot; =&gt; $email,
    &quot;Passwd&quot; =&gt; $passwd,
    &quot;service&quot; =&gt; &quot;analytics&quot;,
    &quot;source&quot; =&gt; &quot;my-analytics&quot;
	);

	$curl = curl_init($clientlogin_url);

	curl_setopt($curl, CURLOPT_POST, true);
	curl_setopt($curl, CURLOPT_POSTFIELDS, $clientlogin_post);
	curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
	curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
	curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);

	$response = curl_exec($curl);

	preg_match(&quot;/Auth=([a-z0-9_\-]+)/i&quot;, $response, $matches);
	$sessionToken = $matches[1];

	if (strlen($sessionToken) == 0){
		$sessionToken = &quot;Authentication Failed.&quot;;
	}

 	return $sessionToken;
}

//AuthSub returns session token for multiple calls to API
	function get_session_token($onetimetoken) {
		$output = call_api($onetimetoken, &quot;https://www.google.com/accounts/AuthSubSessionToken&quot;);

		if (preg_match(&quot;/Token=(.*)/&quot;, $output, $matches))
		{
			$sessionToken = $matches[1];
		} else {
			echo &quot;Error authenticating with Google.&quot;;
			exit;
		}

		return $sessionToken;
	}
</pre>
<h2>Data Requests</h2>
<p>Once authenticated to a Google Analytics account and a multi-use session token is acquired, the data requests can be made. The first one will request the profiles (websites) associated with the account. If there is more than one, a dropdown select is populated allowing for the selection of the profile from which to pull data.</p>
<pre class="brush: php;">
$accountxml = call_api($_SESSION['sessionToken'],&quot;https://www.google.com/analytics/feeds/accounts/default&quot;);
// Get an array with the available accounts
$profiles = parse_account_list($accountxml);
</pre>
<p>The call_api function is going to return the XML data from Google based on the request URL sent in. In this case, it is getting the profile data and the parse_account_list function is rolling through that XML and putting the profile data in an array.</p>
<pre class="brush: php;">
//gets the data
function call_api($sessionToken,$url){
	$curl = curl_init($url);

	curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
	if (isset($_SESSION['authSub'])){
		$curlheader[0] = sprintf(&quot;Authorization: AuthSub token=\&quot;%s\&quot;/n&quot;, $sessionToken);
	} else {
		$curlheader[0] = &quot;Authorization: GoogleLogin auth=&quot; . $sessionToken;
	}
	curl_setopt($curl, CURLOPT_HTTPHEADER, $curlheader);

	$response = curl_exec($curl);
	curl_close($curl);

	return $response;
}

//returns accounts list as array
function parse_account_list($xml){
	$doc = new DOMDocument();
	if(stripos($xml,&quot;&lt;&quot;) !== FALSE)
	{
		$doc-&gt;loadXML($xml);

		$entries = $doc-&gt;getElementsByTagName('entry');
		$i = 0;
		$profiles= array();
		foreach($entries as $entry)
		{
			$profiles[$i] = array();

			$title = $entry-&gt;getElementsByTagName('title');
			$profiles[$i][&quot;title&quot;] = $title-&gt;item(0)-&gt;nodeValue;

			$entryid = $entry-&gt;getElementsByTagName('id');
			$profiles[$i][&quot;entryid&quot;] = $entryid-&gt;item(0)-&gt;nodeValue;

			$tableId = $entry-&gt;getElementsByTagName('tableId');
			$profiles[$i][&quot;tableId&quot;] = $tableId-&gt;item(0)-&gt;nodeValue;

			$i++;
		}
		return $profiles;
	} else {
		$sessionToken = &quot;Authentication Failed.&quot;;
	}

}
</pre>
<p>The dropdown of the profile array:</p>
<pre class="brush: php;">
echo &quot;&lt;form name='siteSelect' id='siteSelect' method='post' action='&quot; . $_SERVER['PHP_SELF'] . &quot;'&gt;&lt;p&gt;&lt;label for='tableId'&gt;Select Site:&lt;/label&gt;&lt;select name='tableId' id='tableId'&gt;&quot;;
		foreach($profiles as $profile)
		{
			if($profile[&quot;tableId&quot;] == $table_Id)
				$selected = &quot;selected='selected'&quot;;
				echo &quot;&lt;option value='&quot; . $profile[&quot;tableId&quot;] . &quot;|&quot; . $profile[&quot;title&quot;] . &quot;'&quot; . $selected  . &quot;&gt;&quot; . $profile[&quot;title&quot;] . &quot;&lt;/option&gt;&quot;;
				$selected = &quot; &quot;;
		}
		echo &quot;&lt;/select&gt;&lt;/p&gt;&quot;;
</pre>
<p>The parse_data function below is going to roll through the data returned from Google Analytics and spit out an array that can be used to create the Google Visualization graphs.</p>
<pre class="brush: php;">
//returns data as array
function parse_data($xml){
		$doc = new DOMDocument();
		$doc-&gt;loadXML($xml);

		$entries = $doc-&gt;getElementsByTagName('entry');
		$i = 0;
		$results = array();
		foreach($entries as $entry)
		{
			$countries[$i] = array();

			$dimensions = $entry-&gt;getElementsByTagName('dimension');
			foreach($dimensions as $dimension)
			{
				$results[$i][ltrim($dimension-&gt;getAttribute(&quot;name&quot;),&quot;ga:&quot;)] =  $dimension-&gt;getAttribute('value');
			}

			$metrics = $entry-&gt;getElementsByTagName('metric');
			foreach($metrics as $metric)
			{
				$results[$i][ltrim($metric-&gt;getAttribute('name'),&quot;ga:&quot;)] =  $metric-&gt;getAttribute('value');
			}

			$i++;
		}
		return $results;
}
</pre>
<h2>Graph Generation</h2>
<p>Google Visualizations requires the inclusion of a javascript file in the head tag and empty div&#8217;s that will be the target for the graphs:</p>
<pre class="brush: xml;">
&lt;script type=&quot;text/javascript&quot; src=&quot;http://www.google.com/jsapi&quot;&gt;&lt;/script&gt;
</pre>
<p>The target div&#8217;s should be placed on the page where you want them to appear.</p>
<pre class="brush: xml;">
&lt;div id='barchart_div'&gt;&lt;/div&gt;
&lt;div id='piechart_div'&gt;&lt;/div&gt;
</pre>
<p>Finally, the data can be added to the chart generation javascript:</p>
<pre class="brush: jscript;">
&lt;script type=&quot;text/javascript&quot;&gt;
      google.load(&quot;visualization&quot;, &quot;1&quot;, {packages:[&quot;piechart&quot;]});
      google.setOnLoadCallback(drawPieChart);
      function drawPieChart() {
        var data = new google.visualization.DataTable();
        data.addColumn('string', 'Referrer');
        data.addColumn('number', 'Visits');
        data.addRows(&lt;?php echo sizeof($referrers) ?&gt;);
        &lt;?php
        $row = 0;
        foreach($referrers as $referrer)
		{
		?&gt;
		data.setValue(&lt;?php echo $row ?&gt;,0,'&lt;?php echo $referrer[&quot;source&quot;] ?&gt;');
		data.setValue(&lt;?php echo $row ?&gt;,1,&lt;?php echo $referrer[&quot;visits&quot;] ?&gt;);
		&lt;?php
		$row++;
		}
		?&gt;

        var chart = new google.visualization.PieChart(document.getElementById('piechart_div'));
        chart.draw(data, {width: 600, height: 440, is3D: true, title: 'Referrer/Visits'});
	  	}

	  google.load(&quot;visualization&quot;, &quot;1&quot;, {packages:[&quot;columnchart&quot;]});
      google.setOnLoadCallback(drawBarChart);
      function drawBarChart() {
        var data = new google.visualization.DataTable();
        data.addColumn('string', 'Day');
        data.addColumn('number', 'Visits');
        data.addRows(&lt;?php echo sizeof($visitsgraph) ?&gt;);
		&lt;?php
         $row = 0;
        foreach($visitsgraph as $visits)
		{
		?&gt;
		data.setValue(&lt;?php echo $row ?&gt;,0,'&lt;?php if ($visits_graph_type == &quot;month&quot;){echo date(&quot;M&quot;, mktime(0, 0, 0, $visits[&quot;month&quot;])).&quot; &quot;.$visits[&quot;year&quot;];}else{echo substr($visits['date'],6,2).&quot;-&quot;.date('M', mktime(0, 0, 0, substr($visits['date'],4,2))).&quot;-&quot;.substr($visits['date'],0,4);} ?&gt;');
		data.setValue(&lt;?php echo $row ?&gt;,1,&lt;?php echo $visits[&quot;visits&quot;] ?&gt;);
		&lt;?php
		$row++;
		}
		?&gt;
        var chart = new google.visualization.ColumnChart(document.getElementById('barchart_div'));
        chart.draw(data, {width: 700, height: 400, is3D: true, title: 'Visits'});
      }

    &lt;/script&gt;
</pre>
<h2>Recommended</h2>
<div style="height: 250px;">
<div style="float:left;margin-right: 25px">
<iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&#038;bc1=000000&#038;IS2=1&#038;bg1=FFFFFF&#038;fc1=000000&#038;lc1=0000FF&#038;t=jensbits-20&#038;o=1&#038;p=8&#038;l=as1&#038;m=amazon&#038;f=ifr&#038;md=10FE9736YVPPT7A0FBG2&#038;asins=0470413964" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe></p>
</div>
<div style="float:left;margin-right: 25px">
<iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&#038;bc1=000000&#038;IS2=1&#038;bg1=FFFFFF&#038;fc1=000000&#038;lc1=0000FF&#038;t=jensbits-20&#038;o=1&#038;p=8&#038;l=as1&#038;m=amazon&#038;f=ifr&#038;md=10FE9736YVPPT7A0FBG2&#038;asins=0470529393" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
</div>
<div style="float:left;margin-right: 25px">
<iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&#038;bc1=000000&#038;IS2=1&#038;bg1=FFFFFF&#038;fc1=000000&#038;lc1=0000FF&#038;t=jensbits-20&#038;o=1&#038;p=8&#038;l=as1&#038;m=amazon&#038;f=ifr&#038;md=10FE9736YVPPT7A0FBG2&#038;asins=0470562315" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
</div>
<div style="float:left;margin-right: 25px">
<iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&#038;bc1=000000&#038;IS2=1&#038;bg1=FFFFFF&#038;fc1=000000&#038;lc1=0000FF&#038;t=jensbits-20&#038;o=1&#038;p=8&#038;l=as1&#038;m=amazon&#038;f=ifr&#038;md=10FE9736YVPPT7A0FBG2&#038;asins=0470531282" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
</div>
</div>
<p id="demo"><a href="/demos/ga/app/"><span>Demo</span></a></p>
<p id="download"><a href="/media/code/GAandGoogleCharts.zip"><span>Download zip of all files</span></a></p>
<p class="donate">If this post helped you out, please consider donating to help pay the hosting fees. 100% of the donations go to the web host.</p>

<!-- Begin PayPal Donations by http://wpstorm.net/ -->
<form action="https://www.paypal.com/cgi-bin/webscr" method="post"><div class="paypal-donations"><input type="hidden" name="cmd" value="_donations" /><input type="hidden" name="business" value="jen@jensbits.com" /><input type="hidden" name="return" value="http://www.jensbits.com/thank-you/" /><input type="hidden" name="item_name" value="Help pay hosting. All donations go to hosting fees for this site." /><input type="hidden" name="currency_code" value="USD" /><input type="image" src="https://www.paypal.com/en_US/i/btn/btn_donate_LG.gif" name="submit" alt="PayPal - The safer, easier way to pay online." /><img alt="" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1" /></div></form>
<!-- End PayPal Donations -->



<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://www.jensbits.com/2010/06/23/google-analytics-data-export-api-with-google-chart-visualizations-2/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Using Google Docs to Create a Survey</title>
		<link>http://www.jensbits.com/2010/02/05/using-google-docs-to-create-a-survey/</link>
		<comments>http://www.jensbits.com/2010/02/05/using-google-docs-to-create-a-survey/#comments</comments>
		<pubDate>Fri, 05 Feb 2010 20:25:15 +0000</pubDate>
		<dc:creator>jen</dc:creator>
				<category><![CDATA[Web development]]></category>
		<category><![CDATA[Google]]></category>

		<guid isPermaLink="false">http://www.jensbits.com/?p=597</guid>
		<description><![CDATA[After creating the pop-up survey in jQuery, further exploration on creating online polls has turned up Google Docs quick and dirty form creation. Google posted a 2-minute video on Google Docs form creation that pretty much sums it up. This has actually been around for a couple of years now but, even though it&#8217;s a [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>After creating the <a href="/2010/01/29/pop-up-survey-with-jquery-ui-dialog/">pop-up survey in jQuery</a>, further exploration on creating online polls has turned up Google Docs quick and dirty form creation.</p>
<p>Google posted a <a href="http://www.youtube.com/watch?v=IzgaUOW6GIs">2-minute video on Google Docs form creation</a> that pretty much sums it up. This has actually been around for a couple of years now but, even though it&#8217;s a little late to the party, here is a quick illustration of my jQuery poll done with Google Docs:</p>
<p><strong>Select &#8220;Form&#8221; from the &#8220;Create New&#8221; menu.</strong></p>
<p><img src="/images/googleforms/form_01_select.gif" alt="" /></p>
<p><strong>Fill in the name of the poll or form, short description, and the first question.</strong></p>
<p><img src="/images/googleforms/form_02_firstquestion.gif" alt="" /></p>
<p><strong>Add a question by clicking the &#8220;Add Item&#8221; button and choose from the menu items. Under &#8220;More Actions&#8221; you can create the confirmation message and allow the submitters to see the results.</strong> </p>
<p><img src="/images/googleforms/form_03_options.gif" alt="" /></p>
<p><strong>You can also get the embed link for putting the poll right on a web page.</strong> </p>
<p><img src="/images/googleforms/form_04_embed.gif" alt="" /></p>
<p><strong>And, you can email the form and have users submit answers right from their email by hitting the &#8220;Email this form&#8221; button and adding the email addresses.</strong></p>
<p><img src="/images/googleforms/form_05_email.gif" alt="" /></p>
<h2>Here it is in all it&#8217;s embedded goodness. Try it out:</h2>
<p><iframe style="border:1px solid;padding: 5px" src="https://spreadsheets.google.com/embeddedform?formkey=dDNhRVB2el9FTmJpSkR1dEdISDdGRXc6MA" width="500" height="400" frameborder="0" marginheight="0" marginwidth="0">Loading&#8230;</iframe></p>


<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://www.jensbits.com/2010/02/05/using-google-docs-to-create-a-survey/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google Visualization API and ColdFusion: Create a Data Table</title>
		<link>http://www.jensbits.com/2009/07/23/google-visualization-api-and-coldfusion-create-a-data-table/</link>
		<comments>http://www.jensbits.com/2009/07/23/google-visualization-api-and-coldfusion-create-a-data-table/#comments</comments>
		<pubDate>Fri, 24 Jul 2009 01:38:31 +0000</pubDate>
		<dc:creator>jen</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Google]]></category>

		<guid isPermaLink="false">http://www.jensbits.com/?p=306</guid>
		<description><![CDATA[The Google Visualization API is fun to play around with and it&#8217;s quite powerful. There are a number of charts and graphs to choose from and filling them up with data from ColdFusion is a snap. At least it was for this table example here. Most of this code comes straight out of Google&#8217;s documentation [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://code.google.com/apis/visualization/documentation/gallery.html">Google Visualization API</a> is fun to play around with and it&#8217;s quite powerful. There are a number of charts and graphs to choose from and filling them up with data from ColdFusion is a snap. At least it was for this table example here. Most of this code comes straight out of Google&#8217;s documentation which was pretty good and easy to follow.</p>
<p>First things first&#8230;get some data. For simplicity sake, a query object is created and populated within a cfscript tag. In the real world you would pull this from a database.</p>
<pre class="brush: coldfusion;">

&lt;cfscript&gt;
bookQuery = QueryNew(&quot;LastName,FirstName,Title,ISBN,PurchaseLink&quot;);
newRow = QueryAddRow(bookQuery);
QuerySetCell(bookQuery, &quot;LastName&quot;, &quot;Clifton&quot; );
QuerySetCell(bookQuery, &quot;FirstName&quot;,&quot;Brian&quot; );
QuerySetCell(bookQuery, &quot;Title&quot;,&quot;Advanced Web Metrics with Google Analytics&quot; );
QuerySetCell(bookQuery, &quot;ISBN&quot;,&quot;0470253126&quot; );
QuerySetCell(bookQuery, &quot;PurchaseLink&quot;,&quot;&lt;a href='http://www.amazon.com/dp/0470253126?tag=jensbits-20&amp;camp=14573&amp;creative=327641&amp;linkCode=as1&amp;creativeASIN=0470253126&amp;adid=0B10Q2FF6KHJB6ATNA5C&amp;'&gt;Amazon.com&lt;/a&gt;&quot; );
newRow = QueryAddRow(bookQuery);
QuerySetCell(bookQuery, &quot;LastName&quot;, &quot;Gilmore&quot; );
QuerySetCell(bookQuery, &quot;FirstName&quot;,&quot;W. Jason&quot; );
QuerySetCell(bookQuery, &quot;Title&quot;,&quot;Beginning PHP and MySQL: From Novice to Professional, Third Edition&quot; );
QuerySetCell(bookQuery, &quot;ISBN&quot;,&quot;1590598628&quot; );
QuerySetCell(bookQuery, &quot;PurchaseLink&quot;,&quot;&lt;a href='http://www.amazon.com/gp/product/1590598628?ie=UTF8&amp;tag=jensbits-20&amp;link_code=as3&amp;camp=211189&amp;creative=373489&amp;creativeASIN=1590598628'&gt;Amazon.com&lt;/a&gt;&quot; );
newRow = QueryAddRow(bookQuery);
QuerySetCell(bookQuery, &quot;LastName&quot;, &quot;Forta&quot; );
QuerySetCell(bookQuery, &quot;FirstName&quot;,&quot;Ben&quot; );
QuerySetCell(bookQuery, &quot;Title&quot;,&quot;Adobe ColdFusion 8 Web Application Construction Kit, Volume 1: Getting Started &quot; );
QuerySetCell(bookQuery, &quot;ISBN&quot;,&quot;032151548X&quot; );
QuerySetCell(bookQuery, &quot;PurchaseLink&quot;,&quot;&lt;a href='http://www.amazon.com/gp/product/032151548X?ie=UTF8&amp;tag=jensbits-20&amp;link_code=as3&amp;camp=211189&amp;creative=373489&amp;creativeASIN=032151548X'&gt;Amazon.com&lt;/a&gt;&quot; );
&lt;/cfscript&gt;
</pre>
<p>Then a little query of a query so we have data to work with.</p>
<pre class="brush: coldfusion;">
&lt;cfquery dbtype=&quot;query&quot; name=&quot;qryBooks&quot;&gt;
SELECT * FROM bookQuery ORDER BY LastName
&lt;/cfquery&gt;
</pre>
<p>Now for the magic. Load up Google&#8217;s API script. </p>
<pre class="brush: xml;">
 &lt;!--Load the AJAX API--&gt;
    &lt;script type=&quot;text/javascript&quot; src=&quot;http://www.google.com/jsapi&quot;&gt;&lt;/script&gt;
</pre>
<p>And, load the visualization package for what you are creating.</p>
<pre class="brush: jscript;">
// Load the Visualization API and the table package.
  google.load('visualization', '1', {'packages':['table']});
</pre>
<p>Set the callback and load the callback function with data. In the drawVisualization function ColdFusion sets the number of rows with the query recordCount and loops through the query records and fills each row with data. The setCell method uses row and column coordinates to set the data. The rows start at 0 (zero) and since ColdFusion likes to start at 1 (one), we have to subtract 1 from the currentRow to get the row correct for the setCell method.</p>
<p>All single quotes need to be escaped. That can be done easily with the ColdFusion Replace function.</p>
<p>Create the table visualization object and call the draw method on it. The allowHtml option is set to true so the links work in the generated table.</p>
<pre class="brush: jscript;">
  // Set a callback to run when the API is loaded.
  google.setOnLoadCallback(drawVisualization);

  // Callback that creates and populates a data table
  function drawVisualization() {
  	  var dataTable = new google.visualization.DataTable();
  	  dataTable.addColumn('string', 'Last Name');
  	  dataTable.addColumn('string', 'First Name');
  	  dataTable.addColumn('string', 'Title');
  	  dataTable.addColumn('string', 'ISBN');
  	  dataTable.addColumn('string', 'Buy Book');
  	  dataTable.addRows(#qryBooks.recordCount#);

  &lt;cfloop query=&quot;qryBooks&quot;&gt;
      dataTable.setCell(#currentRow#-1, 0, '#LastName#');
      dataTable.setCell(#currentRow#-1, 1, '#FirstName#');
      dataTable.setCell(#currentRow#-1, 2,'book-title', '#Title#', {style: 'font-weight:bold;'});
      dataTable.setCell(#currentRow#-1, 3, '#ISBN#');
      dataTable.setCell(#currentRow#-1, 4, '#Replace(PurchaseLink,&quot;'&quot;,&quot;\'&quot;,&quot;all&quot;)#');
  &lt;/cfloop&gt;

  //Create the table visualization object and call the draw method on it.
  var table = new google.visualization.Table(document.getElementById('table'));
  table.draw(dataTable, {allowHtml: true});

}
</pre>
<p>Stick a div in the body as the target for the table.</p>
<pre class="brush: xml;">
 &lt;body&gt;

	&lt;!---   Div to hold the table   ---&gt;
    &lt;div id=&quot;table&quot;&gt;&lt;/div&gt;

  &lt;/body&gt;
</pre>
<p>You&#8217;ll end up with a table with click to sort columns that looks like this:<br />
<img src="http://jensbits.com/images/googletable.gif" alt="Google Table" /></p>
<p>This example just uses one short page of code so give the Google Visualization API a try. It&#8217;s an easy way to show data and trends. </p>
<p id="download"><a href="/media/code/GVtableCF.txt"><span>Download code</span></a></p>


<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://www.jensbits.com/2009/07/23/google-visualization-api-and-coldfusion-create-a-data-table/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Cfpop with Gmail and Other Pop Accounts: Processing Emails and Attachments</title>
		<link>http://www.jensbits.com/2009/06/07/cfpop-with-gmail-or-other-pop-accounts-processing-emails-and-attachments/</link>
		<comments>http://www.jensbits.com/2009/06/07/cfpop-with-gmail-or-other-pop-accounts-processing-emails-and-attachments/#comments</comments>
		<pubDate>Sun, 07 Jun 2009 21:43:10 +0000</pubDate>
		<dc:creator>jen</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Google]]></category>

		<guid isPermaLink="false">http://www.jensbits.com/?p=209</guid>
		<description><![CDATA[Accessing messages and attachments in gmail via cfpop can be done in a relatively straightforward way. An example of connecting to and reading messages and attachments from gmail is shown here. Enable POP on gmail First things first. POP access must be enabled on the gmail (or other) account before attempting to download the mail. [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>Accessing messages and attachments in gmail via cfpop can be done in a relatively straightforward way. An example of connecting to and reading messages and attachments from gmail is shown here.</p>
<h3>Enable POP on gmail</h3>
<p>First things first. POP access must be enabled on the gmail (or other) account before attempting to download the mail. To enable POP, go to the Forwarding/POP and IMAP panel in Settings. Enable POP and save the settings. <strong>Tip:</strong> you can reset this and download the same messages again while testing by enabling pop again.<br />
<img src="http://jensbits.com/images/gmailpop.jpg" alt="gmail pop settings panel" /></p>
<h3>SSL</h3>
<p>gmail requires SSL to access it via POP. Unfortunately, the cfpop tag does not include SSL. It can be turned on with the following code:</p>
<pre class="brush: coldfusion;">
    &lt;cfset javaSystem = createObject(&quot;java&quot;, &quot;java.lang.System&quot;) /&gt;
    &lt;cfset jProps = javaSystem.getProperties() /&gt;
    &lt;cfset jProps.setProperty(&quot;mail.pop3.socketFactory.class&quot;, &quot;javax.net.ssl.SSLSocketFactory&quot;) /&gt;
    &lt;cfset jProps.setproperty(&quot;mail.pop3.port&quot;,995) /&gt;
    &lt;cfset jProps.setProperty(&quot;mail.pop3.socketFactory.port&quot;, 995) /&gt;
</pre>
<h3>cfpop</h3>
<p>Use cfpop wrapped in a cftry surrounded by a cflock to retrieve the emails. POP is slow and may timeout on you if there are lots of messages and lots of attachments. If that is the case, you may want to retrieve just the headers and selectively grab the messages using the UID. This example grabs everything.</p>
<pre class="brush: coldfusion;">
&lt;cflock name=&quot;cfpop-#form.username#&quot; type=&quot;exclusive&quot; timeout=&quot;50&quot;&gt;

           &lt;cftry&gt;

              &lt;cfpop server=&quot;#form.popserver#&quot; username=&quot;#form.username#&quot; password=&quot;#form.pwd#&quot;
          action=&quot;getAll&quot; name=&quot;getEmail&quot; attachmentpath=&quot;#attachmentFolder#&quot; generateUniqueFilenames=&quot;true&quot;&gt;

           &lt;cfcatch type=&quot;any&quot;&gt;
           &lt;h2 class=&quot;error&quot;&gt;Error Message&lt;/h2&gt;
            &lt;p&gt;&lt;strong&gt;Type:&lt;/strong&gt; #CFCATCH.Type#&lt;/p&gt;
            &lt;p&gt;&lt;strong&gt;Message:&lt;/strong&gt; #CFCATCH.Message#&lt;/p&gt;
            &lt;p&gt;&lt;strong&gt;Detail:&lt;/strong&gt; #CFCATCH.Detail#&lt;/p&gt;
            &lt;cfabort&gt;
        &lt;/cfcatch&gt;

        &lt;/cftry&gt;

&lt;/cflock&gt;
</pre>
<h3>Attachments</h3>
<p>By default the attachments will be downloaded to the temp directory of the server. You can find out where that is with the GetTempDirectory() function.</p>
<pre class="brush: coldfusion;">&lt;cfoutput&gt;#GetTempDirectory()#&lt;/cfoutput&gt;</pre>
<p>Or, you could create a folder specifically for the attachments.</p>
<pre class="brush: coldfusion;">&lt;cfset attachmentFolder = ExpandPath(&quot;attachments&quot;) /&gt;</pre>
<p>Attachment names and files are tab-separated lists in ColdFusion. Putting these lists in an array makes for easy looping later. Set this up by creating the empty arrays.</p>
<pre class="brush: coldfusion;">
&lt;!--- Array for attachment name(s) ---&gt;
&lt;cfset attachmentNameArray = ArrayNew(1) /&gt;

&lt;!--- Array for attachment file(s) ---&gt;
&lt;cfset attachmentFileArray = ArrayNew(1) /&gt;</pre>
<h3>Emails</h3>
<p>Looping backwards over the getEmails query returned by cfpop puts the output in the same order as the inbox with the newest message first. The attachments are stuffed in the arrays using the ListtoArray() function and then looped over to display what and where they are.</p>
<pre class="brush: coldfusion;">
           &lt;p&gt;&lt;strong&gt;Number of Records:&lt;/strong&gt; #getEmail.recordCount#&lt;/p&gt;
           &lt;p&gt;&lt;strong&gt;FYI - TempDirectory:&lt;/strong&gt; #GetTempDirectory()#&lt;/p&gt;

      &lt;ul&gt;
         &lt;cfloop from=&quot;#getEmail.recordCount#&quot; to=&quot;1&quot; step=&quot;-1&quot; index=&quot;i&quot;&gt;

                 &lt;li&gt;&lt;strong&gt;Row: #i#&lt;/strong&gt;&lt;br /&gt;
                     &lt;em&gt;MessageNumber:&lt;/em&gt; #getEmail.messagenumber[i]#&lt;br /&gt;
                     &lt;em&gt;UID:&lt;/em&gt; #getEmail.UID[i]#&lt;br /&gt;
                     &lt;em&gt;From:&lt;/em&gt; #getEmail.From[i]# &lt;br /&gt;
                     &lt;em&gt;Subject&lt;/em&gt;: #getEmail.Subject[i]#&lt;br /&gt;
                     &lt;em&gt;Message:&lt;/em&gt; #getEmail.body[i]#&lt;br /&gt;

                     &lt;cfif Len(getEmail.attachments[i])&gt;
                        &lt;cfset attachmentNameArray = ListtoArray(getEmail.attachments[i], chr(9)) /&gt;
                        &lt;cfset attachmentFileArray = ListtoArray(getEmail.attachmentfiles[i], chr(9)) /&gt;

                            &lt;em&gt;Attachments:&lt;/em&gt;&lt;br /&gt;
                            &lt;cfloop from=&quot;1&quot; to=&quot;#ArrayLen(attachmentNameArray)#&quot; index=&quot;num&quot;&gt;
                                #attachmentNameArray[num]#&lt;br /&gt;
                      		&lt;/cfloop&gt;

                             &lt;em&gt;Attachment Files Server Location:&lt;/em&gt;&lt;br /&gt;
                             &lt;cfloop from=&quot;1&quot; to=&quot;#ArrayLen(attachmentFileArray)#&quot; index=&quot;num&quot;&gt;
                              #attachmentFileArray[num]#&lt;br /&gt;
                            &lt;/cfloop&gt;

                     &lt;/cfif&gt;
                    &lt;/li&gt;

         &lt;/cfloop&gt;
      &lt;/ul&gt;
</pre>
<h3>SSL off</h3>
<p>Turn off SSL and it&#8217;s all done. SSL may or may not interfere with other processes on the server. Turning it off helps alleviate that.</p>
<pre class="brush: coldfusion;">&lt;!--- Turn off SSL ---&gt;
      &lt;cfset jProps.setProperty(&quot;mail.pop3.socketFactory.class&quot;, &quot;javax.net.SocketFactory&quot;) /&gt;
</pre>
<h3>Other Pop-enabled Accounts</h3>
<p>This example can be used with other pop-enabled accounts. Try it without SSL first then add that in if needed. </p>
<p><a href="http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=Tags_p-q_08.html">cfpop documentation from Adobe</a></p>
<p id="download"><a href="http://jensbits.com/media/cfpopgmail.txt"><span>Complete code file</span></a></p>


<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://www.jensbits.com/2009/06/07/cfpop-with-gmail-or-other-pop-accounts-processing-emails-and-attachments/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>3 Steps to Remove Pages and Cached Content from Google Search</title>
		<link>http://www.jensbits.com/2009/05/27/3-steps-to-remove-pages-and-cached-content-from-google-search/</link>
		<comments>http://www.jensbits.com/2009/05/27/3-steps-to-remove-pages-and-cached-content-from-google-search/#comments</comments>
		<pubDate>Wed, 27 May 2009 20:06:29 +0000</pubDate>
		<dc:creator>jen</dc:creator>
				<category><![CDATA[Internet]]></category>
		<category><![CDATA[Google]]></category>

		<guid isPermaLink="false">http://www.jensbits.com/?p=192</guid>
		<description><![CDATA[Google&#8217;s indexing of websites for its search is quite good, quite fast, and quite thorough. There are times, however, that pages on a site should not be indexed. For example, admin sections or include files. Asking Google to remove content is easy and Google&#8217;s response is reasonably fast. If you don&#8217;t own the website that [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>Google&#8217;s indexing of websites for its search is quite good, quite fast, and quite thorough. There are times, however, that pages on a site should not be indexed. For example, admin sections or include files. Asking Google to remove content is easy and Google&#8217;s response is reasonably fast. </p>
<p><strong>If you don&#8217;t own the website that has the material that needs to be removed, don&#8217;t bother reading any further. Contact the website responsible for posting it and ask them to remove it.</strong></p>
<p>Cached content is handled through Webmaster Tools. To remove cached content all the steps below are required.</p>
<p>It should be noted that you can could add a meta tag to pages that should not be indexed as such:</p>
<pre class="brush: xml;">&lt;meta name=&quot;robots&quot; content=&quot;noindex&quot;&gt;</pre>
<p>or for Google only</p>
<pre class="brush: xml;">&lt;meta name=&quot;googlebot&quot; content=&quot;noindex&quot;&gt;</pre>
<p>And for cached pages:</p>
<pre class="brush: xml;">&lt;meta name=&quot;robots&quot; content=&quot;noarchive&quot;&gt;</pre>
<p>or for Google only</p>
<pre class="brush: xml;">&lt;meta name=&quot;googlebot&quot; content=&quot;noarchive&quot;&gt;</pre>
<p>The meta tag method can be tedious for a large number of files and there is no direct feedback from Google on the removal. For expedited removal and assurance from Google that it has been removed from the search results, follow the steps below.</p>
<h3>Step 1: Webmaster Tools</h3>
<p>Sign up the site for <a href="http://www.google.com/webmasters/tools/">Webmaster Tools</a>. Webmaster Tools is easy to set up and provides valuable information on Google&#8217;s indexing of your site. There are also tools to help you create the robots.txt needed for step 2.</p>
<h3>Step 2: Robots.txt</h3>
<p>Create a robots.txt file and place it in the root of the website. There are two rules that should be applied in the robots.txt:</p>
<p><strong>User-agent</strong>: the robot the following rule applies to<br />
<strong>Disallow</strong>: the URL you want to block</p>
<h4>User-Agent</h4>
<p>User-agent allows for the specific selection of search engine robots.</p>
<p>For all search engine bots, the user-agent will be:<br />
<code>User-agent: *</code></p>
<p>For Google bots use:<br />
<code>User-Agent: Googlebot</code></p>
<p>All rules under the User-Agent apply to that User-Agent. You can specify rules for individual User-Agents and list them on the same robots.txt. </p>
<h4>Disallow</h4>
<p>Disallow blocks certain sites, directories, pages, images, or file types.</p>
<p>Block entire site:<br />
<code>Disallow: /</code></p>
<p>Block directory:<br />
<code>Disallow: /junk-directory/</code></p>
<p>Block page:<br />
<code>Disallow: /private_file.html</code></p>
<p>Block specific image from Google image search:<br />
<code>User-agent: Googlebot-Image<br />
Disallow: /images/dogs.jpg</code></p>
<p>Block all images on your site from Google image search:<br />
<code>User-agent: Googlebot-Image<br />
Disallow: /</code></p>
<p>Block files of a specific file type (for example, .gif):<br />
<code>User-agent: *<br />
Disallow: /*.gif$</code></p>
<p>A sample robots.txt to block all files in an include directory might look like this:<br />
<code>User-agent: *<br />
Disallow: /includes/</code></p>
<p>Rules on the robots.txt can be stacked and as specific as you want. For example, to exclude a directory and file from all search engine bots and images from Google:<br />
<code>User-agent: *<br />
Disallow: /includes/<br />
Disallow: /admin.html</code></p>
<p><code>User-agent: Googlebot-Image<br />
Disallow: / </code></p>
<p>All rules below a User-Agent declaration apply to the User-Agent specified only.</p>
<h3>Step 3: Remove URLs/Cached Pages</h3>
<p>In Webmaster Tools request the removal of URL from their index. On Webmaster Tools new interface Remove URLs is under Site Configuration, Crawler Access. For the old interface it&#8217;s under Tools, Remove URLs.</p>
<p>Select whether URLs, directories/subdirectories, entire site, or cached copies should be removed. Hit &#8220;Next&#8221; and put in the URL. If you are removing a cached copy and the page still exists, you will need to add a noarchive meta tag.</p>
<pre class="brush: xml;">&lt;meta name=&quot;robots&quot; content=&quot;noarchive&quot;&gt;</pre>
<p>If the page no longer exists, select &#8220;This page has been modified so that it no longer contains the information that is being cached.&#8221;</p>
<p>The removal will be listed as pending until Google successfully removes it. If for some reason it can&#8217;t remove the URLs, Google will list the error on this page. Google can remove the URLs in a matter of hours if done correctly. Keep in mind that Google&#8217;s documentation states that it can take 3-5 days.</p>
<p>Other search engines will respect the robots.txt but to varying levels. No two search engines are the same and neither is their handling of the robots.txt.</p>


<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://www.jensbits.com/2009/05/27/3-steps-to-remove-pages-and-cached-content-from-google-search/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
