Formo defines some common fields (event type, timestamps, and more) across all API calls that make up the core event data structure. This guide covers the common and contextual fields in detail.

Common Fields

The Formo SDKs populate the required information automatically.

NameDatatypeRequiredDescription
typeStringCaptures the type of event. Values can be either identify, track, connect, signature, transaction, and others.
channelStringIdentifies the source of the event. Permitted values are mobile, web, server and sources.
versionStringVersion of the event spec.
project_idStringUnique identification for the project in the database.
session_idStringPrivacy-friendly daily changing session identifier.
anonymous_idStringPseudo-identifier for the user in cases where userId is absent. Equivalent to a device ID.
user_idStringUnique identification for the user in the database.
addressStringUnique wallet address of the user.
eventStringCaptures the user action that you want to record.
contextObjectContains all additional user information.
propertiesObjectPasses all relevant information associated with the event.
original_timestampTimestampRecords the actual time (in UTC) when the event occurred.
sent_atTimestampCaptures the time (in UTC) when the event was sent from the client to Formo.
received_atTimestampTime in UTC when Formo ingests the event.
timestampTimestampFormo calculates this field to account for any client-side clock skew using the formula: timestamp = received_at - (sent_at - original_timestamp). Note that this time is in UTC.
message_idStringUnique identification for the event.

Contextual Fields

Contextual fields give additional information about a particular event. The following table describes the available contextual fields.

NameDatatypeRequiredDescription
user_agentStringThe user agent of the device that you are tracking.
localeStringCaptures the language of the device.
locationStringGeographic location of the user.
timezoneStringCaptures the timezone of the user you are tracking.
referrerStringThe referrer URL where the user came from.
utm_sourceStringIdentifies which site sent the traffic.
utm_mediumStringIdentifies what type of link was used.
utm_campaignStringIdentifies a specific product promotion or strategic campaign.
utm_termStringIdentifies search terms.
utm_contentStringIdentifies what specifically was clicked to bring the user to the site.
refStringReferral code or identifier.
page_urlStringFull URL of the page.
page_pathStringPath component of the URL.
page_titleStringTitle of the page.
library_nameStringName of the SDK used to capture the event.
library_versionStringVersion of the SDK used to capture the event.

Timestamps

Every API call has four timestamps: original_timestamp, timestamp, sent_at, and received_at. They’re used for very different purposes.

All timestamps are ISO-8601 date strings, and are in the UTC timezone. To see the user’s timezone information, check the timezone property that’s automatically collected by client-side SDKs.

Timestamp overview

NameCalculated / Value
original_timestampTime on the client device when call was invoked OR The timestamp value manually passed in through server-side libraries.
sent_atTime on client device when call was sent OR sent_at value manually passed in.
received_atTime on Formo server clock when call was received
timestampCalculated by Formo to correct client-device clock skew using the following formula: received_at - (sent_at - original_timestamp)

Original Timestamp

The original_timestamp tells you when call was invoked on the client device or the value of timestamp that you manually passed in.

Note: The original_timestamp timestamp is not useful for any analysis since it’s not always trustworthy as it can be easily adjusted and affected by clock skew.

Sent At

The sent_at timestamp specifies the clock time for the client’s device when the network request was made to the Formo API.

For libraries and systems that send batched requests, there can be a long gap between a datapoint’s timestamp and sent_at. Combined with received_at, Formo uses sent_at to correct the original_timestamp in situations where a user’s device clock cannot be trusted (mobile phones and browsers). The sent_at and received_at timestamps are assumed to occur at the same time (maximum a few hundred milliseconds), and therefore the difference is the user’s device clock skew, which can be applied back to correct the timestamp.

Note: The sent_at timestamp is not useful for any analysis since it’s tainted by user’s clock skew.

Received At

The received_at timestamp is added to incoming messages as soon as they hit the API. It’s used in combination with sent_at to correct clock skew, and also to aid with debugging libraries and systems that deliver events in batches.

Timestamp

The timestamp specifies when the data point occurred, corrected for client-device clock skew. This is the timestamp that is passed to downstream destinations and used for historical replays. It is important to use this timestamp for importing historical data to the API.

Formo automatically generates timestamp and you cannot manually set one directly in the call payload.

Formo calculates timestamp as timestamp = received_at - (sent_at - original_timestamp).

Sample Event

Here’s an example event with common and contextual fields included:

{
    "type": "page",
    "channel": "web",
    "version": "1",
    "project_id": "d5naNbBlqxSBXLuNa6zwc",
    "session_id": "117b982a451dc22edea6413b8e20958216c0a5b3baaa1d90699c42dbf4e74e33",    
    "anonymous_id": "c2bc0ebe-d852-49d1-9efd-e45744850ae0",
    "user_id": "a46e6878-1ed5-4a81-9185-83608df2fcb6",
    "address": "0x8e6ca77a7e044ba836a97beb796c124ca3a6a154",   
    "event": "FooBar", 
    "context": {
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36",
        "locale": "en-US",
        "location": "ID",
        "timezone": "Asia/Saigon",
        "referrer": "https://chatgpt.com/",
        "utm_source": "chatgpt.com",
        "utm_medium": "linkedin",
        "utm_campaign": "early-access",
        "utm_term": null,
        "utm_content": null,
        "ref": "vitalik.eth",
        "page_url": "https://www.estore.com/best-seller/1",
        "page_path": "/best-seller/1",
        "page_title": "The best sellers offered by EStore",
        "library_name": "Formo Web SDK",
        "library_version": "1.16.2"
    },
    "properties": {
        "name": "Best Seller",
        "category": "Docs",
        "url": "https://formo.so/faucets?utm_source=chatgpt.com",
        "path": "/best-seller/1",
        "hash": "#submit",
        "title": "The best sellers offered by EStore"
    },
    "message_id": "48555101eee2f44ac0f0632fcb7c7c9f6ce0012ae395ae79f8a0d515e4f5e41f",
    "original_timestamp": "2025-04-03 18:21:00",
    "sent_at": "2025-04-03 18:21:00",
    "received_at": "2025-04-03 18:21:00",
    "timestamp": "2025-04-03 18:21:00"
}