CLI command
landing
Landing block tests that need no deploy: a landing reads, for each visitor, the content of the variant they are shown, and each variant's conversions after it are read back.
Invocation#
echo-cli landing list --app <web source>
echo-cli landing create --app <web source> --block <block-key> --file <variants.json> --by <name>
echo-cli landing stop --test <test-id>
echo-cli landing exposures --test <test-id>
echo-cli landing outcomes --test <test-id> --event <conversion event>
echo-cli landing widget --app <web source>Inputs and output#
list writes the web source's tests, newest first: id, app_id, block_key, variants (key and content), status (running or stopped), created_by, created_at and stopped_at. create and stop write the test. exposures writes exposures (test_id, subject_id, variant_key, first_shown_at) and by_variant, how many subjects each variant was shown to. outcomes writes test_id, app_id, block_key, conversion_event and variants: per variant, exposed (subjects shown), converted (of them, those who then sent the event) and rate (converted over exposed, null for a variant shown to no one). widget writes script_url, snippet (the script tag with data-app and data-subject, and an element carrying data-echo-block for each block) and script_bytes, the size of the script Echo Web serves now.
State effect#
Every verb calls Echo Web's authenticated /api/analytics/landing with ECHO_INTERNAL_BEARER at ECHO_WEB_BASE_URL, except widget, which reads the public /api/public/landing/widget without a bearer; the Landing block tests section of the tracking screen and of Echo Desktop's GEO screen call the same operation (both print the widget HTML), and echo-mcp reads tests, exposures and outcomes as echo_landing_tests and the widget as echo_landing_widget. --file holds the block's variants as a JSON list of { key, content }, at least two with distinct keys. At most one test runs per block. A landing reads GET /api/public/landing?app_id=<source>&block_key=<block>&subject=<id> from a browser on an origin CORS_ALLOWED_ORIGINS declares, with the anonymous or user id its analytics send: the first time a subject is shown a block of a running test they are given one variant, evenly by their subject id, stored in landing_exposures as their exposure; every later read answers the same variant. The answer is { rule_id: null, test_id, variant, content }, or nulls when the block runs no test or its test was stopped, so the landing shows its own content; a matching dynamic rule answers first, as landing-rules describes. The widget script does this from the page for every element carrying data-echo-block, passing the page's own query parameters so a rule can match, and writes the content as text; a block answered with no variant keeps the landing's content, and a missing attribute or a refusal keeps it too and is written to the console with its reason. outcomes counts, for each exposure, whether the test's web source stored the --event event under the same anonymous or user id at or after the moment the variant was first shown; it is read from the stored exposures and web events on each call and stores nothing.
Refusals#
- A wrong invocation is refused before anything is sent: "landing takes <every verb's usage, separated by semicolons>; got <word>", "landing <verb> does not take <flag>; it takes …", "<flag> needs a value", "landing <verb> needs <flag>" and "--file <path> is not a readable JSON file: <cause>".
- outcomes is refused with "conversion_event is required: the event a subject sends when the landing did its job, such as a signup" and not found with "no landing test has id <id>; echo-cli landing list --app <source> shows them".
- Echo Web answers a bad request with "app_id is required: …", "block_key is required: …", "variants is required: the block's variants, as [{ key, content }]", "variants[<n>].key is required: the variant's name", "variants[<n>].content is required: what the landing shows for the variant", "variants must hold at least two: a test compares a variant with another; got <n>" or "variants must each have a distinct key"; not found with "no running landing test has id <id>; echo-cli landing list shows them"; and a conflict with "block <block> of <source> already runs test <id>; echo-cli landing stop --test <id> stops it". The public endpoint answers "<name> is required: …" for a missing app_id, block_key or subject. The command prints Echo Web's sentence and exits 1.