A website visitor counter using Amazon Web Services Lambda and DynamoDB for multiple web pages.
To count the visits for two websites, abc.com and xyz.com, we first create a small AWS DynamoDB then use a Lambda function to increment it with each visit.
Each monitored page calls the Lambda function using a small javascript function, run after the page load.
The advantage of this approach is that it gives real world visits rather than metrics that include robots.
First we create the DynomodeDB:
In the AWS console, select DynamoDB then on the left click 'Tables', finally at the top right 'Create table'.
For the Table name use: mycounter and for the Partition key: website
Leave the type as String.
Leave the rest and click 'Create table' at the bottom.
Next the Lambda function. We will use Node.js. In the AWS console, select Lambda and then on the left click Functions then on the top right 'Create function'.
For the 'Function name' use: myct and leave the runtime as Node.js, then click 'Create function' at the bottom.
For the code, replace the source with:
/*global requestJSON*/
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import {
DynamoDBDocumentClient,
PutCommand,
GetCommand,
} from "@aws-sdk/lib-dynamodb";
export const handler = async (event) => {
var name=event.queryStringParameters.name;
if (!name.match(/^(abc|xyz|totals|reset)$/))
{
const response = {
statusCode: 200,
body: 'Unknown'
};
return response;
}
let mybody;
// Create the DynamoDB service object
const client = new DynamoDBClient({});
const dynamo = DynamoDBDocumentClient.from(client);
const tableName = "mycounter";
if (name.match(/^(abc|xyz)$/))
{
var website;
if (name=='abc') website="abc.com";
if (name=='xyz') website="xyz.com";
mybody = await dynamo.send(
new GetCommand({
TableName:tableName,
Key:{"website":website},
}));
mybody=mybody.Item;
var visits=mybody.visits;
visits++;
var body = await dynamo.send(
new PutCommand({
TableName:tableName,
Item:{"website": website,
"visits": visits
},}));
}
if (name=='reset')
{
var thewebsites=["abc.com","xyz.com"];
for(website of thewebsites)
{
var body = await dynamo.send(
new PutCommand({
TableName:tableName,
Item:{"website": website,
"visits": 0
},}));
}
name='totals';
}
if (name=='totals')
{
var thewebsites=["abc.com","xyz.com"];
var thetotals=[];
for(website of thewebsites)
{
mybody = await dynamo.send(
new GetCommand({
TableName:tableName,
Key:{"website": website},
}));
mybody=mybody.Item;
thetotals.push(website+':'+mybody.visits);
}
const dataString = JSON.stringify(thetotals);
const response = {
statusCode: 200,
body: dataString
};
return response;
};
const response = {
statusCode: 200,
body: ''
};
return response;
};
Next click the Configuration tab and on the left Function URL and make it public so it can be called from a web page. Make a note of it.
To give the Lambda function the permission to use the DynamoDB we use IAM to create a policy and then add it to the Lambda function.
In the AWS console select IAM and on the left Policies, then top right, Create policy.
Name it DynamoDB_lambda and use the following replacing the arn with the one for your DynamoDB:
{
"Version": "2024-04-16",
"Statement": [
{
"Effect": "Allow",
"Action": [
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:UpdateItem"
],
"Resource": [
"arn:aws:dynamodb:thedynamoDB"
]
}
]
}
Back on the Lambda function, click Configuration and select Permissions on the left. For the Execicution role select DynamoDB_lambda
Finally, we need to deploy the function to make it available. Above the lambda code there is a Deploy option, just click it.
To call the function, we add the following Javascript to our two webpages. In the header we add the following within script tags:
// For website abc.com
function myfunction() {
var req = new XMLHttpRequest();
req.open("GET", "Your_lambda_URL.aws/?name=abc");
req.send();
};
// For website xyz.com
function myfunction() {
var req = new XMLHttpRequest();
req.open("GET", "Your_lambda_URL.aws/?name=xyz");
req.send();
};
Finally in the Body tag, to run it when the page is loaded:
onload="javascript:myfunction()"
To view the totals from a browser, just use the lambda URL with the query string:
Your_lambda_URL.aws/?name=totals
To reset the totals use:
Your_lambda_URL.aws/?name=reset