AxiTrace Custom Events - define your own event names in the Custom events module, send them from the browser, from no-code triggers or from your server, see them on visitor profiles and forward them to nine ad platforms.

Custom Events

Custom events are event names that YOU define for your workspace, such as quote_requested, size_guide_opened or show_hide_filter. They cover the actions your funnel has that the standard events do not. A custom event flows through the whole AxiTrace pipeline: ingestion, storage, the visitor profile timeline and, if you switch it on, forwarding to your connected ad platforms.

Define first, then send

AxiTrace accepts ONLY names that exist in your workspace's registry. A name you have not defined is rejected and shows up in your Errors tab (Event feed) and in the "Recently rejected names" list, where you can define it with one click.

On This Page

  1. Where to find Custom Events
  2. Availability and plan limits
  3. Quick start: a working event in five minutes
  4. The definition form, field by field
  5. Event key rules and reserved names
  6. Kinds: engagement and conversion
  7. Throttle modes
  8. Properties
  9. Sending from the website (JavaScript SDK)
  10. No-code triggers
  11. The selector tester
  12. Sending from your server (HTTP API)
  13. Sending from PHP (PHP SDK)
  14. Forwarding to ad platforms
  15. Checking that it works
  16. Editing, disabling and deleting
  17. How fast changes take effect
  18. Consent and privacy
  19. Limits at a glance
  20. Error messages
  21. Known limitations
  22. Troubleshooting

Where to Find Custom Events

Custom events are configured per workspace, in the Custom events module:

  1. Sign in at axitrace.com/admin and open your workspace.
  2. Click Custom events in the sidebar, in the Data group.
  3. The same Custom Events card also appears in Workspace settings → Data collection.

The card shows:

  • how many custom events are active and how many your plan allows (for example "2 of 5 active");
  • a table of your definitions with their kind, status, the number of events received in the last 7 days;
  • the New custom event button;
  • the Recently rejected names list: names your site sent in the last 7 days that are not defined, each with an Add as custom event button;
  • a link back to this guide.

The full list, including deleted definitions, is at /admin/workspaces/<workspace-id>/custom-events. The card links to it.

You can also let an AI assistant set custom events up for you, for example by asking Claude "Track clicks on the size guide button as a custom event": see Connect Claude, ChatGPT and Cursor. Scripts can do the same through the REST API v1. Both follow the rules on this page and need a permission you grant separately.

Availability and Plan Limits

The plan limit counts ACTIVE definitions. Disabled and deleted definitions do not count, so you can disable one event to make room for another.

Plan Active custom events
FreeNot available
Legacy StarterNot available
Pro5
Business10
CustomUnlimited

Custom event activity is shown as a technical diagnostic. Your plan allowance is measured in visits: multiple custom events in the same session do not create extra billable visits. Review unusually frequent events when tuning triggers and throttles.

Quick Start: a Working Event in Five Minutes

Example: count how often visitors open and close the product filters on a catalog page. The button in the page looks like this:

<button id="toggleFilters" type="button">
    <span id="filterToggleText">Hide Filters</span>
</button>
  1. Check the SDK. The AxiTrace JavaScript SDK must already be installed on the site (see JavaScript SDK). No code change is needed for this example.
  2. Open the module. Workspace, Custom events in the sidebar, then New custom event.
  3. Fill in the details.
    • Event key: show_hide_filter
    • Display name: Show/Hide filters
    • Kind: Engagement (no value)
    • Throttle: Unlimited (every click counts)
  4. Add a trigger. In No-code triggers click Add trigger, choose Click and enter the CSS selector #toggleFilters. Use the button, not the inner span: a click trigger matches the element you name AND everything inside it.
  5. Leave destinations off and click Create custom event.
  6. Test without sending. Open your page with ?axitrace_test=1 added to the URL. The selector tester shows click: #toggleFilters with a match count of 1, and hovering that row outlines the button. Click the button: the "Would fire" log shows custom show_hide_filter (trigger). Nothing is sent from that tab.
  7. Test for real. Open the page in a NEW browser session (a private window is easiest, because the website SDK picks up new definitions when a session starts) and click the button.
  8. Find the event. Open the Visitors tab, open your own visitor profile and look at the timeline: the event appears with an Engagement badge and the display name Show/Hide filters. The 7-day count on the card grows too.

The Definition Form, Field by Field

Event details

Field Required What it does
Event key Yes The technical name your code and triggers send, for example quote_requested. See Event key rules. It cannot be changed after the event is created.
Display name Yes The human name shown on the card and on visitor profiles. Up to 80 characters. You can change it any time.
Description No A note for your team about what the event means.
Kind Yes Engagement (no value) or Conversion (optional value). See Kinds.
Throttle No How often the event may fire. Once per page view, Once per session, Every N seconds or Unlimited. See Throttle modes.
Seconds between events Only for Every N seconds A whole number from 1 to 3600.

Conversion fallback

Two optional fields for conversion events: Value and Currency (a 3-letter ISO 4217 code such as USD or EUR). They are used ONLY when an event arrives without its own value or currency. Typical use: a "demo booked" conversion that is always worth the same amount, so your code or a trigger never has to send a value.

Declared properties

Up to 10 rows. Each row has a Property name (same rules as the event key), a Type (String, Number or Boolean) and a Label. Declared properties are the ONLY properties forwarded to ad platforms. See Properties.

No-code triggers

Up to 5 rows. Each row has Fires on (Click, Hover or Visible), a CSS selector (up to 300 characters, validated when you save), Hover delay (ms) and Visible for (ms). Under each trigger, Send a property can fill one declared property from the matched element. See No-code triggers.

Destinations

One block per ad platform. Every destination is OFF until you switch it on, and a platform that is not connected in Connections shows a Connect button instead of a switch. See Forwarding to ad platforms.

The side panel of the form shows a ready-to-copy code snippet for the event and, when your workspace has a verified domain, a link that opens your site in the selector tester.

Event Key Rules and Reserved Names

An event key must:

  • start with a lowercase letter;
  • contain only lowercase letters a-z, digits 0-9 and underscores _;
  • be 1 to 40 characters long.
^[a-z][a-z0-9_]{0,39}$
Key Valid? Why
quote_requestedYes
video_played_75Yes
QuoteRequestedNoUppercase letters
quote-requestedNoHyphen
quote.requestedNoDot
1st_visit_popupNoStarts with a digit
purchaseNoReserved name
ga_menu_clickNoReserved prefix

Reserved names

You cannot use a key that AxiTrace or GA4 already uses:

  • Reserved prefixes: ga_, google_, firebase_, axi_, vt_ and a leading underscore.
  • AxiTrace standard events and their aliases, for example page_view, product_view, view_item, add_to_cart, begin_checkout, add_payment_info, purchase, transaction, form_submit, lead, subscribe, sign_up, start_trial, search, identify, engagement and error. For these actions use the standard events, which already map to every platform.
  • GA4 reserved and automatically collected names, for example session_start, first_visit, user_engagement, screen_view, login, share, generate_lead, refund, view_cart, view_item_list, select_item, remove_from_cart and add_shipping_info.

The form tells you when a key is reserved, so you do not need to memorise the list.

Keys are permanent

The key cannot be edited after creation, and a key stays taken by its definition even after you delete it: the form refuses it with "belonged to a deleted custom event and cannot be reused". A key held by a disabled event is refused too; enable that event instead. Pick a key you are happy to keep. The display name is the part you can change freely.

Kinds: Engagement and Conversion

Kind Value Use it for Behaviour
engagement Never Interest signals: filter toggles, video plays, size guide opens, tab switches. Never carries a value and never counts as revenue. A value sent by the website SDK is ignored; a value sent to the HTTP API is rejected with a 400. Default throttle: once per page view. Google Ads and LinkedIn cannot receive engagement events.
conversion Optional Business outcomes: quote requested, demo booked, catalog downloaded, call clicked. May carry value, currency and transaction_id, with the conversion fallback applied when they are missing. Goes through the same retry and enrichment steps as the standard conversion events. Default throttle: unlimited.

Throttle Modes

The throttle stops a single visitor from sending the same event too often, for example when a visitor hovers over the same element again and again.

Mode Website SDK HTTP API and PHP SDK
Once per page view
once_per_page_view
At most one event per page view. A single-page-app navigation or a back/forward page restore counts as a new page view. Not enforced: servers have no page views, so every request is accepted.
Once per session
once_per_session
At most one event per AxiTrace session. At most one event per session_id (or user_id when there is no session) within 30 minutes. Requests without either are not throttled.
Every N seconds
every_n_seconds
At least N seconds (1 to 3600) since the last event that was actually SENT. At least N seconds per session_id or user_id.
Unlimited
unlimited
Every call is sent, with a safety cap of 50 events per event key per page view. Every request is accepted, subject to the workspace rate limit.

A throttled call in the browser is dropped silently. A throttled HTTP API request is answered 202 with {"status": "throttled"}.

Properties

Properties are extra details sent with an event, for example the name of the menu a visitor opened. There are two layers:

  1. What you may SEND. Up to 30 properties per event. Names are 1 to 40 characters of letters, digits and underscores. Values must be a string, a number, a boolean or null. Strings are limited to 500 characters. Objects and arrays are not allowed.
  2. What is FORWARDED. Only the properties you declared on the definition (up to 10) are sent to ad platforms, converted to the declared type: a Number property is sent as a number, a Boolean as true or false, a String as text. Undeclared properties are stored with the event but never leave AxiTrace.

The conversion never guesses. A Number property receives the number when the value reads as one, including the numeric text "34" a trigger extracts from an attribute; anything else is forwarded as 0, so a Number property holding a price range such as "2000-5000" reaches every platform as zero. Use a String property for a value that is not a plain number, and check the type when a platform reports zeros.

Some names are reserved for the event itself and are never treated as properties: value, currency, transaction_id, trigger_id, source, url and referrer. Pass value, currency and transaction id through the dedicated options described below.

No personal data in properties

Do not put e-mail addresses, phone numbers, names or other personal data into properties. Properties are forwarded to ad platforms as plain values. Identity is matched through AxiTrace's own visitor identification, not through properties.

Sending From the Website (JavaScript SDK)

With the JavaScript SDK installed, one call sends a custom event. The signature is:

Axitrace._instance.track(eventKey, properties, options);
Argument Type Description
eventKey string The event key exactly as defined, for example 'quote_requested'.
properties object, optional Flat key/value pairs. See Properties.
options.value number, optional Conversion events only. Zero or more.
options.currency string, optional Conversion events only. ISO 4217 code, uppercased automatically.
options.transaction_id string, optional Conversion events only. Your own order or lead id, up to 100 characters.
options.products array, optional Products the event is about, in the transaction line shape, shown when the event counts as a lead (see Custom events as leads). Not a property: it does not count toward the 30 properties.

Engagement example

document.querySelector('#size-guide').addEventListener('click', function () {
    Axitrace._instance.track('size_guide_opened', {
        product_sku: 'CHAIR-042',
        placement: 'product_page'
    });
});

Conversion example

Axitrace._instance.track('quote_requested', { menu_name: 'Salad' }, {
    value: 149.50,
    currency: 'PLN',
    transaction_id: 'quote-1001'
});

What the SDK does with the call

  • Defined and active key: applies the throttle, cleans the properties, attaches the conversion fields, fires the browser pixel bridge (see Meta and TikTok) and sends the event.
  • Invalid property: a property with an invalid name, a non-scalar value or beyond the 30th is dropped with a console warning; the rest of the event is still sent. Strings longer than 500 characters are cut to 500.
  • Unknown key: the SDK logs "<key>" is not a registered custom event in the console and sends the name ONCE per session, so it appears in your Errors tab and in "Recently rejected names" without flooding them.
  • Key of a standard event: names such as add_to_cart are routed to the standard event, not to a custom event.
  • Before consent: see Consent and privacy.
Why _instance

Tracking calls go through Axitrace._instance, the same object every other event page in these docs uses. Call it after Axitrace.init() has run. Since SDK 0.23.0 the global also accepts the shorthand Axitrace.track(...) (and Axitrace.trackCustom(...)), which forwards to Axitrace._instance and returns its result; a shorthand call made before init() is kept and replayed once it runs.

No-Code Triggers

A trigger fires the event when a visitor interacts with an element that matches a CSS selector. No code on your site is needed beyond the SDK itself. A definition can have up to 5 triggers, so one event can be fired by several buttons.

Fires on Behaviour Timing field
Click Fires when the visitor clicks the matching element or anything inside it. The click itself is never blocked or changed, so links and buttons keep working. None
Hover Fires when the pointer stays on the element for the hover delay. Leaving earlier cancels it. Not available on touch-only devices such as phones, where hover does not exist. Hover delay (ms): 100 to 5000, default 700
Visible Fires when at least half of the element has been on screen for the dwell time in total (it may scroll in and out). Fires at most once per element per page view. Visible for (ms): 100 to 60000, default 1000

Choosing a selector

  • Prefer an id: #toggleFilters.
  • Next best is a dedicated data attribute: button[data-track="quote"]. Adding one to your template is the most robust option, because designers rarely change it.
  • Class names work, but break when styling changes: .product-card .btn-quote.
  • A selector may match several elements. For example .faq-item summary fires for every FAQ question.
  • Elements added to the page later, such as items loaded by infinite scroll or a popup, are picked up automatically.

What triggers never do

  • Triggers never read the text of an element and never read form field values, so they cannot capture what a visitor types.
  • Triggers are not loaded at all while your workspace has no trigger defined, so they add nothing to your page weight.

The first one is a deliberate boundary, not a missing feature. A trigger is configured in a panel by whoever runs your marketing, and a selector such as .checkout input matches the fields a visitor types into. If triggers could read text and input values, one selector would be enough to push an e-mail address, a phone number or a full name into your ad platforms, with no code review and no way to take it back. Everything else in AxiTrace works to keep personal data out of forwarding, so triggers do not get to be the way around it. Values that a trigger may read are the ones your own template put there on purpose, as attributes.

Sending a property from a trigger

Under each trigger row, Send a property fills ONE declared property from the element the trigger matched. Declare the property first under Declared properties.

Be aware of what this costs. A trigger fires on its own against the page as it already is, but a property has to come from somewhere, and the only places a trigger looks are the link address and data- attributes. Unless those attributes are already in your markup, someone has to add them to your theme: one attribute per element, no script and no tracking code, but still an edit to the template. A trigger with no property needs nothing at all.

Taken from Data attribute Reads
A data attribute of the element Required, without the data- prefix The attribute of the matched element itself.
The link address (href) Not used The href of the matched element.
A data attribute of a parent Required, without the data- prefix The attribute of the nearest element, the match itself or one of its parents, that carries it. Useful when the click lands on a button inside a product card.

Example: one trigger for every "Request a quote" button in a menu list.

<li data-menu-name="Salad">
    <button class="btn-quote">Request a quote</button>
</li>
  • Declared property: menu_name, type String.
  • Trigger: Click, selector .btn-quote.
  • Send a property: A data attribute of a parent, data attribute menu-name, into declared property menu_name.

A click on the button sends menu_name: "Salad". When the attribute is missing or empty, the event is still sent, without that property. Values longer than 500 characters are cut. To send more than one property, call track() from your code.

Content Security Policy

The trigger engine (axitrack-triggers.js) and the selector tester (axitrack-tester.js) are loaded on demand from the same tracking domain as the SDK. If your site uses a Content Security Policy that already allows the SDK, nothing else needs to be added.

Throttle and triggers

The throttle applies to trigger fires exactly like it applies to code calls. A Hover or Visible trigger on an element visitors see often should normally use Once per page view or Every N seconds.

The Selector Tester

Add ?axitrace_test=1 to any page of your own site, for example https://www.example.com/catalog?axitrace_test=1. The definition form links to your verified domain with the flag already set.

In that browser tab:

  • Nothing is sent to AxiTrace. The tab runs in dry-run mode, so testing never pollutes your data.
  • A panel in the top-right corner lists every trigger as type: selector (event: key) with the number of elements it matches on this page. 0 means the selector finds nothing here; invalid means the selector has a syntax error.
  • Hovering a row outlines the matching elements in orange.
  • Your triggers are armed. The Would fire log shows every event that would have been sent, with its properties, instead of sending it: trigger fires are marked (trigger), and calls from your own code appear too.
  • Clicking any element on the page proposes a selector for it: its id first, then a data attribute, then a short class path. Copy it into the trigger row.

The tester uses the definitions your browser session already loaded. After you save a change, open the test URL in a new private window to see it.

Sending From Your Server (HTTP API)

POST /v1/custom-events

Use the HTTP API when the action happens on your server: a quote stored in your CRM, a subscription renewed by a webhook, a phone call logged by your call-tracking tool. Send requests to https://stat.axitrace.com or to your own tracking subdomain.

Authentication

Use HTTP Basic authentication with your SECRET key as the username and an empty password, exactly like the other server endpoints. See Authentication. Never put the secret key in browser code.

Request body

Field Type Required Description
event_namestringYesThe event key.
event_idstringYesYour unique id for this occurrence, for example a UUID. Used for deduplication.
propertiesobjectNoFlat key/value pairs. See Properties.
valuenumberNoConversion events only. Zero or more.
currencystringNoThree uppercase letters (ISO 4217), for example EUR.
transaction_idstringNoUp to 100 characters.
productsarrayNoProducts the event is about, in the transaction line shape. An invalid line is dropped and the event is still stored. See Custom events as leads.
client_idstringRecommendedThe value of the visitor's vt_vid cookie. Links the event to the visitor profile and to their ad clicks.
session_idstringRecommendedThe value of the vt_sid cookie. Needed for session-based throttling.
user_idstringNoYour own customer id. Takes precedence over client_id as the visitor identity.
ipstringRecommendedThe visitor's IP address. Without it, the IP of your server is used, which weakens ad platform matching.
user_agentstringRecommendedThe visitor's browser user agent. Without it, the user agent of your HTTP client is used.

Example

curl -X POST https://stat.axitrace.com/v1/custom-events \
  -u "sk_live_YOUR_SECRET_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
    "event_name": "quote_requested",
    "event_id": "5f0c7a52-8a4e-4a53-9a3e-0f1d2c3b4a51",
    "properties": { "menu_name": "Salad", "guests": 12 },
    "value": 149.50,
    "currency": "PLN",
    "transaction_id": "quote-1001",
    "client_id": "value-of-the-vt_vid-cookie",
    "session_id": "value-of-the-vt_sid-cookie",
    "ip": "203.0.113.24",
    "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ..."
  }'

Responses

Status Body Meaning
200{"status": "queued"}Accepted and queued for processing.
202{"status": "duplicate"}An event with the same event_id was received in the last 5 minutes. Nothing new was queued.
202{"status": "throttled"}The definition's throttle suppressed this event.
400plain text errorInvalid request or unknown event. The message is also written to your Errors tab (Event feed). See Error messages.
401plain text errorMissing or wrong secret key.
429custom event budget exceededMore than 600 custom events in one minute for this workspace. Retry in the next minute.
500plain text errorTemporary failure on our side. Retry with the SAME event_id.
Safe retries

/v1/custom-events is the only endpoint with event_id deduplication, so retrying after a timeout or a 500 never double counts. An event_id is claimed only by a request that passed validation: a request answered 400 claims nothing, so you can fix it and resend it with the same id. A 500 releases the id as well.

Sending From PHP (PHP SDK)

The AxiTrace PHP SDK provides the CustomEvent model from version 1.7.0. It sends to /v1/custom-events and generates the event_id for you when you do not pass one.

use AxiTrace\Model\Event\CustomEvent;

$event = new CustomEvent(
    'quote_requested',          // event key
    ['menu_name' => 'Salad'],   // properties
    149.50,                     // value (conversion events only, or null)
    'PLN',                      // currency, or null
    'quote-1001',               // transaction id, or null
    $quote->getUuid()           // event id, or null to generate one
);

// Link the event to the visitor who made the request.
$event->setClientId($_COOKIE['vt_vid'] ?? null);
$event->setSessionId($_COOKIE['vt_sid'] ?? '');

$axiTrace->events()->send($event);

Pass a stable event id, such as the id of the record you just stored, if the same code path can run twice. Then a repeated call within 5 minutes is answered as a duplicate instead of counting twice.

Custom events as leads

A registered custom event can count as a lead: switch it on in Settings > Leads and its occurrences appear in Leads. Choosing it changes only what Leads shows, never how the event is tracked or forwarded. Any custom event can carry the products it is about as a root products array (in the JavaScript SDK, options.products), anchored on the event's currency. Products are optional; an invalid line is dropped and the event is still stored. From PHP SDK 1.12.0, CustomEvent has addProduct() and setProducts():

$event = (new CustomEvent('quote_requested', ['menu_name' => 'Salad'], 149.50, 'PLN', null, $quote->getUuid()))
    ->addProduct(['sku' => 'MENU-SALAD', 'name' => 'Salad menu', 'finalUnitPrice' => 14.95, 'quantity' => 10]);

$axiTrace->events()->send($event);

The full rules for lead products are on the Leads page.

Forwarding to Ad Platforms

General rules for every platform:

  • Forwarding is configured per definition, in the Destinations section of the form. The per-event checkboxes of a connection in Connections do not apply to custom events.
  • A destination can only be switched on when the platform is connected in Connections.
  • Only declared properties are forwarded, converted to their declared type.
  • For a conversion event, the conversion fallback value and currency fill in what the event does not carry.
  • Names of purchase-type standard events (such as Meta Purchase or GA4 purchase) cannot be used for custom events, so a custom event can never inflate your revenue reporting.
  • An engagement event that carries no identity signal at all (no cookie, no click id, no user id) is not forwarded, because the platform could not match it to a person. It is still stored and visible on the profile.
  • Every forwarding attempt, successful or not, appears in the connection's integration log.
Platform Settings in the destination block What you must do on the platform side
Meta (Facebook) Conversions API Send as: Custom event name (1 to 50 letters, digits, spaces and underscores; defaults to the key) or Standard event: Lead, Contact, Schedule, SubmitApplication, ViewContent, Search, CustomizeProduct, FindLocation, Donate, CompleteRegistration, StartTrial, Subscribe. Nothing for a standard event. A custom name appears in Events Manager after the first event; create a custom conversion from it if you want to optimise campaigns for it. If the Meta pixel runs on your site, the SDK also fires it with the same event id, so Meta counts the pair once.
TikTok Events API Send as: Custom event name (starts with a letter, 1 to 50 letters, digits, hyphens and underscores) or Standard event: Contact, SubmitForm, ViewContent, Search, ClickButton, Download, CompleteRegistration, Subscribe. Optional Description property: one declared string property sent as the TikTok description. Nothing for a standard event. If the TikTok pixel runs on your site, the SDK also fires it with the same event id for deduplication.
Google Analytics 4 GA4 event name: starts with a letter, up to 40 letters, digits and underscores; defaults to the key. GA4 reserved names are refused. GA4 does not show event parameters in reports until you register them. In GA4 go to Admin, Custom definitions, Create custom dimension, scope Event, one per declared property, plus value and currency for a conversion event. To count the event as a key event, mark it in Admin, Events. GA4 sends value and currency together or not at all.
Google Ads Conversion events only. Conversion action ID: the numeric id of an existing conversion action in the connected account. Create the conversion action in Google Ads first (type: Import, from clicks). AxiTrace never creates one for you.
Microsoft Advertising Action (defaults to the key), optional Category and Label, each up to 100 characters. Create an Event goal in Microsoft Advertising whose Action equals the Action you entered. AxiTrace never creates the goal.
LinkedIn Conversions API Conversion events only. Conversion rule URN in the form urn:lla:llaPartnerConversion:12345. Create the conversion rule in Campaign Manager with the Conversions API method, then copy its URN. AxiTrace never creates a rule.
Pinterest Conversions API Send as: Custom event name (1 to 100 letters, digits, hyphens and underscores) or Standard event: lead, search, view_category, signup. At most 15 custom events per advertiser, and a custom event stays untracked until you map it in Ads Manager.
Reddit Conversions API Send as: Custom event name (1 to 64 characters) or Standard event: Lead, SignUp, ViewContent, Search. Events Manager shows only the 20 most recently used custom names.
OpenAI Ads OpenAI event name: lowercase letters, digits, hyphens and underscores, 2 to 64 characters, starting and ending with a letter or digit; defaults to the key. Nothing beyond the connection.

Checking That It Works

  1. Selector tester: every trigger shows a match count above 0 on the pages where it should fire, and interacting with the element adds a line to the "Would fire" log. See The selector tester.
  2. Browser console (code calls): no [AxiTrace] warning about an unregistered event or a dropped property. In the Network tab, the request to /track carries "event": "custom" and your key in event_name.
  3. Visitor profile: open the Visitors tab and then the visitor. The timeline shows the event with an Engagement or Conversion badge and the display name. Events usually appear within a few seconds; a conversion can take a little longer.
  4. The Custom Events card: the 7-day count of the definition grows.
  5. Event feed → Errors: rejected events are listed with the reason. See Error messages.
  6. Ad platform: the connection's integration log shows each forwarding attempt; the platform's own test or events screen shows the event after its usual delay.

Editing, Disabling and Deleting

Action Where Effect
Edit The full list page, Edit Everything except the event key can be changed. Events already stored keep the values they were received with.
Disable The card or the list page New events with this key are rejected. The definition, its history and its settings are kept, and it no longer counts toward your plan limit.
Enable The card or the list page Accepts the key again. Only possible while you are under your plan limit.
Delete The card or the list page, after a confirmation Works like Disable, and the definition disappears from the card. It stays visible on the full list page, its past events stay on visitor profiles with a deleted badge, and its key cannot be reused.

How Fast Changes Take Effect

  • Server side (HTTP API, PHP SDK and the ingestion of browser events): a NEW definition is accepted within seconds. A disabled or deleted definition stops being accepted within 10 seconds.
  • Website SDK: trigger, throttle and pixel bridge changes reach NEW visitor sessions within 5 minutes. A visitor whose session already loaded the configuration keeps it until their next session.

If saving shows the warning "Saved. The ingestion registry could not be updated", your change is stored and the registry repairs itself automatically within 20 minutes. You do not need to save again.

Nothing is dropped while the registry is warming up

If the ingestion's copy of your registry is temporarily unavailable, events with a valid key format are ACCEPTED and checked afterwards against your saved definitions: defined keys are processed normally, undefined keys land in your Errors tab with the unknown custom event: prefix. The website SDK behaves the same way while its configuration is missing: calls are sent without throttling and the console shows one custom event config unavailable warning per session.

  • Custom events follow the same consent rules as every other event of the website SDK (see Cookie consent). While the SDK waits for consent, calls and trigger fires are held in a short in-memory buffer and sent with their original time once consent is granted. If consent is never granted, nothing is sent.
  • When the SDK is disabled for a visitor, for example by Do Not Track where your workspace respects it, custom events are not sent.
  • Triggers never read element text or form field values.
  • Only declared properties leave AxiTrace, and only to destinations you switched on.
  • For server calls you are responsible for sending events only for visitors who consented, like for any other server event.

Limits at a Glance

Limit Value
Active definitions per workspacePro 5, Business 10, Custom unlimited
Event key1 to 40 characters, [a-z][a-z0-9_]
Display name80 characters
Declared properties per definition10
Properties sent per event30
Property name1 to 40 characters of letters, digits and underscores
Property string value500 characters
Triggers per definition5
CSS selector300 characters
Hover delay100 to 5000 ms
Visible dwell time100 to 60000 ms
Every N seconds1 to 3600
Unlimited throttle in the browser50 events per key per page view
Transaction id100 characters
Rate limit600 custom events per minute per workspace
Deduplication window (HTTP API)5 minutes per event_id

Error Messages

These messages appear in HTTP API responses and in Event feed → Errors.

Message Cause Fix
unknown custom event: <key> The key is not defined, or it is disabled or deleted. Define or enable it. Check the spelling: keys are case sensitive and lowercase.
unsupported event: <name> The name does not follow the key format, for example it contains uppercase letters, a hyphen or a dot. Use a key that matches the rules.
event_name and event_id are required HTTP API request without one of them. Send both.
custom event <key>: properties: expected at most 30 keys More than 30 properties. Send fewer properties.
custom event <key>: properties.<name>: expected 1 to 40 characters of [a-zA-Z0-9_] Invalid property name. Rename the property.
custom event <key>: properties.<name>: expected a scalar value An object or array was sent as a property value. Send a string, number or boolean.
custom event <key>: properties.<name>: expected at most 500 characters String value too long. Shorten it.
custom event <key>: value: an engagement event cannot carry a value A value was sent for an engagement definition. Drop the value, or make the definition a conversion.
custom event <key>: value: expected at least 0 Negative value. Send zero or more.
custom event <key>: currency: expected an ISO 4217 code Currency is not three uppercase letters. Send for example EUR, not eur or €.
custom event <key>: transaction_id: expected at most 100 characters Transaction id too long. Shorten it.
custom event budget exceeded (600/min) More than 600 custom events in one minute for the workspace. Check for a loop or a trigger without a throttle.

Known Limitations

Shopify storefronts

No-code triggers and Axitrace._instance.track() are NOT available inside the Shopify Web Pixel. It runs in a sandbox without access to your page, so a trigger engine cannot run there. The HTTP API and the PHP SDK work, and Shopify order events keep flowing as before.

  • The visitor profile timeline shows the most recent 100 events across ALL event types; custom events share that window.
  • There are no per-event trend charts or dashboard widgets for custom events yet. Use the 7-day count on the card and the visitor profiles.
  • A trigger configured in the panel fills at most one property. Send more from your code.

Troubleshooting

The event does not appear on the profile

  1. Look in Event feed → Errors for unknown custom event or a validation message.
  2. Check that the definition is Active on the card.
  3. For a trigger or a throttle change, start a NEW browser session: existing sessions keep the configuration they loaded, for up to the session length.
  4. Check the throttle: with Once per page view a second click on the same page is not sent.
  5. Check consent: while the visitor has not consented, nothing is sent.
  6. Make sure you are looking at the right profile: in a private window you are a new visitor.

The tester shows 0 matches

  • The element may not exist on this page, or it is rendered later (open the menu or scroll first, then hover the row again).
  • Click the element with the tester open to get a proposed selector and compare it with yours.

The tester shows matches but nothing arrives

  • The tester tab never sends anything, by design. Test in a normal tab without ?axitrace_test=1, in a new session.

The console says the event is not registered

  • The key in your code differs from the defined key, or the definition was created after this session started. Open a new session.

The event is on the profile but not on the ad platform

  • Check that the destination is switched on in the definition, not only connected.
  • Check the connection's integration log for the platform's answer.
  • For Microsoft Advertising, LinkedIn and Google Ads, the goal, rule or conversion action must exist on the platform side.
  • For GA4, register the custom dimensions; parameters are invisible in reports until you do.
  • An engagement event without any identity signal is not forwarded, see Forwarding.

An HTTP API retry is answered "duplicate"

  • That is the deduplication working: an event with this event_id was accepted in the last 5 minutes. Use a new id only for a genuinely new occurrence.