Tags & Routing
Developer Guide
What are tags?
Tags are short string labels attached to cart line items. When a rate request reaches the ShipRateAPI API, the tags on every item are pooled into a single basket-level set and matched against the tag rules on each rate table — for example, restricting a rate table to baskets containing cold-storage items, or excluding a rate table entirely when anything tagged hazmat is present.
Tags are evaluated per basket, not per item. The rating engine flattens the tags from every line item into one pool and evaluates each rate table once against that pool. A single hazmat item therefore excludes a table for the whole basket, and a single cold-storageitem satisfies that table's required tags for the whole basket — including the untagged items sitting alongside it. There is no per-item rating: one basket, one decision per table.
How tags are set — per platform
| Platform | Method |
|---|---|
| Magento 2 | Layer 1: shiprate_tags product attribute (comma-separated)Layer 2: Admin attribute mapping rules — map any EAV attribute value to a tag |
| Shopify | Line item property named shiprate_tags (comma-separated), set when the item is added to the cart.The native Shopify product Tags field is not read by the connector. |
| BigCommerce | Not available. BigCommerce does not expose product tags in its rate callback, so the connector always sends an empty tag array. |
| commercetools | Product attribute named shiprate_tags (comma-separated) — read per line item by the connector |
| Custom / REST | Pass tags directly in the items[].tags array of the API payload |
requiredTags set will never match a BigCommerce basket — those tables are silently skipped and their rates never appear at checkout. Keep at least one table with no required tags for BigCommerce zones, and use order value or weight guards instead of tags to route BigCommerce traffic.Magento 2 — attribute mapping rules
The attribute mapping table (under Stores → Configuration → Sales → Delivery Methods → ShipRateAPI Live Rates → Attribute Tag Mapping) lets you derive tags from existing product attributes without touching each product. This is useful when you already have structured data in attributes such as hazmat_class, temperature_zone, or product_category_code.
Example rules:
| Attribute Code | Operator | Value | Tag applied |
|---|---|---|---|
temperature_zone | equals | chilled | cold-storage |
hazmat_class | not equals | (empty) | dangerous-goods |
name | contains | glass | fragile |
Attribute codes are validated against the Magento EAV catalog when you save the config. Rules with an invalid attribute code are rejected with a descriptive error before the config is persisted. At runtime, if an attribute cannot be read (e.g. it was deleted after the config was saved), the rule is skipped with a warning logged — the checkout flow is not interrupted.
Tags in the API payload
Tags appear in the items[].tags array. Every connector filters out empty strings, and the API trims and lowercases each inbound tag on arrival. Deduplication is Magento-only — the Magento module merges its two tag layers and removes duplicates; the Shopify and commercetools connectors send whatever remains once empties are dropped. Duplicates are harmless either way, since matching is a membership test — though they still count toward the 20-tag limit below. A product with no tags sends an empty array.
"items": [
{
"sku": "CHILLED-001",
"name": "Organic Milk 2L",
"qty": 1,
"price": 1.80,
"weight": 2.1,
"tags": ["cold-storage", "perishable"]
},
{
"sku": "STANDARD-002",
"name": "Reusable Bag",
"qty": 2,
"price": 0.99,
"weight": 0.05,
"tags": []
}
]How tags route a basket to a rate table
Every rate table carries three tag fields: requiredTags, excludedTags, and matchMode. The rating engine checks them against the basket tag pool in a fixed order, before any weight, order value, or bracket logic runs.
- Excluded tags are evaluated first, and win outright. If any tag in
excludedTagsappears anywhere in the basket, the table is skipped immediately with the reasontag_mismatch—requiredTagsis never even read. An exclusion cannot be overridden by a required tag on the same table. - Required tags are evaluated second, honouring
matchMode.any— the default — needs at least one required tag present in the basket;allneeds every required tag present. If the basket does not satisfy them, the table is skipped withtag_mismatch. - A table with neither field set matches every basket — including baskets with no tags at all. That is what makes a table an unrestricted fallback.
Worked examples:
| Table tag config | Basket tags | Outcome |
|---|---|---|
| (none set) | anything, including none | Matches — unrestricted fallback |
required cold-storage, mode any | cold-storage | Matches |
required cold-storage, medicine, mode any | medicine | Matches — any needs just one |
required cold-storage, medicine, mode all | medicine | Skipped — all needs both present |
excluded hazmat | fragile, hazmat | Skipped — one hazmat item excludes the whole basket |
required cold-storage, excluded hazmat | cold-storage, hazmat | Skipped — exclusion is checked first and wins |
Cold-Storage and cold-storage are the same tag.Configuring routing rules in the portal
Tags are not configured as standalone rules — they are fields on a rate table. Once tags are flowing in the API payload, open Rate Tables in the admin portal sidebar, then edit (or create) the table you want to restrict. Its form carries three tag fields: Required tags, Tag match mode (shown once at least one required tag is set), and Excluded tags.
Because tags live on the table itself, they combine naturally with that table's zone, carrier, schedule window, and order value guards — a basket must satisfy all of them for the table to produce a rate. Setting the same tag as both required and excluded on one table makes it impossible to match; the Coverage Scanner flags that as an error, along with zones that have no unrestricted fallback table.