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="model.google.analytics">
<constructor-arg name="username">
<value>rcamden@gmail.com</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()) & ".riaforge.org" />
<cfset var downloadpage = "/index.cfm?event=action.download" /><!---
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.
Archived Comments
Typo: This is a hard coded account "idea" for RIAForge
idea = id
Fixed, thanks.
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
Nope, didn't have any issue with this at all. I just installed Todd's code and it plain worked.
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?
thanks
I have CF on my Mac talking to a beta Java update. A 1.6.0 version.
@David - I am having similar issues with SSL - were you able to find a solution?
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.
What kind of issues are you having with charts?
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.
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?
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.
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.
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 :)
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" />
</cfchart>
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 ".
Thanks!
Well the error says getCOntentOverview isn't a query. Does that variable exists? If you do:
<cfdump var="#getContentOverview#">
what do you see?
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:
http://www.danhynes.com/pub...
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!
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.
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:
http://pastebin.com/m55ca107f
live site file updated and link is same as above:
http://www.danhynes.com/pub...
I greatly appreciate your help and patience sir!
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
contentoverview.data
As your query.
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!
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.
Yes, thanks for all your help over the last couple of days on this. Happy to have had been your Padawan learner this week.