Skip to content

Types reference

Field names in JSON payloads use snake_case. The snippets below match the TypeScript types in @usesophi/sophi-web-object.

SophiConfig and SophiSession

Set only the fields described in Configuration on window.sophi_object.config. The published SophiConfig type in the npm package may include additional properties that the SDK fills in; you should not set those yourself.

interface SophiSession {
  accessToken: string;
  clientId: string;
}

PageType and PageObject

type PageType =
  | 'Home'
  | 'Category'
  | 'Product'
  | 'Basket'
  | 'Checkout'
  | 'Confirmation'
  | 'Search'
  | 'Account'
  | 'Custom';

interface PageObject {
  type: PageType;
  url: string;
  title?: string;
  language?: string;
  category_id?: string;
  search_query?: string;
  custom?: Record<string, unknown>;
}

UserObject and sub-objects

user events require consent with gdpr_optin defined. When gdpr_optin !== true, the SDK strips identity and profile from the outgoing envelope (non-PII behavior, segmentation, custom remain). Do not rely on this as your only privacy control.

interface ConsentObject {
  gdpr_optin: boolean;
  version: string;
  timestamp: number; // epoch seconds
}

interface IdentityObject {
  uuid?: string;
  email?: string;
  phone_number?: string; // E.164, e.g. "+447700900000"
}

interface ProfileObject {
  name?: string;
  surname?: string;
  gender?: 'F' | 'M' | 'O' | 'U';
  birthday?: string; // YYYY-MM-DD
  language?: string; // BCP-47
}

interface BehaviorObject {
  returning?: boolean;
  has_transacted?: boolean;
  transaction_count?: number;
  last_transaction_at?: number; // epoch seconds
}

interface SegmentationObject {
  static_segment_ids?: (string | number)[];
}

interface UserObject {
  consent: ConsentObject;
  identity?: IdentityObject;
  profile?: ProfileObject;
  behavior?: BehaviorObject;
  segmentation?: SegmentationObject;
  custom?: Record<string, unknown>;
}

ProductObject

interface ProductObject {
  id: string;
  variant_id?: string;
  sku?: string;
  group_code?: string;
  category_ids: string[];
  name: string;
  url: string;
  product_image_url: string;
  taxonomy: string[];
  currency: string;
  unit_price: number;
  unit_sale_price: number;
  omnibus_price?: number;
  in_stock: 0 | 1;
  stock?: number;
  brand?: string;
  color?: string;
  size?: string;
  gender?: string;
  locale?: string;
  description?: string;
  tags?: string[];
  custom?: Record<string, unknown>;
}

BasketObject and BasketLineItem

Line items are flat rows (not nested full product objects).

interface BasketLineItem {
  product_id: string;
  variant_id?: string;
  sku?: string;
  quantity: number;
  currency: string;
  unit_price: number;
  unit_sale_price: number;
  line_total: number;
}

interface BasketObject {
  basket_id?: string;
  currency: string;
  total: number;
  subtotal?: number;
  tax?: number;
  shipping_cost?: number;
  discount_total?: number;
  coupon_code?: string;
  line_items: BasketLineItem[];
}

ListingObject and ListingItemObject

At least one of category_id, slug, or search_query must be present on ListingObject.

interface ListingItemObject {
  product_id: string;
  variant_id?: string;
  position: number;
  name: string;
  url: string;
  product_image_url: string;
  currency: string;
  unit_price: number;
  unit_sale_price: number;
  in_stock?: 0 | 1;
  brand?: string;
}

interface ListingObject {
  category_id?: string;
  slug?: string;
  search_query?: string;
  name?: string;
  taxonomy?: string[];
  total_results?: number;
  page_number?: number;
  page_size?: number;
  sort?: string;
  applied_filters?: Record<string, unknown>;
  items?: ListingItemObject[];
}

TransactionObject and TransactionLineItemObject

interface TransactionLineItemObject {
  product_id: string;
  variant_id?: string;
  sku?: string;
  quantity: number;
  currency: string;
  unit_price: number;
  unit_sale_price: number;
  line_total: number;
}

interface TransactionObject {
  order_id: string;
  currency: string;
  total: number;
  subtotal?: number;
  tax?: number;
  shipping_cost?: number;
  discount_total?: number;
  coupon_code?: string;
  payment_method?: string;
  line_items: TransactionLineItemObject[];
}

EventEnvelope

Payload sent to Sophi (HTTPS, JSON) for each tracked event:

type ExternalEventType =
  | 'page_view'
  | 'identify'
  | 'product_view'
  | 'listing_view'
  | 'add_to_cart'
  | 'remove_from_cart'
  | 'basket_view'
  | 'checkout_started'
  | 'purchase'
  | 'custom';

interface EventEnvelope {
  event_type: ExternalEventType;
  client_timestamp: number; // epoch seconds
  sdk_version: string;
  page: PageObject;
  user?: UserObject;
  product?: ProductObject;
  basket?: BasketObject;
  listing?: ListingObject;
  transaction?: TransactionObject;
  custom?: Record<string, unknown>;
}

Conventions (summary)

Topic Rule
Timestamps Unix epoch seconds (integers) on consent and envelope client_timestamp
Currency ISO 4217 (TRY, EUR, …)
Language BCP-47 (tr-TR, en-US)
in_stock Integer 0 or 1
unit_sale_price Always send; equals unit_price when there is no discount
line_total Caller-computed: typically unit_sale_price * quantity
Unknown fields Prefer omitting keys over sending placeholder null / 0 / ""

Full validation rules: Validation.