Followup to Google/RIAForge Post

This post is more than 2 years old.

Yesterday I blogged about I how I integrated Todd Sharp's ColdFusion/Google API project into RIAForge. I had a few people ask to see a bit of the code, so I thought I'd share how it was added. Credit goes to Todd Sharp for the integration, I just handled the view, and obviously, to see his core Google/CF code, visit his project.

Ok, so to start off with, we added a ColdSpring bean definition for his service:

<bean id="analytics" class=""> <constructor-arg name="username"> <value></value> </constructor-arg> <constructor-arg name="password"> <value>mypassword</value> </constructor-arg> <constructor-arg name="defaultFormat"> <value>xml</value> </constructor-arg> </bean>

As you can see, the API is initialized with my login for Google Analytics. Yes, that's my real password. Go ahead and try it.

Next up is the controller method. This runs the reports I asked Todd to set up. To be clear, these are the reports I wanted added to RIAForge, but do not represent all the data you can get from Google Analytics.

<cffunction name="getAnalytics" access="public" returntype="void" output="false"> <cfargument name="event" type="any" /> <cfset var anal = getModelGlue().getBean("analytics") /> <cfset var id = "ga:1392225" /><!--- hardcoding - make dynamic if you want to ---> <cfset var projectOb = arguments.event.getValue("project")> <cfset var project = lcase(projectOb.getUrlName()) & "" /> <cfset var downloadpage = "/index.cfm?" /><!--- set it as a variable in case it ever changes ---> <cfset var trafficSources = anal.getAnalyticsData(id=id,dimensions="ga:hostname,ga:source,ga:referralPath",metrics="ga:pageViews,ga:visits,ga:newVisits,ga:timeOnSite",filters="ga:hostname=~^#left(project, 21)#", sort="-ga:visits",maxResults=25) /> <cfset var keywords = anal.getAnalyticsData(id=id,dimensions="ga:hostname,ga:keyword",metrics="ga:pageViews,ga:visits,ga:newVisits,ga:timeOnSite",filters="ga:hostname=~^#left(project, 21)#", sort="-ga:visits",maxResults=25) /> <cfset var downloads = anal.getAnalyticsData(id=id,dimensions="ga:hostname,ga:pagePath,ga:month,ga:year", metrics="ga:pageViews",filters="ga:hostname=~^#left(project,21)#;ga:pagePath==#downloadpage#",startDate=dateAdd("m",-11,now())) /> <cfset var views = anal.getAnalyticsData(id=id,dimensions="ga:hostname,ga:month,ga:year",metrics="ga:pageViews,ga:visits,ga:newVisits,ga:timeOnSite",filters="ga:hostname=~^#left(project, 21)#",startDate=dateAdd("m",-11,now())) /> <!--- you might consider caching some of this stuff for performance reasons and because there are rate limits to the google api ---> <cfset arguments.event.setValue("trafficSources", trafficSources) /> <cfset arguments.event.setValue("keywords", keywords) /> <cfset arguments.event.setValue("downloads", downloads) /> <cfset arguments.event.setValue("views", views) /> </cffunction>

I want to first point out this line:

<cfset var id = "ga:1392225" />

This is a hard coded account id for RIAForge. My Google Analytics account has about 10 sites being tracked, and this one specifically focuses it on RIAForge.

After that we simply run four getAnalyticsData calls. I won't go over each call, but you can see how different options, filters, etc, are passed in to get the appropriate data.

And really, that's it! I did have to massage the data a bit in the view. First, the query was sorted newest date to oldest. I also translated the date based columns (one for month and one for year) into one formatted date column. But outside of that, the hard work was already done for me.

Anyway, I hope this helps others and encourages folks to check out the project.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA

Archived Comments

Comment 1 by Todd Rafferty posted on 7/21/2009 at 4:24 PM

Typo: This is a hard coded account "idea" for RIAForge

idea = id

Comment 2 by Raymond Camden posted on 7/21/2009 at 4:33 PM

Fixed, thanks.

Comment 3 by David posted on 7/23/2009 at 2:27 AM

Hi Ray, i'm really loving this idea and want to implement it but i'm pulling out my hair in frustration, i keep getting this error on the cfhttp calls to google:

I/O Exception: peer not authenticated

i looked into it a bit and people are saying that error is normally that the JVM needs the site's SSL cert added to it's keystore, but it seems strange that google's SSL would require such a hack as they'd be using a tier 1 cert provider surely.

did you experience anything like this as i'm sure you are on a similar configuration to me: OSX 10.5.7, cf 8,0,1,195765, jvm 1.6.0_13

Comment 4 by Raymond Camden posted on 7/23/2009 at 3:47 PM

Nope, didn't have any issue with this at all. I just installed Todd's code and it plain worked.

Comment 5 by David posted on 7/26/2009 at 9:58 AM

Hi Ray, this issue has turned into a far greater one for me as i realised now no SSL via cfhttp is working, i'm just wondering if you've run OSX's java update 4 as i suspect that the lastest update has broken SSL in java for me?

Comment 6 by Raymond Camden posted on 7/26/2009 at 2:55 PM

I have CF on my Mac talking to a beta Java update. A 1.6.0 version.

Comment 7 by Scott Stroz posted on 8/3/2009 at 6:01 PM

@David - I am having similar issues with SSL - were you able to find a solution?

Comment 8 by Marc posted on 11/18/2009 at 1:02 AM

Anyone have any luck with formating the output? I was actually hoping to get them into cfchart or cfgraph, but really have not had any luck doing anything but outputing the tables on the test page.

Comment 9 by Raymond Camden posted on 11/18/2009 at 1:24 AM

What kind of issues are you having with charts?

Comment 10 by Marc posted on 11/18/2009 at 2:28 AM

well, they are not showing up. I got the table to all worm in the
analyticsTestPublic.cfm that comes with the coldfusion google api, but can not figure our how to do anything other than cfdump them. I also tried to copy your code above and change out the customizations to make it work for mine and I can not get anything but the bean info to output. Do you know of any other examples of using the google api and cutomzing output.

Comment 11 by Raymond Camden posted on 11/18/2009 at 2:33 AM

Errr well - the result is data and you pass that data to cfchart. How you pass it depends on what you want to chart. Have you read the docs on cfchart/cfchartseries/cfchartdata? Knowing the syntax should give you a clue as to how to convert the data returned from the CFC into something the chart can use. Does that make sense?

Comment 12 by Marc posted on 11/18/2009 at 3:20 AM

Thanks Raymond, let me look at the cfchartdata tag and see if I can get a clearer view on how to get the data from the google api into the cfchart.

Comment 13 by Marc posted on 11/18/2009 at 6:10 AM

I guess, I am getting ahead of myself. And forgive me if this is a really basic question, but what I am having trouble with is how to access the data that comes back. I guess it comes back as a struct. but there does not seem to be anything in the documentation that talks about how to use the return data. It is possible that I am just a bit over my head, but hat is really what I am looking for is other than cfdump var code that is used in the public test I am not sure how to access the data back.

Comment 14 by Raymond Camden posted on 11/18/2009 at 9:37 AM

When you dump the data, what do you see in the struct? I believe you get a query and another struct. So the query object would be like any other database query. You can cfloop over it, cfoutput query it, etc. You may want to consider reading some of the CF docs, specifically on data types (like structs :)

Comment 15 by Ryan posted on 11/21/2009 at 1:55 AM

Hey Ray,

Following up on your's and Marc's conversation, can you explain why the following code isn't working for me?

<cfchart format="flash" show3d="true" chartwidth="680" chartheight="300" pieslicestyle="solid" title="Top 10 pages" style="#style#">
<cfchartseries type="pie" query="getContentOverview" valueColumn="pageviews" itemColumn="pagepath" />

I've added this to the bottom of the analyticstestpublic.cfm file and keep getting an error... I've tried changing the query name to all variants of above that seemed relevant and keep getting the "Query not found: getContentOverview ".


Comment 16 by Raymond Camden posted on 11/21/2009 at 2:04 AM

Well the error says getCOntentOverview isn't a query. Does that variable exists? If you do:

<cfdump var="#getContentOverview#">

what do you see?

Comment 17 by Ryan posted on 11/21/2009 at 2:16 AM

Actually, the cfdump part is working fine and I am getting both a struct and a query returned....

the test page I'm working on is:

and as you'll see both the struct and query are there and have data... I just cant figure out why I cant access the query...

thanks so much for your help and this killer component!

Comment 18 by Raymond Camden posted on 11/21/2009 at 2:29 AM

I'm sorry - but where are you dumping getCOntentOverview? I don't see it. Please add that dump and use label="This is getContentOverview". Also, paste your code to pastebin please.

Comment 19 by Ryan posted on 11/21/2009 at 2:37 AM

Ok, fixed a couple things:

I actually originally pasted the wrong version of the code... here it is with the query set to the "#contentOverview#" dump... I added the label you asked about and here is the pastebin link of my source:

live site file updated and link is same as above:

I greatly appreciate your help and patience sir!

Comment 20 by Raymond Camden posted on 11/21/2009 at 3:12 AM

Look at the dump of contentover. It isn't a query! It is a struct. Inside the struct is a query, specifically the data key. You want to use

As your query.

Comment 21 by Ryan posted on 11/21/2009 at 3:47 AM

you sir, truly are a king amongst men!!

I was misunderstanding the structure of what the dump was giving me... Cannot thank you enough sir!

Comment 22 by Raymond Camden posted on 11/21/2009 at 3:52 AM

Glad you got it. FYI, don't thank me for the code (although I'll take thanks for the help ;) Todd Sharp wrote the component.

Comment 23 by Marc posted on 11/21/2009 at 6:07 AM

Yes, thanks for all your help over the last couple of days on this. Happy to have had been your Padawan learner this week.