Echo/Docs

CLI command

competitors

Competitor page history: capture a public page over time, see what each new reading added and removed, every move in the prices it shows, and track a product's competitor pages so they are captured on each page's own schedule and a price move reaches someone.

Invocation#

Shell
echo-cli competitors capture --url <https-url> --by <name>
echo-cli competitors captures --url <https-url>
echo-cli competitors pricing --url <https-url>
echo-cli competitors diff --url <https-url>
echo-cli competitors pages tracked [--product <id>]
echo-cli competitors pages watch --product <id> --url <https-url> --competitor <name> --notify <user-id> [--every-days <n>] --by <name>
echo-cli competitors pages unwatch --product <id> --url <https-url>
echo-cli competitors pages capture [--product <id>] --by <name>
echo-cli competitors pages due [--product <id>] --by <name>

Inputs and output#

capture writes the capture it stored, as id, url, final_url, title, headings, fetch_error, captured_by and captured_at, with pricing_change: the change this capture recorded or null. captures writes every capture of the page, newest first, in the same fields without the page text. pricing writes every pricing change of the page, newest first, as id, url, before_capture_id, after_capture_id, before_prices, after_prices and recorded_at. diff writes url, before and after (the two captures compared, newest after), added (text blocks the newer capture has and the older lacks) and removed (the reverse), and the page's structure beside them: headings and offers, each { added, removed } — the headings Weles read and the prices pricing reads that the newer capture has and the older lacks, and the reverse. pages tracked writes every tracked page (of the product when named) as product_id, url, competitor, notify_user, every_days (null when captured on every daily run), watched_by and watched_at; watch and unwatch write the page tracked or untracked; pages capture (every tracked page) and pages due (only the due ones) write, per page captured, url, capture_id, fetch_error, pricing_change and alerts (change_id, product_id, pending_action_id and raised_at, one per product tracking the page).

State effect#

Every verb calls Echo Web's authenticated /api/market/captures, /api/market/pricing, /api/market/diff or /api/market/watched with ECHO_INTERNAL_BEARER at ECHO_WEB_BASE_URL; the Page history and Tracked competitor pages sections of the competitors screen and the Competitor pages and Tracked competitor pages sections of Echo Desktop's GEO screen call the same operations, and echo-mcp lists captures (echo_competitor_page_captures), price moves (echo_competitor_pricing_changes) and compares captures (echo_competitor_page_diff) but cannot take one, and manages tracked pages (echo_competitor_pages, echo_competitor_page_watch, echo_competitor_page_unwatch, echo_competitor_pages_capture with due). A capture renders the page through Weles with Echo's research viewport (ECHO_RESEARCH_VIEWPORT) and research agent and stores the address it ended at, its title, headings and visible text; a page that cannot be rendered is stored with the error that stopped it and no reading, so a failed fetch never looks like an emptied page. A page's prices are every amount written with a currency symbol, with the billing period that follows it (such as $29 / mo), in the order they first appear; when a readable capture shows other prices than the page's previous readable capture, a pricing change is recorded with both lists, and matching prices record nothing. diff compares only readable captures: the page's text is split into blocks at line breaks with runs of spaces collapsed, and blocks are compared as wholes. /api/cron/competitor-pages runs daily at 05:17 UTC, before the battlecards refresh, and captures each due page once however many products track it: a page is due when a product tracks it without --every-days, or when its newest capture (readable or not) is at least the shortest --every-days of the products tracking it old; pages due makes the same choice now, pages capture takes every page. A capture that records a pricing change raises one pending action (type competitor_pricing_change, naming the page, both price lists and both captures) for the notify_user of each product tracking the page, kept in competitor_pricing_alerts so a change alerts a product once. An unreadable page alerts no one and is answered with its fetch error.

Refusals#

  • A wrong invocation is refused before anything is sent: "competitors takes <every verb's usage, separated by semicolons>; got <word>", "competitors <verb> does not take <flag>; it takes …", "<flag> needs a value" and "competitors <verb> needs <flag>" for each flag the verb needs.
  • Echo Web answers a bad request with "url is required: the public https page to capture", "url must be an absolute https address; got <value>", "<url> has one readable capture, taken <time>; a diff needs a second, which echo-cli competitors capture --url <url> takes" or "captured_by is required: an internal caller has no signed-in user, so it names who is acting"; and not found with "<url> has no readable capture; echo-cli competitors capture --url <url> takes one". A page Weles cannot render is not a refusal: capture stores it with fetch_error set to Weles's or the network's own words. The command prints Echo Web's sentence and exits non-zero on a refusal.
  • pages watch is refused with "product_id is required: …", "competitor is required: whose page it is", "notify_user is required: the user whose pending actions receive a price move" and "every_days must be a positive whole number: how many days pass between captures of the page; got <value>", not found with "no product has id <id>; echo-cli products lists the ones that exist", and a conflict with "product <id> already tracks <url>, since <time> by <name>"; pages unwatch with "product <id> does not track <url>"; pages capture and pages due with "product_id, when given, is the product whose tracked pages to capture". A pending action or alert that cannot be stored is the error naming the change and the product.