Skip to content

Commit

Permalink
Made library into object, added report count capability
Browse files Browse the repository at this point in the history
  • Loading branch information
RobGoretsky committed Sep 20, 2011
1 parent 60889b0 commit 9ce94af
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 34 deletions.
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
Omniture_Py
===========
A Python Library To Simplify Accessing Omniture's SiteCatalyst Reporting API
----------------------------------------------------------------------------

This library simplifies the process of accessing the Omniture SiteCatalyst Reporting API by wrapping the REST API calls in a Python library.

First, get access configured by reading through documentation at [Omniture Developer Connection](http://developer.omniture.com/)

Then, to test authentication/access:
import omniture_py
ompy = OmniturePy('username:company','shared_secret')
json_object = ompy.run_omtr_immediate_request('Company.GetReportSuites', '')
for suite in json_object["report_suites"]:
print "Report Suite ID: %s\nSite Title: %s\n" % (suite["rsid"], suite["site_title"])

To get total number of page views yesterday, just run the following. It runs an "Overtime" report in SiteCatalyst,
with 'pageViews' as the metric, and returns the numeric total result.
print ompy.get_count_from_report('report_suite_name', 'pageViews')


To get number of page views for "Homepage" and "Media Guide" combined, yesterday, run the following. It runs a "Trended"
report in SiteCatalyst, using 'pageViews' as the metric, and 'page' as the Element, and then selecting for pages titled either
"Homepage" or "Media Guide"
print ompy.get_count_from_report('report_suite_name', 'pageViews', 'page', ["Homepage","Media Guide"])

The get_count_from_report function currently supports requesting one dimension (called an 'element') in addition to the date, which is always implied to be included. It also only currently supports requesting one metric at a time.

If you wish to have lower-level access to the Omniture API than this, you can just use the run_omtr_queue_and_wait_request, and pass it the type of request and full request body:
obj = ompy.run_omtr_queue_and_wait_request('Report.QueueTrended', {"reportDescription" : reportDescription})



121 changes: 87 additions & 34 deletions src/omniture_py.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,91 @@
from datetime import date, timedelta
import urllib2, time, binascii, sha, json

USER_NAME = 'username:company'
SHARED_SECRET = 'sharedsecret'

def get_header():
nonce = str(time.time())
base64nonce = binascii.b2a_base64(binascii.a2b_qp(nonce))
created_date = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.localtime())
sha_object = sha.new(nonce + created_date + SHARED_SECRET)
password_64 = binascii.b2a_base64(sha_object.digest())
return 'UsernameToken Username="%s", PasswordDigest="%s", Nonce="%s", Created="%s"' % (USER_NAME, password_64.strip(), base64nonce.strip(), created_date)

def run_omtr_immediate_request(method, request_data):
request = urllib2.Request('https://api.omniture.com/admin/1.2/rest/?method=%s' % method, json.dumps(request_data))
request.add_header('X-WSSE', get_header())
return json.loads(urllib2.urlopen(request).read())

def run_omtr_queue_and_wait_request(method, request_data):
status_resp = run_omtr_immediate_request(method, request_data)
report_id = status_resp['reportID']
status = status_resp['status']
print "Status for Report ID %s is %s" % (report_id, status)
while status != 'done':
time.sleep(5)
status_resp = run_omtr_immediate_request('Report.GetStatus', {"reportID" : report_id})
status = status_resp['status']
print "Status for Report ID %s is %s" % (report_id, status)
return run_omtr_immediate_request('Report.GetReport', {'reportID' : report_id})
class OmniturePy:


#Just for testing, this will ensure that you can connect to your report suite
if __name__ == '__main__':
json_object = run_omtr_immediate_request('Company.GetReportSuites', '')
for suite in json_object["report_suites"]:
print "Report Suite ID: %s\nSite Title: %s\n" % (suite["rsid"], suite["site_title"])

YESTERDAY_DATE = (date.today() - timedelta(1)).strftime("%Y-%m-%d")

def __init__(self, user_name, shared_secret):
self.user_name = user_name
self.shared_secret = shared_secret

def __get_header(self):
nonce = str(time.time())
base64nonce = binascii.b2a_base64(binascii.a2b_qp(nonce))
created_date = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.localtime())
sha_object = sha.new(nonce + created_date + self.shared_secret)
password_64 = binascii.b2a_base64(sha_object.digest())
return 'UsernameToken Username="%s", PasswordDigest="%s", Nonce="%s", Created="%s"' % (self.user_name, password_64.strip(), base64nonce.strip(), created_date)

def run_omtr_immediate_request(self, method, request_data):
"""Send a request to the Omniture REST API
Parameters:
method-- The Omniture Method Name (ex. Report.QueueTrended, Company.GetReportSuites)
request_data-- Details of method invocation, in Python dictionary/list form.
"""
request = urllib2.Request('https://api.omniture.com/admin/1.2/rest/?method=%s' % method, json.dumps(request_data))
request.add_header('X-WSSE', self.__get_header())
return json.loads(urllib2.urlopen(request).read())

def run_omtr_queue_and_wait_request(self, method, request_data):
"""Send a report request to the Omniture REST API, and wait for its response.
Omniture is polled every 10 seconds to determine if the response is ready. When the response is ready, it is returned.
Parameters:
method-- The Omniture Method Name (ex. Report.QueueTrended, Report.QueueOvertime)
request_data-- Details of method invocation, in Python dictionary/list form.
"""
status_resp = self.run_omtr_immediate_request(method, request_data)
report_id = status_resp['reportID']
status = status_resp['status']
print "Status for Report ID %s is %s" % (report_id, status)
while status != 'done' and status != 'failed':
time.sleep(10)
status_resp = self.run_omtr_immediate_request('Report.GetStatus', {"reportID" : report_id})
status = status_resp['status']
print "Status for Report ID %s is %s" % (report_id, status)
return self.run_omtr_immediate_request('Report.GetReport', {'reportID' : report_id})

def get_count_from_report(self, report_suite_id, metric, element=None, selected_element_list=None, date_from=YESTERDAY_DATE, date_to=YESTERDAY_DATE, date_granularity="day"):
"""Send a report request to the Omniture REST API, and return the total count from its response for all selected elements (if any).
Parameters:
report_suite_id-- The name of the report suite configured in Omniture
metric-- See Omniture documentation for full list - examples include visits, pageViews, visitorsMonthly
element-- Optional. If ommitted, the only element used is the date, and the report is run an Overtime report. See Omniture docs for full list - examples include page, prop11
selected_element_list-- Optional. Python list of all element values to filter on, for example ["Homepage", "Media Guide"]
date_from-- Optional. If ommitted, assumed to be yesterday's date. To set, use date in string form YYYY-MM-DD.
date_to-- Optional. If ommitted, assumed to be yesterday's date. To set, use date in string form YYYY-MM-DD.
date_granularity--Optional. If ommitted, assumed to be "day"
"""
metrics = [{"id":metric}]

#Determine which type of report to run based on whether there is an element needed besides date/time
if element == None:
request_type = 'Report.QueueOvertime'
elements = None
else:
request_type= 'Report.QueueTrended'
elements = [{"id":element, "selected": selected_element_list }]

#Invoke Omniture API with properly formed JSON Request
response = self.run_omtr_queue_and_wait_request(request_type,{"reportDescription":
{"reportSuiteID" :report_suite_id,
"dateFrom":date_from,
"dateTo":date_to,
"dateGranularity":date_granularity,
"metrics": metrics,
"elements" : elements
}})
if response["status"] != "done":
raise Exception("Error: Full response is %s" % response)

report = response["report"]
if selected_element_list == None:
return int(report["totals"][0]) #Using the first element here since we only support one metric. If we want to support more than one metric, would need to handle that here.

total_for_selected_elements = 0
for datum in report["data"]:
if datum["name"] in selected_element_list:
total_for_selected_elements += int(datum["counts"][0]) #Using the first element here since we only support one metric. If we want to support more than one metric, would need to handle that here.
return total_for_selected_elements


0 comments on commit 9ce94af

Please sign in to comment.