Getting started
Deploy Rainlytics for an existing CloudFront distribution, then read your first pageview report from the command line. The deployment stores access logs and analytics in your AWS account.
You need:
- Node.js 22 or newer
- an AWS CDK app written in TypeScript
- a deployed CloudFront distribution
- AWS credentials that can deploy the resources in this guide
Rainlytics configures CloudFront standard logging v2 through the CloudWatch Logs API in
us-east-1. The example keeps the log bucket, Glue table, Athena workgroup and scheduled jobs in
that region too.
Install Rainlytics
Section titled “Install Rainlytics”Add Rainlytics to your CDK app. Most CDK apps already have the two peer dependencies.
pnpm add @kensio/rainlytics aws-cdk-lib constructsThe package also installs the rainlytics command.
Create the visitor salt
Section titled “Create the visitor salt”The default pageview rollup (a scheduled analytics query) also counts visitors. Rainlytics uses a
secret to derive visitor identifiers for each reporting period. Store that secret in SSM Parameter
Store as a SecureString.
Create the secret once in the account and region where the scheduled jobs will run:
aws ssm put-parameter \ --region us-east-1 \ --name /rainlytics/visitor-salt \ --type SecureString \ --value "$(openssl rand -hex 32)"Use your normal AWS CLI profile or role for this command. Rainlytics never writes the secret to a CloudFormation template. Keep the parameter after deployment because recomputing an old period requires the same secret.
You can omit this step by excluding viewer addresses from log delivery. See Counting visitors.
Add an analytics stack
Section titled “Add an analytics stack”Create a stack like this in your CDK app. Replace the distribution ID with your own.
import { App, CfnOutput, Stack, type StackProps } from "aws-cdk-lib";import { Construct } from "constructs";
import { CloudFrontLogDelivery, LogBucket, LogTable, QueryWorkgroup, RollupQueries, RollupSummaries,} from "@kensio/rainlytics/cdk";
class AnalyticsStack extends Stack { constructor(scope: Construct, id: string, props: StackProps) { super(scope, id, props);
const logs = new LogBucket(this, "Logs");
const delivery = new CloudFrontLogDelivery(this, "Delivery", { distributionId: "E1EXAMPLE1234", logBucket: logs.bucket, });
const table = new LogTable(this, "Table", { deliveries: [delivery], });
const workgroup = new QueryWorkgroup(this, "Workgroup");
const summaries = new RollupSummaries(this, "Summaries", { table, workgroup, });
new RollupQueries(this, "SavedQueries", { summaries });
new CfnOutput(this, "SummaryBucketName", { value: summaries.bucket.bucketName, }); }}
const app = new App();
new AnalyticsStack(app, "Analytics", { env: { account: process.env["CDK_DEFAULT_ACCOUNT"], region: "us-east-1", },});This stack creates:
- a private, versioned S3 bucket for raw logs
- a CloudFront log delivery with hourly Hive partitions
- a Glue database and projected table
- an Athena workgroup with a per-query scan limit
- saved versions of the built-in rollup queries
- scheduled summary and calendar-report jobs
- a second S3 bucket for stored answers
The raw log bucket holds the data needed to rebuild reports. It retains objects for 370 days by default. Separate buckets hold the precomputed summaries and Athena query results, each with its own retention settings.
Passing summaries to RollupQueries saves the same queries that the summary jobs run. Configure
the query list once on RollupSummaries. For a deployment without scheduled summaries, pass
table and workgroup directly to RollupQueries. These configuration forms cannot be combined.
This example puts every resource in us-east-1. Only CloudFrontLogDelivery requires that region.
To store and query data elsewhere, put the delivery in a separate stack. See
Log table.
Synthesize and deploy
Section titled “Synthesize and deploy”Check the template before deployment:
pnpm exec cdk synth Analyticspnpm exec cdk diff --method=template Analyticspnpm exec cdk deploy AnalyticsThe deploy prints SummaryBucketName. Keep that value for the command line.
CloudFront can take up to 12 hours to apply a logging change. New log objects then appear under a path like this:
s3://<log-bucket>/rainlytics/distributionid=E1EXAMPLE1234/year=2026/month=09/day=01/hour=14/The first scheduled summary covers a completed hour. It contains traffic only after CloudFront has delivered the logs for that hour. A new deployment has no historical summaries to read yet.
Run the command line
Section titled “Run the command line”Set the region and summary bucket in your shell:
export AWS_REGION=us-east-1export RAINLYTICS_SUMMARY_BUCKET=<SummaryBucketName>Run a named question:
pnpm exec rainlytics pageviews --last 24hThe command reads your AWS credentials from the standard SDK credential chain. It prints a table at a terminal and JSON when piped.
pnpm exec rainlytics pageviews --last 24h | jq '.[0]'pnpm exec rainlytics status-codes --last 24h --output csv > status-codes.csvNamed questions read the precomputed objects in the summary bucket. Add --query to calculate the
answer directly from the raw logs with Athena:
pnpm exec rainlytics pageviews --last 2h --queryAn Athena query needs write access to the workgroup’s results bucket and query permissions that a read-only role usually lacks. The Query workgroup page shows how to grant the complete set from CDK.
Add the browser beacon
Section titled “Add the browser beacon”The access-log pipeline is complete at this point. Add the browser module only when you need SPA route changes, custom events, Web Vitals or JavaScript errors.
BeaconPath must be added where your CDK app has the Distribution and its origin:
import { BeaconPath } from "@kensio/rainlytics/cdk";
new BeaconPath(this, "AnalyticsBeacon", { distribution, origin,});Start the browser module in your site’s existing JavaScript bundle:
import { startBeacon } from "@kensio/rainlytics/beacon";
const beacon = startBeacon();beacon.report({ event: "signup", page: location.pathname });The collection path defaults to /_rainlytics. The CDK construct and browser module must use the
same path. Continue with Browser beacon for Core Web Vitals, error reporting, consent
and custom event rollups.
Next steps
Section titled “Next steps”- Read Rollups for every built-in question and filter.
- Read Command line for profiles, output formats and reports.
- Adjust raw log retention in Log bucket.
- Review visitor data handling in Counting visitors.
- Review costs and failure checks in Summary schedule.
