We are pleased to announce the release of the Snowplow Python Tracker version 0.3.0. In this version we have added support for Snowplow custom contexts for all events. We have also updated the API for tracker initialization and ecommerce transaction tracking, added the option to turn off Pycontracts to improve performance, and added an event vendor parameter for custom unstructured events.
In the rest of the post we will cover:
- Tracker initialization
- Disabling contracts
- Ecommerce tracking
- Custom contexts
- Event vendors
- Context vendors
- Tracking method return values
- Other improvements
- Upgrading
- Support
1. Tracker initialization
Several optional configuration arguments have been added to the Tracker
class’s initialization function. Its new signature looks like this:
def __init__(self, collector_uri, namespace=None, app_id=None, context_vendor=None, encode_base64=True, contracts=True):
The example below would initialize a tracker whose name is “cf” for an application whose ID is “ae9f587d23”. It would disable Pycontracts. It does not change the default behaviour of Base64-encoding event data.
from snowplow_tracker.tracker import Tracker t = Tracker("d3rkrsqld9gmqf.cloudfront.net", "cf", "ae9f587d23", "com.example", False)
2. Disabling contracts
The Python Tracker uses the Pycontracts module for type checking, so a runtime error will be raised if you pass a method a parameter of the wrong type. This check does introduce a performance hit, so we have added the option to disable Pycontracts when configuring a tracker by setting the contracts
argument to False
:
from snowplow_tracker.tracker import Tracker t = Tracker("d3rkrsqld9gmqf.cloudfront.net", contracts=False)
3. Ecommerce tracking
In previous versions of the Python Tracker, you had to individually call a tracking method for each item in the ecommerce transaction and for the transaction as a whole. The new version has a single method called track_ecommerce_transaction
that is called once per transaction. This is its signature:
def track_ecommerce_transaction(self, order_id, total_value, affiliation=None, tax_value=None, shipping=None, city=None, state=None, country=None, currency=None, items={}, context=None, tstamp=None):
The required fields are order_id
, total_value
, and items
.
The relevant argument here is items
. This should be an array, each of whose entries is a dictionary containing data about a single item in the transaction. The mandatory fields in the dictionary are sku
, price
, and quantity
.
An example may help. The call to track an ecommerce transaction in which two items are sold might look like this:
t.track_ecommerce_transaction("6a8078be", 45, city="London", currency="GBP", items= [{ "sku": "pbz0026", "price": 20, "quantity": 1, "name": "crystal ball" }, { "sku": "pbz0038", "price": 15, "quantity":
1, "name": "tarot deck" }])
This will fire three events: one for each transaction item and one for the transaction as a whole. The order_id
and currency
fields will be attached to all three events; the total_value
and city
fields will only be attached to the transaction event, not the transaction item events.
The three events are guaranteed to have the same dtm
and tid
fields, where dtm
is the timestamp and tid
is a random 6-digit transaction ID attached to every Snowplow event.
For more detailed documentation, including a full list of fields available for each item in the transaction, see the wiki.
4. Custom contexts
In short, custom contexts let you add additional information about the circumstances surrounding an event in the form of a Python dictionary object. Each tracking method now accepts an additional optional contexts parameter before the optional timestamp parameter:
def track_page_view(self, page_url, page_title=None, referrer=None, context=None, tstamp=None):
The context argument is a Python dictionary. Each of its keys is the name of a context, and each of its values is the flat (not nested) dictionary for that context. So if a visitor arrives on a page advertising a movie, the context argument might look like this:
{ "movie_poster": { # Context entry "movie_name": "Solaris", "poster_country": "JP", "poster_year$dt": new Date(1978, 1, 1) } }
This is how to fire a page view event with the above custom context:
t.track_page_view("http://www.films.com", "Homepage", context={ "movie_poster": { "movie_name": "Solaris", "poster_country": "JP", "poster_year$dt": new Date(1978, 1, 1) } })
In order to avoid confusion between custom contexts defined by different companies, fill in the context_vendor
argument when initializing a tracker:
from snowplow_tracker.tracker import Tracker t = Tracker("d3rkrsqld9gmqf.cloudfront.net", context_vendor="com.example")
Then whenever the tracker fires an event with a custom context, the event will include the context vendor you provide.
The context vendor string should contain no characters other than lowercase letters, underscores, and dots. It should be your company’s reversed Internet domain name – for example, “uk.co.example_biz” for contexts developed at the company with domain name “example-biz.co.uk”.
For more on custom contexts, see the blog post which introduced them in the Snowplow JavaScript Tracker.
5. Event vendors
The event vendor parameter represents the company who developed the model for an event. It is analogous to the context vendor parameter, although it is not part of tracker construction. All events other than custom unstructured events have “com.snowplowanalytics” automatically set in their event vendor field.
Custom unstructured events now have a mandatory event_vendor
initial field:
def track_unstruct_event(self, event_vendor, event_name, dict_, context=None, tstamp=None):
Use it like this:
t.track_unstruct_event("com.your_company", "viewed_product", { "product_id": "ASO01043", "price": 49.95 })
The event vendor string should follow the same rules as the context vendor string.
6. Tracking method return values
Each tracking method now returns a tuple based on the status code of the request it fired. If the code is between 0 and 400, it returns a tuple whose first element is true
and whose second is the code:
(true, 200)
If the code is a number not in that range, the first element is instead false
:
(false, 500)
Finally, if the host is not found:
(false, "Host [http://d3rkrsqld9gmqf.cloudfront.net/i?] not found (possible connectivity error")
7. Other improvements
We have also:
8. Upgrading
The release version of this tracker (0.3.0) is available on PyPI, the Python Package Index repository, as snowplow-tracker. Download and install it with pip:
$ pip install snowplow-tracker --upgrade
Or with setuptools:
$ easy_install -U snowplow-tracker
For more information on getting started with the Snowplow Python Tracker, see the setup page.
9. Support
Please get in touch if you need help setting up the Snowplow Python Tracker or want to suggest a new feature. The Snowplow Python Tracker is still young, so of course do raise an issue if you find any bugs.