Data Types and Field Values
Reference for how Ours interprets null, undefined, and empty string values across the Ingest API, Web SDK, webhooks, and other sources.
Data Types and Field Values
When you send data to Ours — through the Ingest API, Web SDK, webhooks, or any other source — the value you pass for a field determines whether Ours sets, ignores, or clears that field on a visitor.
Getting this right matters most when a source sometimes doesn't have a value to send. The wrong choice can wipe out a previously captured value — for example, an ad click ID captured on the landing page.
Top-level visitor properties
Applies to fields like email, first_name, external_id, phone_number, gclid, fbclid, and every other top-level attribute listed in Visitor Properties Overview.
| Value you send | What happens |
|---|---|
A concrete value ("abc", 42, true) | Set — the field is saved (and overwrites any existing value) |
null | Clears — the existing value is unset |
undefined, or the field is omitted | Ignored — the existing value is preserved |
"" (empty string) | Ignored — treated the same as omitting the field |
Custom properties
Applies to entries inside the custom_properties object.
| Value you send | What happens |
|---|---|
| A concrete value | Set — the property is saved or updated |
null | Ignored — the existing value is preserved |
undefined, or the key is omitted | Ignored — the existing value is preserved |
"" (empty string) | Ignored — the existing value is preserved |
custom_properties use partial (merge) updates — sending a subset of keys never removes keys you didn't include. See Custom Properties for examples.
Difference from top-level fields:
nulldoes not clear acustom_propertiesentry. If you need to remove a custom property, contact support.
Why this matters
If you send { "gclid": null } as a top-level visitor property, Ours will clear the existing gclid on that visitor. This is intentional — it lets you explicitly remove a value.
Many source systems render missing fields as null in their payloads. Webhook templates, for example, often interpolate a merge tag as the literal value null when the underlying field is empty. If those payloads are mapped to top-level visitor properties, every subsequent event can wipe out previously captured attribution data.
Common pitfalls
- Webhook payloads with
nullmerge fields — If a later event from the same webhook carries{"gclid": null}for a contact that didn't originally have one, the visitor's storedgclidwill be cleared. See Webhooks Integration and GoHighLevel Integration for source-specific guidance. - SDK calls with conditional values —
ours('identify', { gclid: capturedGclid })wherecapturedGclidresolves tonullwill clear the field. Useundefinedor omit the key entirely if you don't have a value. - Server-side JSON serializers that emit
nullfor missing fields — Prefer leaving the key out of the payload over sendingnull.
How to say "I don't have a value"
Any of these will cause Ours to leave the existing value alone:
- Omit the key from the payload
- Send the key with
undefined(this is dropped during JSON serialization) - Send an empty string
""
How to explicitly clear a value
Send null as the value for a top-level visitor property:
{
"email": "visitor@example.com",
"phone_number": null
}This unsets phone_number on the visitor record while leaving all other fields untouched.
Where this applies
These rules apply to every path that writes visitor properties:
- The
/trackand/identifyREST endpoints - The Web SDK:
ours('identify', ...)and the visitor properties argument ofours('track', ...) - Webhook sources with field mappings
- LeadGen, scheduling, and CRM source integrations (GoHighLevel, Calendly, Typeform, and others)
The same semantics apply everywhere so you can reason about a single set of rules no matter where the data enters Ours.
How is this guide?