Documentation

Documentation

Web-SDK automatic events

All events go to the track service and share a common structure. Below we describe only the data field of each event and the conditions under which it is generated.

EventSourceEnabled by
sessionsession start or restartalways
pagerstat4('page')call
page_loadedwindow.loadalways
page_unloadbeforeunloadbrowserEvents.unloadHandlers
page_visibilityvisibilitychangebrowserEvents.visibilityHandlers
activityDOM event counter, once per flushIntervaltrackActivity
scrollscrolling stoppedtrackActivity.scrollEvents
link_clickclick on a linktrackClicks
element_clickclick on any elementtrackClicks.allClicks
form_submitform submissiontrackForms
field_focus, field_blur, field_change, field_invalidfield eventstrackForms
user_paramssynchronization with GA4 and Yandex Metricaalways
rec_start, rec_batchsession recordingtrackRecord or rstat4('record')

Session#

Sent instead of the event that triggered the session start; that event is sent right after. data is empty, all the information is in the sess block. See more in the Sessions section.

{
  "name": "session",
  "data": {},
  "sess": {
    "pageNum": 0, "eventNum": 0, "num": 1,
    "type": "organic", "engine": "google", "refhost": "google.com",
    "marks": {}, "hasMarks": false, "start": 1757960000000
  }
}

Page view#

The library does not send page on its own; the site calls it. Everything passed into the call lands in data. A perf block with load timings is added to the event.

{
  "name": "page",
  "data": { "type": "category", "id": "2342344", "name": "Товары для дома" },
  "perf": { "cs": 0, "ce": 0, "scs": -1, "rqs": 211, "rss": 1549, "rse": 1560, "dl": 1581, "di": 1812, "dc": -1 }
}

Page loaded#

Sent on window.load, data is empty, and the perf block is already fully populated.

{ "name": "page_loaded", "data": {}, "perf": { "...": "..." } }

Page unload#

Sent on beforeunload when navigating to another page or closing the tab, data is empty. Delivered via sendBeacon, so the event makes it out in time.

{ "name": "page_unload", "data": {} }

Tab visibility#

Sent on visibilitychange: the user switched tabs, minimized the browser, or came back.

{
  "name": "page_visibility",
  "data": {
    "hidden": 1,          // 1 — tab is hidden, 0 — visible
    "state": "hidden",    // document.visibilityState
    "dur": 48213          // how many ms the previous state lasted
  }
}

Activity#

The DOM event counter accumulates statistics and, once every flushInterval seconds (5 by default), sends them to the server. If there was no activity during the period, the event is not sent, but the iteration number keeps growing. With zeroEvents: true, empty periods are sent as well.

{
  "name": "activity",
  "data": {
    "interval": 5,     // period, seconds
    "iteration": 65,   // period number since the page loaded
    "active": 4,       // number of the period with activity
    "mousemove": 62,
    "mousedown": 2,
    "mouseup": 2,
    "click": 2,
    "wheel": 23,
    "scroll": 22,
    "keydown": 5,
    "touchstart": 1
  }
}

The following events are counted: touchmove, touchstart, touchleave, touchenter, touchend, touchcancel, click, mouseup, mousedown, mousemove, mousewheel, wheel, scroll, keypress, keydown, keyup, resize, focus, blur. Only those that occurred during the period land in data. A description of the events is available at developer.mozilla.org.

Scrolling#

Sent when scrolling has stopped. data is empty, the position is in the scroll block, which is also added to all other user events.

{ "name": "scroll", "data": {}, "scroll": { "dh": 1148, "ch": 326, "to": 479, "cs": 100, "ms": 100 } }

The nearest <a> is searched for upward from the element that received the click. outbound means the link points to another host. Elements with the trackClicks.ignoreClass class (rst-ignore by default) are not tracked.

{
  "name": "link_click",
  "data": {
    "target": {
      "tag": "span",              // tag of the deepest element under the cursor
      "type": "",
      "name": "",
      "ph": "",                   // placeholder
      "cls": "menu-item",         // class
      "id": "",
      "href": "",
      "text": "Меню"
    },
    "href": "https://www.example.com/catalog/#menu",
    "text": "Текст ссылки",
    "outbound": false
  }
}

Click on any element#

Only with trackClicks: { allClicks: true }. Clicks on links are still sent as link_click; element_click is not sent for them.

{
  "name": "element_click",
  "data": {
    "target": {
      "tag": "input",
      "type": "text",
      "name": "city",
      "ph": "Введите город прибытия",
      "cls": "SearchWidget-input -to",
      "id": "",
      "href": "",
      "text": ""
    }
  }
}

Form fields#

Four events with the same set of parameters:

  • field_focus — the caret was placed in the field;
  • field_change — the field value changed;
  • field_blur — the caret left the field;
  • field_invalid — the field failed browser validation on form submission.

Parameters with the e prefix describe the field, those with the f prefix describe the form it belongs to.

{
  "name": "field_change",
  "data": {
    "event": "change",            // DOM event
    "etag": "input",              // element tag
    "etype": "text",              // type attribute
    "ename": "delivery_address",  // name attribute
    "eph": "",                    // placeholder
    "ecl": "form-field",          // class
    "eid": "",                    // id
    "evalue": "",                 // value, see below
    "fmthd": "post",              // form method
    "fact": "/checkout/purchase", // form action
    "fname": "order-form",        // form name
    "fcls": "",                   // form class
    "fid": "order-form"           // form id
  }
}

If the field is not inside a form, "ferr": "Form element absent" is sent instead of f*.

Field values#

By default, values are not sent, and evalue is empty. The options are:

  • trackForms: { trackValues: true } — the value is sent as plain text in evalue;
  • trackForms: { encryptionKey: '...' } — the value is encrypted in the browser with a public RSA key (WebCrypto RSA-OAEP) and sent in evalue with eenc: 1. If encryption is unavailable, the value is dropped and eenc: 0 is sent.

Field events are among the most useful for diagnosing problems in forms: the field_focus → field_change → field_invalid chain shows where the visitor got stuck.

Form submission#

{
  "name": "form_submit",
  "data": {
    "event": "submit",
    "fmthd": "post",
    "fact": "/cart",
    "fname": "cart",
    "fcls": "cart-submit",
    "fid": "cart-submit"
  }
}

Identifier synchronization#

If GA4 or Yandex Metrica is present on the page, the SDK gets their client id and sends the internal user_params event. The identifiers are saved in storage and are then included in the user block of every message as ga4ClientId and ymId.

{ "name": "user_params", "data": { "ga4ClientId": "2039255293.1537236640", "ymId": "1537242943246737376" } }

Session recording#

When recording starts, rec_start is sent, then the rrweb buffer is sent in rec_batch batches.

{ "name": "rec_start", "data": { "packed": 1, "masked": 1 } }
{ "name": "rec_batch", "data": { "seq": 3, "part": 1, "of": 2, "p": 1, "d": "[{\"type\":3,..." } }

d is a fragment of a JSON array of packed rrweb events. The array is serialized as a whole and cut into parts of maxBatchBytes characters each. The server stitches d together by the (uid, lib.st, seq) key in part order (of is the number of parts), parses the JSON, and unpacks each event (p: 1 — fflate, p: 0 — raw JSON).

Session recording and identify do not create events with scroll; all other user events receive a scroll block with the current page position.