├── README.md
└── src
└── omniture_py.py
/README.md:
--------------------------------------------------------------------------------
1 | Omniture_Py
2 | ===========
3 | A Python Library To Access Omniture's SiteCatalyst Reporting API
4 | ----------------------------------------------------------------------------
5 |
6 | This library simplifies the process of accessing the Omniture SiteCatalyst Reporting API by wrapping the REST API calls in a Python library.
7 |
8 | First, get access configured by reading through documentation at [Omniture Developer Connection](http://developer.omniture.com/). Then, to test authentication/access:
9 |
10 | ```python
11 | import omniture_py
12 | ompy = OmniturePy('username:company','shared_secret')
13 | json_object = ompy.run_omtr_immediate_request('Company.GetReportSuites', '')
14 | for suite in json_object["report_suites"]:
15 | print "Report Suite ID: %s\nSite Title: %s\n" % (suite["rsid"], suite["site_title"])
16 | ```
17 |
18 | 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.
19 |
20 | ```python
21 | print ompy.get_count_from_report('report_suite_name', 'pageViews')
22 | ```
23 |
24 | 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":
25 |
26 | ```python
27 | print ompy.get_count_from_report('report_suite_name', 'pageViews', 'page', ["Homepage","Media Guide"])
28 | ```
29 |
30 | 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. This will return a Python object.
31 |
32 | ```python
33 | obj = ompy.run_omtr_queue_and_wait_request('Report.QueueTrended', {"reportDescription" : reportDescription})
34 | ```
35 |
36 | Full documentation on each of the parameters available to these methods can be found within the code.
--------------------------------------------------------------------------------
/src/omniture_py.py:
--------------------------------------------------------------------------------
1 | from datetime import date, timedelta
2 | from collections import defaultdict
3 | import urllib2, time, binascii, sha, json
4 |
5 | class OmniturePy:
6 |
7 | YESTERDAY_DATE = (date.today() - timedelta(1)).strftime("%Y-%m-%d")
8 |
9 | def __init__(self, user_name, shared_secret):
10 | self.user_name = user_name
11 | self.shared_secret = shared_secret
12 |
13 | def __get_header(self):
14 | nonce = str(time.time())
15 | base64nonce = binascii.b2a_base64(binascii.a2b_qp(nonce))
16 | created_date = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.localtime())
17 | sha_object = sha.new(nonce + created_date + self.shared_secret)
18 | password_64 = binascii.b2a_base64(sha_object.digest())
19 | return 'UsernameToken Username="%s", PasswordDigest="%s", Nonce="%s", Created="%s"' % (self.user_name, password_64.strip(), base64nonce.strip(), created_date)
20 |
21 | def run_omtr_immediate_request(self, method, request_data):
22 | """Send a request to the Omniture REST API
23 | Parameters:
24 | method-- The Omniture Method Name (ex. Report.QueueTrended, Company.GetReportSuites)
25 | request_data-- Details of method invocation, in Python dictionary/list form.
26 | """
27 | request = urllib2.Request('https://api.omniture.com/admin/1.2/rest/?method=%s' % method, json.dumps(request_data))
28 | request.add_header('X-WSSE', self.__get_header())
29 | return json.loads(urllib2.urlopen(request).read())
30 |
31 | def run_omtr_queue_and_wait_request(self, method, request_data,max_polls=20,max_retries=3):
32 | """Send a report request to the Omniture REST API, and wait for its response.
33 | Omniture is polled every 10 seconds to determine if the response is ready. When the response is ready, it is returned.
34 | Parameters:
35 | method-- The Omniture Method Name (ex. Report.QueueTrended, Report.QueueOvertime)
36 | request_data-- Details of method invocation, in Python dictionary/list form.
37 | max_polls-- The max number of times that Omniture will be polled to see if the report is ready before failing out.
38 | max_retries-- The max number of times that we allow Omniture to report a failure, and retry this request before throwing an Exception.
39 | """
40 | status, status_resp = "", ""
41 | num_retries=0
42 | while status != 'done' and num_retries < max_retries:
43 | status_resp = self.run_omtr_immediate_request(method, request_data)
44 | report_id = status_resp['reportID']
45 | status = status_resp['status']
46 | print "Status for Report ID %s is %s" % (report_id, status)
47 | polls=0
48 | while status != 'done' and status != 'failed':
49 | if polls > max_polls:
50 | raise Exception("Error: Exceeded Max Number Of Polling Attempts For Report ID %s" % report_id)
51 | time.sleep(10)
52 | status_resp = self.run_omtr_immediate_request('Report.GetStatus', {"reportID" : report_id})
53 | status = status_resp['status']
54 | print "Status for Report ID %s is %s" % (report_id, status)
55 |
56 | if status == 'failed':
57 | num_retries += 1
58 | print "Omniture Reported Failure For Report. Retrying same request."
59 |
60 | #We exit the while loop only when the report is done or the report has failed and passed the max retries.
61 | if status == 'failed':
62 | raise Exception("Error: Omniture Report Run Failed and passed %s retries. Full response is %s" % (max_retries, status_resp))
63 |
64 | #We are all good, return the report
65 | return self.run_omtr_immediate_request('Report.GetReport', {'reportID' : report_id})
66 |
67 | 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", return_one_total_result = True):
68 | """Send a report request to the Omniture REST API, and return the total count from its response for all selected elements (if any).
69 | Parameters:
70 | report_suite_id-- The name of the report suite configured in Omniture
71 | metric-- See Omniture documentation for full list - examples include visits, pageViews, visitorsMonthly
72 | 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
73 | selected_element_list-- Optional. Python list of all element values to filter on, for example ["Homepage", "Media Guide"]
74 | date_from-- Optional. If ommitted, assumed to be yesterday's date. To set, use date in string form YYYY-MM-DD.
75 | date_to-- Optional. If ommitted, assumed to be yesterday's date. To set, use date in string form YYYY-MM-DD.
76 | date_granularity--Optional. If ommitted, assumed to be "day"
77 | return_one_total_result --Optional. If ommitted, assumed to be "True", and a single integer is returned, which is the sum of the metric for the entire date range. If false, then a dictionary of results is returned, with one result per dat in the date range entered.
78 | """
79 | metrics = [{"id":metric}]
80 |
81 | #Determine which type of report to run based on whether there is an element needed besides date/time
82 | if element == None:
83 | request_type = 'Report.QueueOvertime'
84 | elements = None
85 | else:
86 | request_type= 'Report.QueueTrended'
87 | elements = [{"id":element, "selected": selected_element_list }]
88 |
89 | #Invoke Omniture API with properly formed JSON Request
90 | response = self.run_omtr_queue_and_wait_request(request_type,{"reportDescription":
91 | {"reportSuiteID" :report_suite_id,
92 | "dateFrom":date_from,
93 | "dateTo":date_to,
94 | "dateGranularity":date_granularity,
95 | "metrics": metrics,
96 | "elements" : elements
97 | }})
98 | if response["status"] != "done":
99 | raise Exception("Error: Full response is %s" % response)
100 |
101 | report = response["report"]
102 |
103 | if return_one_total_result:
104 | if selected_element_list == None:
105 | 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.
106 | total_for_selected_elements = 0
107 | for datum in report["data"]:
108 | if datum["name"] in selected_element_list:
109 | 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.
110 | return total_for_selected_elements
111 |
112 | #Handle returning a dictionary of results, with one entry per day.
113 | else:
114 | result_dict = defaultdict(int) #Using a defaultdict here to allow 0 to be set for every value the first time through. Makes code cleaner for QueueTrended, as we dont need to check the presence of the key first.
115 | for datum in report["data"]:
116 | if request_type == "Report.QueueOvertime":
117 | result_dict[datum["name"]] = datum["counts"][0]
118 | elif request_type == "Report.QueueTrended":
119 | if selected_element_list == None or datum["name"] in selected_element_list:
120 | for day_breakdown in datum["breakdown"]:
121 | result_dict[day_breakdown["name"]] += int(day_breakdown["counts"][0])
122 | return result_dict
123 |
124 |
125 |
--------------------------------------------------------------------------------