Github

Using Python, AWS Lambda, & DynamoDB For Analytics

Sometimes you want to instrument a process in your app or website, but creating a whole new service and getting it hosted isn't worth the trouble. Or maybe you just want to start owning your own analytics data. Either way, the combination of AWS Lambda and DynamoDB fit the bill perfectly.

Lambda lets you create functions without having to worry about provisioning servers and scaling them up or down. You simply define a function and AWS takes care of the rest. This lets you create serverless, infinitly scalable and customizable analytics.

To show you how to set this up, lets create an analytics service on AWS Lambda that counts the number of times a given page on your site has been viewed.

Javascript Tracker Client

The Javascript tracker just reads the current URL and sends it off to the Lambda function through an image beacon:

(function(exports, undefined) {
  var baseUrl = 'https://apigatewayurl.com/prod/lambdaAnalytics';
  (new Image()).src = baseUrl +  '?path=' + exports.location.pathname;
})(window);

DynamoDB

We are going to store our analytics data in DynamoDB, which works nicely with Lambda. To get started, create a new table called analytics, with a hash key named path.

Lambda Function

This basic function simply retrieves the path from the event dict (more on that later), and uses that as the key for the DynamoDB table. It then does an atomic increment of that value, creating it if necessary.

To connect to DynamoDB we are using the boto3 library. It is included by default in the Lambda runtime.

import json
import boto3


def handler(event, context):
    client = boto3.client('dynamodb')
    client.update_item(
        TableName='analytics',
        Key={
            'path': { 'S': event['path'] }
        },
        AttributeUpdates={
            'count': {
                'Value': { 'N': '1' },
                'Action': 'ADD'
            }
        }
    )

In order for your Lambda function to have permission to connect to your DynamoDB table, you need to have your function run under a role with DynamoDB privileges. Under the role dropdown when creating the function, choose "Basic with DynamoDB" under "Create New Role".

Expose Your Lambda Function Via API Gateway

The easiest way to expose your Lambda function to the world is through Amazon's API Gateway. Create a new API, and then create a new GET handler on the root Resource (/). Select "Lambda Function" as the Integration Type, and then select your function name:

To use a GET param in your function, you need to tell API Gateway about it. Add the path param under URL Query String Parameters.

We need to tell API Gateway to populate the event dict in your Lambda function with the GET param we just setup. To do this, click on Integration Request and then create a Mapping Template for the application/json Content-Type. The end result should look like this:

Then deploy that API, and take note of the URL. If you deployed to the production environment, it will look something like this:

https://XXXX.execute-api.us-east-1.amazonaws.com/production/lambdaAnalytics

Update the JS client with your production URL, and try it out! You can see the data collected in the DynamoDB console: