Vizen Shop

Storefront redirects: old addresses that keep their traffic

/docs/redirectsdraftEN· проверено 2026-09-25

Резюме по-русски. Правила «откуда → куда» для витрины магазина: точное, маска, шаблон, условие по параметру; переход «не найдено → ближайший раздел»; журнал 404. Здесь — короткий вход и жизненный цикл адреса; полный справочник — /docs/redirects-reference?section=<slug>. Перед переносом раздела — dry_run и вопрос владельцу.

Status: draft · Verified: 2026-09-25 against branch production (integration TestSFR* on PostgreSQL 17) · Owner: redirects line Serves: GET /docs/redirects · full reference GET /docs/redirects-reference

What redirects are

A rule {from_path, to_target, code, enabled} sends a path of the shop's own storefront to another path (or, with external: true, to an http(s) URL) under redirects:read / redirects:write, for the shop's owner or admin only. Three kinds: exact /old (optionally with query_match ELEMENT_ID=5), pattern — a mask, * inside one segment and ** as the tail, $1…$9 in the target (/old/*.html → /c/$1), and prefix /shop/* → /catalog/* (the tail carried). A rule acts only where no page exists unless override_live: true. Rules live in production only; a draft key reads them and cannot write.

How the storefront answers an address

  1. rules with override_live (exact → pattern → prefix) or on a .html address — their own 301/302;
  2. the live page — or, when the chain broke, the entity named by the last segment (308 to its canonical address);
  3. the slug journal: an old slug of a product, category or article (308);
  4. rules without override_live — answered as 308/307 (Next.js);
  5. miss_fallback (on by default): a live section typed in another Latin case → that section; a deleted product → its last section, otherwise the nearest live section of the address; never /; 308. A file address (…/feed.yml — .xml, .csv, .txt, .json, .yml) never falls back;
  6. 404, and the address goes to the 404 log.

URL lifecycle

  • Moving a category changes the addresses of the category, its subcategories and the products whose primary category is in the branch. They keep working by rule 2 above. Before moving, call `POST /categories/move` with `"dry_run": true`, show the summary to the user and ask: move · move and pin with rules · cancel. Then repeat without dry_run, with "pin_rules": true if asked. The answer: categories_affected, products_affected, rules_created, url_changes[] (≤ 20 examples of old_path, new_path, kind, covered_by: auto · rule · fallback · none). pin_rules creates an exact 301 rule for every changed address not already covered, in the same transaction; over the limit the whole move is refused (REDIRECT_LIMIT_REACHED) and nothing moves. Needs redirects:write.
  • Moving a product to another category: the old address follows by the last segment; pin it with an exact rule if asked.
  • Renaming a slug (product, category, article): the journal answers 308 from the old slug; GET /slug-redirects/resolve?entity_type=article&….
  • Deleting a product or category: miss_fallback sends its addresses to the nearest live section; for another target create an exact rule.

Quick start

curl -s "$API/storefront-redirects" -H "$T"                      # set, version, miss_fallback
curl -s -X POST "$API/storefront-redirects" -H "$T" -H "$J" \
  -d '{"item":{"from_path":"/old","to_target":"/new","enabled":true}}'
curl -s "$API/storefront-redirects/check?url=/old" -H "$T"       # every step

Key rules

  • `enabled: true` must be sent — a rule without it is saved switched off.
  • CSV exchange (POST /storefront-redirects/import, dry_run first): from;to;code;kind;params;condition;always;note — always 1 = override_live; no note column keeps the stored note.
  • Ad tags always travel (utm_*, gclid, yclid…), even with drop_query.
  • Loops are refused (REDIRECT_LOOP), counting masks, .html and the fallback; 10 hops are allowed, the 11th is REDIRECT_CHAIN_TOO_LONG.
  • Check: code is the rule's, sent_code the one sent (308/307).
  • Limits are the plan's: redirects_max rules and redirect_masks_max masks (Free 200/20, Pro 2000/50), refused with REDIRECT_LIMIT_REACHED / REDIRECT_PATTERN_LIMIT_REACHED + limit_code; ceiling 20000/200 whatever the plan; 1000 lines per import. ?section=11-limits.
  • Turn the fallback off with PUT /storefront-redirects/settings {"miss_fallback": false}.

404 log

GET /storefront-redirects/misses?q=&sort=hits|last_seen&include_hidden=true — addresses that still answered 404 after all of the above: path, hits, last_seen, the referrer host, rule_id (the rule that catches it now; 0 — none). Bot junk (.php, wp-admin, .env…) is not logged; one-hit days expire after 90 days. Hide: POST /storefront-redirects/misses/hide {"paths":[…]}. A rule from a row: from_path = path.

Reference: sections

GET /docs/redirects-reference?section=<slug>:

SlugWhat
1-what-you-can-do-here · 2-decide-first-forks · 3-quick-startscope, which rule to take, three requests
4-requests (4-2-endpoints, 4-3-csv-import-and-export, 4-4-check-an-address)objects, endpoints with JSON, CSV, check, settings, public set
5-what-the-storefront-does-with-an-address · 6-mask-grammarmatching order, 301/302 vs 308/307, masks
7-url-lifecycle (7-1-moving-a-category, 7-3-renaming-a-slug)move, rename, delete in detail
8-loops · 9-refusal-codes · 10-silently-ignoredloop rules, error codes, silent traps
11-limits · 12-404-log · 13-how-this-was-verifiedlimits and plans, the 404 log, tests

Исходник: https://api.vizen.shop/docs/redirects

Работает в демо-режиме