> ## Documentation Index
> Fetch the complete documentation index at: https://docs.siteline.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# AWS CloudFront

> Integrate Siteline with CloudFront standard logs in S3

Use the Siteline AWS CloudFront S3 Log Processor to track CloudFront traffic with Siteline. This advanced/self-hosted integration processes CloudFront standard access logs from S3, triggers on S3 object-created events via EventBridge, and forwards pageview events to the Siteline API.

<Info>
  If you use Fastly, the recommended setup is the direct [Fastly HTTPS logging integration](/integrations/fastly). It avoids the AWS S3/EventBridge/Lambda path.
</Info>

## Prerequisites

* A [Siteline website key](/authorization)
* An existing CloudFront distribution configured to write **standard access logs** to S3
* AWS CLI v2 configured for the target account
* `jq` and `zip` installed locally
* Node.js 18+ and npm
* IAM permissions for `s3`, `lambda`, `iam`, and `events`

<Info>
  CloudFront standard logs are delayed by design. Typical availability is **5-15 minutes** after requests occur.
</Info>

## Setup

<Steps>
  <Step title="Clone and install">
    ```bash theme={null}
    git clone https://github.com/siteline-ai/siteline-cloudfront.git
    cd siteline-cloudfront
    npm install
    ```
  </Step>

  <Step title="Configure environment variables">
    ```bash theme={null}
    cp .env.example .env
    ```

    Set at minimum:

    * `SITELINE_WEBSITE_KEY`
    * `LOG_BUCKET_NAME`
    * `AWS_REGION`
    * `AWS_PROFILE` (if using SSO or non-default profile)
  </Step>

  <Step title="Build and package Lambda">
    ```bash theme={null}
    npm run package
    ```
  </Step>

  <Step title="Provision AWS resources">
    ```bash theme={null}
    npm run setup:all
    ```

    This runs:

    * `npm run setup:s3`
    * `npm run setup:lambda`
    * `npm run setup:eventbridge`
  </Step>

  <Step title="Point CloudFront logs to the configured bucket">
    In your CloudFront distribution settings, enable **standard access logs** and confirm logs are written to `LOG_BUCKET_NAME`.
  </Step>
</Steps>

## How it works

This integration uses S3 log delivery, EventBridge, and Lambda:

```text theme={null}
CloudFront (standard logs)
  -> S3 log bucket
  -> EventBridge (Object Created)
  -> Lambda s3-log-processor
  -> Siteline intake API
```

Processing flow:

1. CloudFront writes gzipped log files to S3.
2. S3 sends `Object Created` events to EventBridge.
3. EventBridge invokes the Lambda processor.
4. Lambda downloads and gunzips the log file.
5. Lambda parses the `#Fields` header dynamically, maps each valid row, and sends events to Siteline.

Rows with invalid status codes or missing URI are skipped. Malformed rows are skipped without stopping the rest of the file.

## Configuration

<ResponseField name="SITELINE_WEBSITE_KEY" type="string" required>
  Your Siteline website key. If missing, the Lambda exits without processing logs.
</ResponseField>

<ResponseField name="LOG_BUCKET_NAME" type="string" required>
  S3 bucket used for CloudFront standard logs. Lambda only reads objects from this bucket.
</ResponseField>

<ResponseField name="AWS_REGION" type="string" required>
  AWS region used by setup scripts and Lambda operations.
</ResponseField>

<ResponseField name="S3_BUCKET_REGION" type="string">
  Region override for S3 bucket operations. Defaults to `AWS_REGION`.
</ResponseField>

<ResponseField name="SITELINE_ENDPOINT" type="string">
  Siteline intake endpoint. Defaults to `https://api.siteline.ai/v1/intake/pageview`.
</ResponseField>

<ResponseField name="SITELINE_DEBUG" type="boolean">
  Enables debug mode in the Siteline SDK.
</ResponseField>

<ResponseField name="LAMBDA_FUNCTION_NAME" type="string">
  Lambda function name. Default is `siteline-cloudfront-s3-processor`.
</ResponseField>

<ResponseField name="EVENT_RULE_NAME" type="string">
  EventBridge rule name for S3 object-created events.
</ResponseField>

## Required IAM policies

Lambda trust policy:

```json theme={null}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": ["lambda.amazonaws.com"]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
```

Lambda execution policy (bucket name is injected during setup):

```json theme={null}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowCloudWatchLogs",
      "Effect": "Allow",
      "Action": ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"],
      "Resource": "arn:aws:logs:*:*:*"
    },
    {
      "Sid": "AllowReadCloudFrontLogsFromS3",
      "Effect": "Allow",
      "Action": ["s3:GetObject"],
      "Resource": "arn:aws:s3:::<LOG_BUCKET_NAME>/*"
    }
  ]
}
```

## Troubleshooting

<AccordionGroup>
  <Accordion title="No Lambda invocations">
    Confirm CloudFront is writing standard logs to `LOG_BUCKET_NAME`, then verify S3 EventBridge notifications are enabled on that bucket.
  </Accordion>

  <Accordion title="No EventBridge to Lambda delivery">
    Check targets with:

    ```bash theme={null}
    aws events list-targets-by-rule --name "${EVENT_RULE_NAME}" --region "${AWS_REGION}"
    ```
  </Accordion>

  <Accordion title="AccessDenied errors during setup or runtime">
    Ensure deployer permissions include S3, IAM, Lambda, and EventBridge management. Also confirm Lambda execution role has `s3:GetObject` on the log bucket.
  </Accordion>

  <Accordion title="How do I inspect processor logs?">
    Stream CloudWatch logs with:

    ```bash theme={null}
    aws logs tail "/aws/lambda/${LAMBDA_FUNCTION_NAME}" --follow --region "${AWS_REGION}"
    ```
  </Accordion>
</AccordionGroup>

<Tip>
  **Need help?** [Book a setup call](https://cal.com/team/siteline/tech-set-up) and we'll walk you through it.
</Tip>
