Azure Data Lake Storage Gen2
Datafly Signal writes batches of first-party events to ADLS Gen2 — a Blob Storage account with hierarchical namespace enabled — ideal for Spark, Databricks, and Synapse workloads.
Why route Azure Data Lake through Datafly Signal
- The data lands in infrastructure you own. Signal writes to your Azure Data Lake directly from your own deployment. Datafly operates no intermediary and never holds a copy of your event data.
- Client IP and user agent are recorded as event context. Both come from the original visitor request rather than from your server, so geography and device analysis done in the warehouse reflects the actual visitor.
- One consent decision governs every destination. Azure Data Lake is gated by the same consent state as the rest of your stack, so a withdrawal applies everywhere at once.
Prerequisites
Before configuring Azure Data Lake Storage Gen2 in Signal, you need an Azure account with a Storage Account that has hierarchical namespace enabled, and a container for storing events.
Create an Azure Account
If you don’t already have one, sign up at azure.microsoft.com.
Create a Storage Account with Hierarchical Namespace
- In the Azure portal, search for Storage accounts and click Create.
- Select your Subscription and Resource group.
- Enter a Storage account name (e.g.
dataflydatalake). Names must be globally unique, 3-24 characters, lowercase letters and numbers only. - Select a Region close to your Signal deployment.
- Choose Performance: Standard (recommended).
- On the Advanced tab, under Data Lake Storage Gen2, enable Hierarchical namespace. This is required for Data Lake Gen2 functionality.
- Click Review + Create > Create.
Hierarchical namespace cannot be enabled after creation. You must enable it during Storage Account creation. If you have an existing account without it, you will need to create a new one.
Create a Container
- Open your Storage Account in the Azure portal.
- In the left sidebar, click Containers (under Data storage).
- Click + Container.
- Enter a Name (e.g.
datafly-events). - Set Public access level to Private.
- Click Create.
Get the Access Key
- In your Storage Account, go to Security + networking > Access keys.
- Click Show next to Key1.
- Copy the Key value (not the connection string).
Store the access key securely. For production environments, prefer a service principal or AKS workload identity with Azure RBAC instead of account keys. See Authentication.
Configuration
| Field | Type | Required | Description |
|---|---|---|---|
account_name | string | Yes | The Azure Storage account name. Also accepts storage_account. |
container | string | Yes | The Data Lake container (filesystem) name. Also accepts container_name. |
prefix | string | No | Optional path prefix for stored objects (e.g. events/). Include a trailing slash. |
auth_method | select | No | connection_string, account_key, sas, service_principal, managed_identity, workload_identity or default. |
account_key | secret | Per method | Storage account access key. |
connection_string | secret | Per method | Azure Storage connection string. |
sas_token | secret | Per method | SAS token granting Write + Create on the container. |
tenant_id | string | Per method | Microsoft Entra tenant ID (service principal; optional override for workload identity). |
client_id | string | Per method | Application (client) ID (service principal; user-assigned managed identity; optional override for workload identity). |
client_secret | secret | Per method | Service principal client secret. |
file_format | select | Yes | json (newline-delimited, default), parquet or csv. Use Parquet for Databricks. |
parquet_compression | select | No | snappy (default), zstd, gzip or none. |
schema_mode | select | No | canonical (default, 16 fixed columns) or blueprint (typed columns from the blueprint). |
schema_columns | textarea | No | Declared columns for blueprint mode, one per line as name[:type[:source]]. |
batch_size | number | No | Events per file; above 1 consolidates events into one file per partition-hour. Typical: 1000. |
batch_max_wait_ms | number | No | Flush a batch after this long even if it is not full. Default 60000. |
Authentication
auth_method | Credentials | Notes |
|---|---|---|
connection_string | connection_string | Carries the account name and key. |
account_key | account_name, account_key | |
sas | account_name, sas_token | Scope the SAS to the container with Write and Create. |
service_principal | tenant_id, client_id, client_secret | A Microsoft Entra app registration. |
managed_identity | client_id optional | The identity of the VM or node running Signal. Set client_id to pick a user-assigned identity. |
workload_identity | none | AKS workload identity. |
default | none | The Azure SDK default credential chain in the delivery worker environment. |
Choosing an Authentication Method makes that method’s credentials required: the connection cannot be saved until they are filled in. For the Entra ID methods (service principal, managed identity, workload identity), assign Storage Blob Data Contributor on the storage account or container; no storage key is stored in Signal. The Helm values for workload identity are in Azure Blob Storage: Authentication. If auth_method is not set, Signal uses the first credential filled in, as it did before the setting existed.
Signal writes through the storage account’s Blob endpoint (<account>.blob.core.windows.net), which accepts writes to hierarchical-namespace accounts. If the account is only reachable through a private endpoint, create the private endpoint for the blob sub-resource.
Before you connect
- The container must already exist. Signal writes files into it but does not create it.
- Storage firewall. If the account’s firewall is on, allow the delivery workers’ outbound IP addresses, or reach the account through a private endpoint for the
blobsub-resource. - Shared Key disabled. If the account disallows Shared Key authorization, access keys, key-based connection strings and account SAS tokens are refused: use a Microsoft Entra ID method or a user delegation SAS.
- ACLs instead of an RBAC role. With POSIX access control lists on a hierarchical-namespace account, the identity needs Execute on every parent directory of the prefix, and Write and Execute on the directory the files go into.
- Azure Government and Azure China work only with a connection string: the other methods write to
<account>.blob.core.windows.net.
Signal Setup
Quick Setup
- Navigate to Integrations in the sidebar.
- Open the Integration Library tab.
- Find Azure Data Lake Storage Gen2 or filter by Cloud Storage.
- Click Install, select a variant if available, and fill in the required fields.
- Click Install Integration to create the integration with a ready-to-use default blueprint.
API Setup
curl -X POST http://localhost:8084/v1/admin/integration-catalog/azure_data_lake/install \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Azure Data Lake Storage Gen2",
"variant": "default",
"config": {
"account_name": "dataflydatalake",
"container": "datafly-events",
"prefix": "events/",
"auth_method": "service_principal",
"tenant_id": "YOUR_TENANT_ID",
"client_id": "YOUR_APP_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET"
},
"delivery_mode": "server_side"
}'Presets
The blueprint ships the same eight presets as the other file-storage integrations. Each writes one named field per documented event-spec property (canonical names first, the legacy names as fallbacks), plus a global block under @root with the envelope fields, UTM parameters, the analytics and marketing consent flags, and email, phone and names as normalised SHA-256 digests (email_sha256, phone_sha256, first_name_sha256, last_name_sha256, name_sha256; phone shaped to E.164 first). A raw field is a deliberate edit to the installed blueprint. Every preset also stores the consent event’s consent_category, consent_action, consent_message and consent_valid_until.
| Preset | Events |
|---|---|
Retail (ecommerce) | Lists, search, product, cart, checkout, purchase, refund, wishlist, promotions, account and lead events. |
General (general) | Default. Page, identify, search, product view, add to cart, checkout, purchase, refund, lead, sign-up, login, subscription start and cancel. |
Insurance (insurance) | Quotes, leads, policy view, application and checkout, purchase and policy_purchased (policy number as transaction_id), renewals, cancellations, documents and claims. |
Travel (travel) | Flight, hotel, car and destination search, listings, booking, payment, purchase, modifications and cancellations, check-in, loyalty and reviews. |
Media & Streaming (media) | Content engagement, video and audio playback, video content and ads, podcasts, subscriptions and purchases. |
Publishing (publishing) | Articles, content engagement, authors and topics, video and audio, newsletters, paywall and subscriptions. |
B2B / SaaS (saas) | Marketing and leads, authentication, onboarding, trial and subscription lifecycle, product usage, support, referrals and seats. |
Automotive (automotive) | Vehicle search, views, saves, comparisons, brochures, configuration, finance quotes, trade-in valuations, leads, dealer contact, test drives, reservations, purchase and service bookings. |
Only what the blueprint maps is written to properties_json (the row contract). An event with no section in the preset still arrives, with the @root block only: add a section for any other event whose properties you need.
Schema
Signal writes newline-delimited JSON by default, or Parquet (Snappy-compressed) or CSV. CSV and Parquet use either the canonical 16-column layout (message_id, event_type, event_name, … properties_json, context_json) or, with schema_mode set to blueprint, typed columns from your blueprint output, with event_name taken from the blueprint’s vendor event name. See File formats and schema for the column reference.
Files use Hive-style partitions of the event time, which Spark, Databricks Auto Loader and Synapse read directly:
<prefix>/yyyy=2026/mm=09/dd=15/hh=10/<pipeline_id>/<message_id>.parquetStored event context
Alongside the fields your blueprint maps (where email, phone, names and address are stored as normalised SHA-256 by default), each file row carries the event’s collected context exactly as Signal received it. The blueprint does not filter or hash the context: this is deliberate (decision 2026-09-23), so the context is complete for attribution, fraud and debugging queries, and it is listed here so you can decide what to keep.
| Stored | What it contains |
|---|---|
| Visitor request | IP address, user agent, Accept-Language, locale and timezone |
| Page | URL including its query string, path, title and referrer |
| Campaign | UTM source, medium, campaign, term and content |
| Consent | The visitor’s consent state |
| Location | GeoIP country, region and city, and the network (ASN) |
| Device | Screen size; for app events the OS and version, manufacturer, model, advertising ID and IDFV when the app collected them |
| Vendor IDs | Cookie and click identifiers in vendor_ids (for example the _fbp browser ID, gclid, ttclid, the GA client ID) |
| Session and library | Session ID, number and engagement time; the collector’s name and version |
| Partner attributes | Profile attributes from partner enrichment (partner_attrs) |
In each NDJSON line these are the context object, with anonymous_id, user_id, device_id, message_id, event_id, click_ids and collected_ids beside the mapped properties. In CSV and Parquet with the canonical schema they are the ip_address, user_agent, page_url, page_path and page_referrer columns and, in full, the context_json column. In blueprint schema mode only the columns you declare are written.
The IP address, device and advertising IDs, and cookie and click identifiers are personal data under UK and EU GDPR. To keep any of them out of storage, strip, mask or hash the field for every integration with the organisation data layer, apply URL redaction to page URLs, or remove it in the installed blueprint; and set the storage’s retention to match your privacy notice. See Personal data by integration.
Consent
ADLS Gen2 is a first-party destination in your own Azure subscription. The default blueprint forwards all events. Apply consent-aware filtering or partitioning via pipeline transforms on context.consent if needed.
Testing
- Enable the integration in Signal and trigger a test event on your website.
- In the Azure portal, open your Storage Account > Containers > your container.
- Navigate through the path prefix directory structure to find event files.
- Download a file and inspect the event data.
- In Signal, check the Live Events view to confirm delivery status shows as successful.
Troubleshooting
| Problem | Solution |
|---|---|
| Events not appearing in the container | Verify the account name, container name, and access key are correct. |
AuthenticationFailed | The access key is invalid or has been regenerated. Get the current key from Access Keys. |
ContainerNotFound | The container does not exist. Verify the container name in the Azure portal. |
AccountRequiresHttps | Ensure the connection is using HTTPS. Check the storage account settings. |
| Files appearing but empty | Check the batch settings. Events are buffered before flushing to files. |
| Hierarchical namespace errors | Verify that hierarchical namespace was enabled on the Storage Account. It cannot be enabled after creation. |
| Network access denied | Check the Storage Account firewall rules under Networking > Firewalls and virtual networks. Add Signal’s IP addresses if firewall is enabled. |
Visit Azure Data Lake Storage Gen2 documentation for full API reference, access control, and performance tuning guides.