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

# What data is needed

> The four kinds of data Auxia uses, with examples of how each is structured

Auxia uses four kinds of first-party data. You don't need all four to start — most teams begin with user attributes and user events, and add the rest over time.

| Data | Describes | Example |
| - | - | - |
| [User attributes](#user-attributes) | Who each user is | Country, plan, sign-up date, lifetime value |
| [User events](#user-events) | What each user does | `page_viewed`, `added_to_cart`, `video_started` |
| [Transaction events](#transaction-events) | What each user buys | Order ID, amount, currency, items purchased |
| [Item attributes](#item-attributes) | The things users interact with | A product's category, price, and discount; an offer's start and end date |

You don't have to reshape your data to match the structures below. Auxia's [Transform stage](/data-ingestion/concepts/how-ingestion-works) maps your tables as they are — these examples show what Auxia looks for, so you know which tables to connect.

## How Auxia uses this data

* **Qualification criteria** — rules that decide which users are eligible for a treatment, such as "signed up in the last 30 days" or "viewed a product twice this week".
* **Content personalization** — inserting attributes into a treatment's content, such as a user's first name or the price of an item they viewed.
* **Treatment selection** — giving the model context to pick the best treatment for each user.
* **Machine learning features** — aggregations such as "logins per week" or "purchases in the last 30 days" that Auxia's models learn from. Ingested data is ready to use as features from day one.

***

## User attributes

User attributes describe the current state of each user — who they are, rather than what they did. Common examples:

* **Profile:** country, language, age band, sign-up date
* **Account:** subscription plan, loyalty tier, account status
* **Value:** lifetime value, total orders, last purchase date
* **Technical:** device type, operating system, app version

Each user attribute table needs:

| Field | Required | Description |
| - | - | - |
| `user_id` | Yes | The [primary user ID](/data-ingestion/concepts/map-your-data#understanding-the-primary-user-id) — the same ID you pass to the [Get Treatments](/api-reference/get-treatments) API |
| Attributes | Yes | One or more attributes describing the user |
| `update_timestamp` | Yes | When the attributes were last updated, so Auxia always uses the latest value |

Attributes can be stored in either of two shapes. Auxia recognizes both automatically.

### Attributes in columns

One row per user, one column per attribute.

| user\_id | country | plan | signup\_date | lifetime\_value | updated\_at |
| - | - | - | - | - | - |
| u\_1001 | US | premium | 2025-03-14 | 412.50 | 2026-10-01T08:00:00Z |
| u\_1002 | JP | free | 2026-07-02 | 0.00 | 2026-10-01T08:00:00Z |
| u\_1003 | GB | premium | 2024-11-20 | 1,280.00 | 2026-10-01T08:00:00Z |

### Attributes in rows

Several rows per user: one column holds the attribute name, another its value.

| user\_id | attribute\_name | attribute\_value | updated\_at |
| - | - | - | - |
| u\_1001 | country | US | 2026-10-01T08:00:00Z |
| u\_1001 | plan | premium | 2026-10-01T08:00:00Z |
| u\_1002 | country | JP | 2026-10-01T08:00:00Z |
| u\_1002 | plan | free | 2026-10-01T08:00:00Z |

***

## User events

Events record what users do — one row per action, with the user, the action, and when it happened. They usually come from your analytics tool or clickstream data, across your website and apps.

| Field | Required | Description |
| - | - | - |
| `user_id` | Yes | The user who performed the event |
| `event_name` | Yes | What happened, such as `sign_up`, `page_viewed`, or `added_to_cart` |
| `event_timestamp` | Yes | When it happened |
| Event properties | No | Context about the event, such as `page_url`, `product_category`, or `cart_value` |
| User properties | No | The user's state at the time of the event, such as `subscription_status` |

| user\_id | event\_name | event\_timestamp | channel | page\_url |
| - | - | - | - | - |
| u\_1001 | page\_viewed | 2026-10-01T10:23:45Z | web | /products/trail-jacket |
| u\_1002 | added\_to\_cart | 2026-10-01T11:45:32Z | app | /products/rain-shell |
| u\_1001 | sign\_up | 2026-10-01T12:15:20Z | app | — |

If every row in a table is the same event (for example, a table of logins), you can give it an event name during setup instead of needing an `event_name` column.

GA4, Firebase, Amplitude, Mixpanel, and Segment event exports are recognized automatically.

***

## Transaction events

Transactions are events that record a purchase. They follow the same structure as user events, with properties that describe the order. Connecting them lets Auxia optimize for revenue and conversion, not just engagement.

| user\_id | event\_name | event\_timestamp | order\_id | item\_id | quantity | amount | currency |
| - | - | - | - | - | - | - | - |
| u\_1001 | order\_completed | 2026-10-01T14:02:11Z | ord\_88412 | sku\_2231 | 1 | 149.00 | USD |
| u\_1001 | order\_completed | 2026-10-01T14:02:11Z | ord\_88412 | sku\_0457 | 2 | 38.00 | USD |
| u\_1003 | subscription\_renewed | 2026-10-02T00:00:05Z | ord\_88530 | plan\_premium | 1 | 12.99 | GBP |

Include an item ID (such as `item_id` or `sku`) when you have one, so transactions can be linked to your [item attributes](#item-attributes).

***

## Item attributes

Item attributes describe the **things users interact with** — products, offers, articles, videos, listings — rather than the users themselves. They give Auxia context about what each user is looking at or buying, so it can recommend similar items or the right offer.

An item table has one row per item, keyed by an item ID that also appears in your events or transactions. It doesn't need a user ID.

**Example: a retail product catalog**

| item\_id | name | category | brand | price | discount\_pct | launch\_date | in\_stock |
| - | - | - | - | - | - | - | - |
| sku\_2231 | Trail Jacket | Outerwear | Acme | 149.00 | 20 | 2026-08-15 | true |
| sku\_0457 | Wool Socks (2-pack) | Accessories | Acme | 19.00 | 0 | 2025-11-01 | true |

**Example: a promotions table**

| offer\_id | offer\_type | discount\_pct | eligible\_category | start\_date | end\_date |
| - | - | - | - | - | - |
| fall\_outerwear\_20 | percent\_off | 20 | Outerwear | 2026-09-15 | 2026-10-31 |
| free\_shipping\_50 | free\_shipping | 0 | All | 2026-10-01 | 2026-12-31 |

Item tables connect through the same self-serve setup wizard as your other tables. They don't need a primary user ID — see [Entity tables](/data-ingestion/concepts/map-your-data#entity-tables-non-user) in Map your data.

***

## Reference: Auxia's unified event schema

Auxia's Transform stage maps every event source into one unified event schema. You don't need to produce this structure yourself — it's here for teams that send events directly with the [Log Events API](/api-reference/log-events) or want to know what Auxia stores.

<AccordionGroup>
  <Accordion title="Proto structure">
    ```proto theme={null}
    syntax = "proto3";

    import "google/protobuf/timestamp.proto";

    message LogEventsRequest {
      // For any given Auxia customer, this should always be the same.
      // Required.
      string project_id = 1;

      // Unique ID for the user that can be joined to events and attributes.
      // Required.
      string user_id = 2;

      // Events for the user.
      // Required.
      repeated ExternalEventPb events = 3;
    }

    // Attributes of a single event.
    message ExternalEventPb {
      // Name of the event.
      // Required.
      string event_name = 1;

      // Auxia uses this identifier to de-duplicate events for the same user.
      // Optional.
      string insert_id = 2;

      // Key-value pairs describing the event.
      // Optional.
      map<string, PropertyValuePb> event_properties = 3;

      // Key-value pairs describing the user.
      // Optional.
      map<string, PropertyValuePb> user_properties = 4;

      // The timestamp of the event.
      // Required.
      .google.protobuf.Timestamp client_event_timestamp = 5;

      // When the event was received by the server.
      // Optional.
      .google.protobuf.Timestamp server_received_timestamp = 6;

      // Identifies a user across signed-out and signed-in sessions.
      // Optional.
      string pre_login_temp_user_id = 7;

      // Optional.
      string session_id = 8;
      string country = 9;
      string region = 10;
      string city = 11;
      string ip_address = 12;
      string device_id = 13;
      string app_version_id = 14;
    }

    // Value corresponding to the property. Set exactly one.
    message PropertyValuePb {
      oneof property_value {
        int64 long_value = 1;
        double double_value = 2;
        string string_value = 3;
        bool boolean_value = 4;
        .google.protobuf.Timestamp timestamp_value = 5;
      }
    }
    ```
  </Accordion>

  <Accordion title="BigQuery schema">
    | Column | Mode | Type | Description |
    | - | - | - | - |
    | `project_id` | REQUIRED | STRING | Unique identifier for a given Auxia customer |
    | `user_id` | REQUIRED | STRING | Unique ID for the user |
    | `event_name` | REQUIRED | STRING | Name of the event |
    | `insert_id` | NULLABLE | STRING | Identifier for de-duplicating events |
    | `event_properties` | REPEATED | RECORD | Key-value pairs describing the event (see below) |
    | `user_properties` | REPEATED | RECORD | Key-value pairs describing the user (see below) |
    | `client_event_timestamp` | REQUIRED | TIMESTAMP | When the event happened |
    | `server_received_timestamp` | NULLABLE | TIMESTAMP | When the server received the event |
    | `pre_login_temp_user_id` | NULLABLE | STRING | Identifies the user across sessions |
    | `session_id` | NULLABLE | STRING | A single user session |
    | `country`, `region`, `city` | NULLABLE | STRING | User location |
    | `ip_address` | NULLABLE | STRING | IP address of the user |
    | `device_id` | NULLABLE | STRING | The user's device |
    | `app_version_id` | NULLABLE | STRING | App version the event came from |

    Each `event_properties` and `user_properties` record has a required `property_name` and exactly one of `long_value` (INTEGER), `double_value` (FLOAT), `string_value` (STRING), `boolean_value` (BOOLEAN), or `timestamp_value` (TIMESTAMP).
  </Accordion>

  <Accordion title="Building properties in SQL (BigQuery)">
    ```sql theme={null}
    CREATE OR REPLACE FUNCTION `<gcp-project-name>.<data-set>.create_properties`(property_name STRING, data_type STRING, column_value STRING)
    RETURNS STRUCT<
        property_name STRING,
        long_value INT64,
        double_value FLOAT64,
        string_value STRING,
        boolean_value BOOL,
        timestamp_value TIMESTAMP
    >
    AS (
      CASE
        WHEN data_type = 'LONG' THEN STRUCT(
          property_name AS property_name, CAST(column_value AS INT64) AS long_value,
          CAST(NULL AS FLOAT64) AS double_value, NULL AS string_value,
          CAST(NULL AS BOOL) AS boolean_value, CAST(NULL AS TIMESTAMP) AS timestamp_value)
        WHEN data_type = 'DOUBLE' THEN STRUCT(
          property_name AS property_name, NULL AS long_value,
          CAST(column_value AS FLOAT64) AS double_value, NULL AS string_value,
          CAST(NULL AS BOOL) AS boolean_value, CAST(NULL AS TIMESTAMP) AS timestamp_value)
        WHEN data_type = 'BOOLEAN' THEN STRUCT(
          property_name AS property_name, NULL AS long_value,
          CAST(NULL AS FLOAT64) AS double_value, NULL AS string_value,
          CAST(column_value AS BOOL) AS boolean_value, CAST(NULL AS TIMESTAMP) AS timestamp_value)
        WHEN data_type = 'TIMESTAMP' THEN STRUCT(
          property_name AS property_name, NULL AS long_value,
          CAST(NULL AS FLOAT64) AS double_value, NULL AS string_value,
          CAST(NULL AS BOOL) AS boolean_value, CAST(column_value AS TIMESTAMP) AS timestamp_value)
        -- STRING, and anything else, is stored as a string.
        ELSE STRUCT(
          property_name AS property_name, NULL AS long_value,
          CAST(NULL AS FLOAT64) AS double_value, column_value AS string_value,
          CAST(NULL AS BOOL) AS boolean_value, CAST(NULL AS TIMESTAMP) AS timestamp_value)
      END
    );
    ```
  </Accordion>
</AccordionGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.