# null Source: https://docs.ratelab.app/getting-started # Getting Started This guide will walk you through installing Rate Lab and creating your first custom shipping rate. ## Install Rate Lab 1. **Find Rate Lab in the Shopify App Store** Visit the Shopify App Store and search for "Rate Lab" or use your direct installation link. 2. **Install to your store** Click "Add app" and follow the prompts to authorize Rate Lab to access your store's shipping settings. 3. **Open Rate Lab** After installation, find Rate Lab in your Shopify admin under Apps. Click to open the Rate Lab workspace. ## Your first custom rate When you open Rate Lab, you'll see three panels filled with a working example. Let's understand what you're looking at: ### Left panel: Your Liquid template This is where you write your shipping logic. The default example shows a simple rate calculation: ```liquid theme={null} {% liquid assign service_name = "Rate Lab Test" assign total_weight = shopify_rate_check.line_items | sum: "grams" assign weight_price = total_weight | divided_by: 1.5 | round %} { "rates": [{ "service_name": {{ service_name | json }}, "service_code": "RL", "currency": "USD", "total_price": {{ weight_price }} }] } ``` This calculates shipping based on the total weight of items in the cart. ### Top right panel: Order data (Context) This shows what information Shopify provides about the order - items, quantities, destination, cart totals, etc. Your Liquid template uses this data to calculate rates. ### Bottom right panel: Rate results This shows the shipping rates your template produces - what customers will see at checkout. ## Try modifying the rate Let's make a simple change: 1. In the left panel, find this line: ```liquid theme={null} assign weight_price = total_weight | divided_by: 1.5 | round ``` 2. Change it to charge more per gram: ```liquid theme={null} assign weight_price = total_weight | divided_by: 1.0 | round ``` 3. Click the **Run** button at the top 4. Watch the bottom right panel update to show the new shipping price That's it! You've just modified your first shipping rate calculation. ## What's actually happening? When a customer reaches checkout, Shopify sends order information to Rate Lab. Your Liquid template processes that information and returns shipping rates. The customer sees these rates as options at checkout. The three-panel interface lets you test your logic safely before customers see it. You can: * Edit your Liquid template (left panel) * Test with different order scenarios (top right panel) * See the resulting rates immediately (bottom right panel) ## Next steps Now that you understand the basics, learn more about: * **[Using the IDE](ide-tour)** - Deep dive into the workspace and available tools * **[Understanding Your Data](live-updates)** - Learn what information is available in your Liquid templates * **[Shipping Examples](use-cases/index)** - Browse ready-to-use templates for common scenarios # null Source: https://docs.ratelab.app/glossary # Glossary * **App Bridge** — Shopify library that embeds Rate Lab inside the admin and issues session tokens. * **Function Object** — The `function` field returned by the IDE API, containing `id`, `name`, and `src`. * **Liquid Context** — JSON payload that Shopify supplies to your shipping function for evaluation. * **Monaco Editor** — The VS Code engine powering the template and JSON panels inside Rate Lab. * **Phoenix Channel** — WebSocket connection named `template:{function.id}` used for live updates. * **Rate Check** — A saved shipping scenario accessible via `/api/shopify/rate_check.json`. * **Rendered Attrs** — The evaluated Liquid output that Shopify reads to display shipping rates. * **Shopify Rate Function** — Liquid template that calculates shipping rates based on cart details. # null Source: https://docs.ratelab.app/ide-tour # Using the Rate Lab Interface Rate Lab's workspace is built around three panels that work together to help you design and test shipping rates. This guide will show you how to use each panel and the tools available to you. ## The three-panel workspace ### Left panel: Your Liquid template This is your code editor where you write shipping logic using Liquid. Think of it like editing a theme template, but for shipping rates. **What you can do:** * Write Liquid code with syntax highlighting and auto-completion * Access order data through the `shopify_rate_check` object * Calculate shipping prices using Liquid filters and logic * Return one or more shipping rate options for customers **Tips:** * The editor supports standard keyboard shortcuts (Ctrl/Cmd+S to save, Ctrl/Cmd+F to find) * Liquid syntax errors are highlighted as you type * You can undo/redo changes normally ### Top right panel: Order context (test data) This panel shows the order information that Shopify sends to your rate function. It's formatted as JSON and includes everything you need to make shipping decisions. **What's included:** * `line_items` - Products in the cart with quantities, weights, prices, SKUs, and properties * `destination` - Where the order is shipping (country, province, city, postal code) * `currency` - The currency for this order * Cart totals, item counts, and more **How to use it:** * Edit this data to test different scenarios (heavier orders, different countries, more items) * Try edge cases: single items, huge orders, international destinations * See how your rate logic responds to different inputs * Click **Run** after editing to recalculate rates **Example: Testing a weight-based rate** If you're building a rate that charges more for heavy orders, edit the `grams` field in a line item to test how your calculation responds. ### Bottom right panel: Rate results This read-only panel shows exactly what shipping options customers will see at checkout after your Liquid template runs. **What you'll see:** * `service_name` - The shipping method name (e.g., "Standard Shipping", "Express") * `service_code` - An internal identifier * `total_price` - The price in cents (e.g., 995 = \$9.95) * `currency` - The currency code * `description` (optional) - Additional information shown to customers **Multiple rates:** Your template can return multiple shipping options, giving customers choices like "Standard ($9.95)" and "Express ($19.95)". ## Toolbar controls **Run button** Click this whenever you change your Liquid template or test data. It recalculates the rates and updates the results panel. **Template name field** Give your rate function a descriptive name like "Holiday Shipping Rules" or "Multi-Vendor Rates". This helps when you have multiple rate functions. **Auto-update indicator** When active, this shows that your workspace automatically updates when changes are saved. You'll see your rate results refresh in real-time. ## Common workflows ### Building a new rate from scratch 1. Clear the left panel and start with this basic structure: ```liquid theme={null} { "rates": [{ "service_name": "My Shipping Rate", "service_code": "CUSTOM", "currency": "USD", "total_price": 1000 }] } ``` 2. Add Liquid logic to calculate `total_price` based on order data 3. Click **Run** to test 4. Iterate until the rate behaves as expected ### Testing different scenarios 1. Start with your working template in the left panel 2. Edit the order context (top right) to simulate different orders: * Change item quantities * Modify destination country or postal code * Adjust product weights or prices 3. Click **Run** after each change 4. Verify the rate results (bottom right) match your expectations ### Copying an example 1. Browse the [Shipping Examples](use-cases/index) section 2. Copy the Liquid code from an example that's close to what you need 3. Paste it into your left panel 4. Modify the logic for your specific requirements 5. Test with your order data ## Quick tips **Prices are in cents** Always work with prices in cents/pennies. \$9.95 = 995, not 9.95. **Use the json filter** When outputting strings in JSON, use `{{ my_variable | json }}` to properly escape quotes and special characters. **Test edge cases** Try extreme scenarios: empty carts, single items, international orders, very heavy shipments. Your rate logic should handle all cases gracefully. **Check your math** If rates seem wrong, use Liquid's math filters step by step and verify each calculation in the results. ## Next steps * **[Understanding Your Data](live-updates)** - Learn about all the order information available in your Liquid templates * **[Shipping Examples](use-cases/index)** - Browse ready-to-use templates for common scenarios * **[Troubleshooting](troubleshooting)** - Fix common issues and error messages # null Source: https://docs.ratelab.app/live-updates # Understanding Your Order Data When calculating shipping rates, your Liquid template has access to detailed information about the order through the `shopify_rate_check` object. This page explains what data is available and how to use it. ## The rate check object In the top right panel of Rate Lab, you'll see a JSON object containing all the order information Shopify provides. Your Liquid template accesses this data to make shipping decisions. ### Basic structure ```liquid theme={null} shopify_rate_check ├── rate (origin information) ├── items (or line_items - the products being ordered) ├── destination (shipping address) ├── currency └── locale ``` ## Line items (products in cart) Access products using `shopify_rate_check.items` or `shopify_rate_check.line_items`: ```liquid theme={null} {% for item in shopify_rate_check.items %} {{ item.name }} {{ item.quantity }} {{ item.grams }} {{ item.price }} {{ item.sku }} {{ item.vendor }} {{ item.requires_shipping }} {% endfor %} ``` ### Common patterns with items **Calculate total weight:** ```liquid theme={null} {% assign total_weight = shopify_rate_check.items | sum: "grams" %} ``` **Calculate cart subtotal:** ```liquid theme={null} {% assign subtotal = 0 %} {% for item in shopify_rate_check.items %} {% assign line_total = item.price | times: item.quantity %} {% assign subtotal = subtotal | plus: line_total %} {% endfor %} ``` **Count items by SKU:** ```liquid theme={null} {% assign kayak_items = shopify_rate_check.items | where: "sku", "KAYAK-01" %} {% assign kayak_count = kayak_items | size %} ``` **Filter by vendor:** ```liquid theme={null} {% assign acme_items = shopify_rate_check.items | where: "vendor", "Acme Corp" %} ``` **Check for specific products:** ```liquid theme={null} {% assign has_hazmat = false %} {% for item in shopify_rate_check.items %} {% if item.properties contains "hazmat" %} {% assign has_hazmat = true %} {% endif %} {% endfor %} ``` ## Destination (shipping address) Access shipping address details: ```liquid theme={null} {{ shopify_rate_check.destination.country_code }} {{ shopify_rate_check.destination.province_code }} {{ shopify_rate_check.destination.city }} {{ shopify_rate_check.destination.postal_code }} ``` ### Geographic logic examples **Charge more for Alaska/Hawaii:** ```liquid theme={null} {% assign base_price = 995 %} {% if shopify_rate_check.destination.province_code == "AK" or shopify_rate_check.destination.province_code == "HI" %} {% assign base_price = 1995 %} {% endif %} ``` **Block PO boxes:** ```liquid theme={null} {% assign address = shopify_rate_check.destination.address1 | downcase %} {% if address contains "po box" or address contains "p.o. box" %} {% endif %} ``` **International surcharge:** ```liquid theme={null} {% assign surcharge = 0 %} {% if shopify_rate_check.destination.country_code != "US" %} {% assign surcharge = 1500 %} {% endif %} ``` ## Currency The order's currency is available at: ```liquid theme={null} {{ shopify_rate_check.currency }} ``` Always return rates in the same currency: ```liquid theme={null} { "rates": [{ "service_name": "Standard Shipping", "service_code": "STANDARD", "currency": {{ shopify_rate_check.currency | json }}, "total_price": 995 }] } ``` ## Product properties and metafields Items can have custom properties and metafields that you can use in your logic: ```liquid theme={null} {% for item in shopify_rate_check.items %} {% if item.properties.gift_wrap == "true" %} {% endif %} {% endfor %} ``` ## Advanced: Working with variants Some rate checks include variant information: ```liquid theme={null} {% for item in shopify_rate_check.items %} {{ item.variant_id }} {{ item.product_id }} {{ item.variant_title }} {% endfor %} ``` ## Testing different scenarios In Rate Lab's top right panel, you can edit this data to test how your rates respond: **Test heavier orders:** Change `"grams": 500` to `"grams": 5000` on an item **Test international shipping:** Change `"country_code": "US"` to `"country_code": "CA"` **Test high-value orders:** Change item prices or quantities to create a large cart total **Test specific products:** Add or remove items, change SKUs, modify vendor names ## Prices are always in cents Remember: all price values in Rate Lab are in cents (or smallest currency unit): * `"price": 1995` = \$19.95 * `"price": 50` = \$0.50 * Your `total_price` should also be in cents ## Next steps Now that you understand what data is available, explore how to use it: * **[Shipping Examples](use-cases/index)** - See real-world examples using this data * **[Cart & Pricing](use-cases/cart-and-pricing)** - Calculate rates based on cart value and weight * **[Destination Controls](use-cases/destination-controls)** - Adjust rates by geography * **[Product Qualifiers](use-cases/product-qualifiers)** - Use SKUs, vendors, and properties # null Source: https://docs.ratelab.app/overview # What is Rate Lab? Rate Lab is a Shopify app that gives you complete control over your shipping rates through custom logic. Instead of being limited to basic carrier rates or simple flat fees, you can create sophisticated shipping calculations that respond to your cart contents, destination, products, and business rules. ## What you can do with Rate Lab **Cart-based pricing** Charge a percentage of cart subtotal, offer free shipping over a threshold, or adjust rates based on total weight or item count. **Product-specific logic** Apply surcharges for oversized items, hazmat fees, or special handling. Filter rates based on SKU, vendor, or product properties. **Geographic controls** Block shipping to PO boxes, charge extra for remote regions, or offer different rates by country, state, or postal code. **Multi-vendor operations** Calculate separate fees per vendor, cap rates by fulfillment partner, or route orders based on warehouse location. **Dynamic rate descriptions** Show customers exactly why a rate costs what it does, with contextual messages based on their order. ## How it works Rate Lab provides a three-panel workspace in your Shopify admin: 1. **Write shipping logic** using Liquid templates - the same template language you use in Shopify themes 2. **Test with real order data** by previewing exactly what Shopify sends during checkout 3. **See instant results** as you make changes, with live updates showing the rates customers will see ## What's in this guide **[Getting Started](getting-started)** - Install the app and create your first custom shipping rate **[Using the IDE](ide-tour)** - Learn the three-panel interface and how to test your logic **[Understanding Your Data](live-updates)** - See what information is available for your shipping calculations **[Shipping Logic Examples](use-cases/index)** - Copy and adapt proven templates for common scenarios **[Reference](glossary)** - Troubleshooting tips and glossary of terms Ready to take control of your shipping rates? Continue to [Getting Started](getting-started). # null Source: https://docs.ratelab.app/troubleshooting # Troubleshooting Checklist Use these checks when something feels off inside Rate Lab. ## No rates returned * Verify `rates` is an array in your Liquid output; returning `[]` hides all offers. * Confirm `rendered_attrs` in the Output panel contains the expected structure. * Re-run the scenario and inspect backend logs for evaluation errors. ## WebSocket isn’t updating * Check the toolbar indicator—red means the Phoenix channel is disconnected. * Ensure the `function.id` in your payload matches the active template channel. * Try the **Run** button to force a manual refresh while the socket reconnects. ## Authentication failures * Refresh your Shopify admin window to regenerate App Bridge tokens. * Make sure development environment variables for the embedded app are set. * Confirm the Phoenix backend allows the origin you’re testing from. ## Editor issues * JSON validation errors appear inline; fix syntax before re-running. * If Monaco stops responding, reload the route—state persists after reconnect. * Disable browser extensions that inject scripts into Shopify admin pages. # null Source: https://docs.ratelab.app/use-cases/cart-and-pricing # Cart & Pricing Strategies These examples show how to calculate shipping based on cart totals, weight thresholds, and quantity-based adjustments. Copy any template below and adapt it to your needs. ## Default Rate Lab function ```liquid theme={null} {% liquid assign service_name = "Rate Lab Test" assign kayak_lines = shopify_rate_check.line_items | select: "sku", "abkayak" | size assign kayak_surcharge = kayak_lines | times: 5000 assign total_weight = shopify_rate_check.line_items | sum: "grams" assign weight_price = total_weight | divided_by: 1.5 | round %} { "rates": [{ "service_name": {{ service_name | json }}, "service_code": "RL", "currency": "USD", "total_price": {{ total_weight | plus: kayak_surcharge }} }] } ``` * Calculates a base price from cart weight. * Adds a surcharge for “abkayak” SKUs to cover oversize handling. ## Percentage of cart subtotal ```liquid theme={null} {% liquid assign cart_subtotal = 0 for item in shopify_rate_check.items assign line_total = item.price | times: item.quantity assign cart_subtotal = cart_subtotal | plus: line_total endfor assign shipping_price = cart_subtotal | times: 12 | divided_by: 100 assign shipping_price = shipping_price | at_least: 500 | at_most: 2500 %} { "rates": [ { "service_name": {{ "12% Cart Shipping" | json }}, "service_code": "PERCENT", "currency": {{ shopify_rate_check.currency | json }}, "total_price": {{ shipping_price }}, "description": {{ "12% of cart subtotal, between $5 and $25" | json }} } ] } ``` * Charges 12% of the cart subtotal. * Uses guardrails to enforce a minimum and maximum shipping charge. ## Weight and spend combined ```liquid theme={null} {% liquid assign cart_subtotal = 0 assign total_weight = 0 for item in shopify_rate_check.items assign line_total = item.price | times: item.quantity assign cart_subtotal = cart_subtotal | plus: line_total assign line_weight = item.grams | times: item.quantity assign total_weight = total_weight | plus: line_weight endfor assign shipping_price = 900 if total_weight > 10000 assign shipping_price = 1400 endif if cart_subtotal >= 20000 and shopify_rate_check.destination.country == "US" assign shipping_price = 0 endif %} { "rates": [ { "service_name": {{ "Weight & Spend Logic" | json }}, "service_code": "WEIGHT_PRICE", "currency": {{ shopify_rate_check.currency | json }}, "total_price": {{ shipping_price }}, "description": {{ "Base $9, heavier than 10kg is $14, free over $200 spend in the US" | json }} } ] } ``` * Starts with a flat fee, increases for heavier orders, and offers free shipping for high-value US orders. ## First item plus incremental extras ```liquid theme={null} {% liquid assign shippable_qty = 0 for item in shopify_rate_check.items if item.requires_shipping assign shippable_qty = shippable_qty | plus: item.quantity endif endfor assign additional_units = shippable_qty | minus: 1 | at_least: 0 assign incremental = additional_units | times: 250 assign shipping_price = 850 | plus: incremental %} { "rates": [ { "service_name": {{ "First Item + Extras" | json }}, "service_code": "PER_ITEM", "currency": {{ shopify_rate_check.currency | json }}, "total_price": {{ shipping_price }}, "description": {{ "First shippable item is $8.50, each additional adds $2.50" | json }} } ] } ``` * Counts only shippable items. * Adds \$2.50 for every additional unit beyond the first. Looking for more specialized rules? Continue to [Vendor-Based Logic](vendor-operations). # null Source: https://docs.ratelab.app/use-cases/destination-controls # Destination Controls Adjust shipping based on where the order is going - country, region, postal code, or address type. ## Postal code tiering ```liquid theme={null} {% liquid assign postal_code = shopify_rate_check.destination.postal_code | upcase assign prefix = postal_code | slice: 0, 3 if prefix == "941" assign shipping_price = 0 assign description = "Free local delivery for San Francisco 941xx" assign service_name = "Local Delivery" assign service_code = "LOCAL_FREE" elsif prefix == "997" or prefix == "999" assign shipping_price = 2800 assign description = "Remote area surcharge applies" assign service_name = "Remote Area Shipping" assign service_code = "REMOTE_SURCHARGE" else assign shipping_price = 1200 assign description = "Standard continental US shipping" assign service_name = "Standard Shipping" assign service_code = "STANDARD" endif %} { "rates": [ { "service_name": {{ service_name | json }}, "service_code": {{ service_code | json }}, "currency": {{ shopify_rate_check.currency | json }}, "total_price": {{ shipping_price }}, "description": {{ description | json }} } ] } ``` * Branches on the postal code prefix to serve local delivery, remote surcharges, or standard shipping. ## State-based restrictions ```liquid theme={null} {% liquid assign region = shopify_rate_check.destination.province | upcase assign restricted_state_list = "AK,HI,PR" | split: "," assign restricted_skus = "BATTERY-001|BATTERY-010" assign is_restricted_region = false for state in restricted_state_list if state == region assign is_restricted_region = true endif endfor assign has_restricted_sku = false for item in shopify_rate_check.items if restricted_skus contains item.sku assign has_restricted_sku = true endif endfor assign allow_rates = true if is_restricted_region and has_restricted_sku assign allow_rates = false endif %} { "rates": {% if allow_rates %} [ { "service_name": {{ "Standard Shipping" | json }}, "service_code": "STANDARD", "currency": {{ shopify_rate_check.currency | json }}, "total_price": 1800, "description": {{ "Allowed because restricted SKUs are not headed to blocked states" | json }} } ] {% else %} [] {% endif %} } ``` * Blocks rates entirely when restricted SKUs ship to prohibited states. * Demonstrates how to return an empty array to stop Shopify from showing the rate. ## Offshore surcharge ```liquid theme={null} {% liquid assign offshore_regions = "AK,HI,PR" | split: "," assign region = shopify_rate_check.destination.province | upcase assign is_offshore = false for code in offshore_regions if code == region assign is_offshore = true endif endfor assign base_price = 1000 assign surcharge = 0 if is_offshore assign surcharge = 1500 endif assign total_price = base_price | plus: surcharge %} { "rates": [ { "service_name": {{ "Standard Shipping" | json }}, "service_code": "STANDARD", "currency": {{ shopify_rate_check.currency | json }}, "total_price": {{ total_price }}, "description": {{ "Adds $15.00 for AK/HI/PR destinations" | json }} } ] } ``` * Adds a surcharge when shipping to non-continental regions. * Keeps the same base service for all other destinations. ## PO box filtering ```liquid theme={null} {% liquid assign address = shopify_rate_check.destination.address1 | downcase | replace: ".", "" assign is_po_box = address contains "po box" assign ground_price = 1200 assign expedited_price = 2200 %} { "rates": [ { "service_name": {{ "Postal Ground" | json }}, "service_code": "GROUND_PO", "currency": {{ shopify_rate_check.currency | json }}, "total_price": {{ ground_price }}, "description": {{ "Safe delivery for PO boxes" | json }} } {% unless is_po_box %} , { "service_name": {{ "Courier Express" | json }}, "service_code": "EXPRESS", "currency": {{ shopify_rate_check.currency | json }}, "total_price": {{ expedited_price }}, "description": {{ "Hand-delivered express service" | json }} } {% endunless %} ] } ``` * Always offers a PO-box-safe method. * Hides the express option when the destination is a PO box. Next, see how product attributes can influence shipping in [Product-Level Qualifiers](product-qualifiers). # null Source: https://docs.ratelab.app/use-cases/fulfillment-fees # Fulfillment & Fees These examples show how to add handling fees, account for fulfillment partners, segment by warehouse, and apply pricing refinements. ## Fulfillment-aware surcharge ```liquid theme={null} {% liquid assign base_price = 700 assign fulfillment_surcharge = 0 for item in shopify_rate_check.items if item.fulfillment_service == "printful" and item.requires_shipping assign fulfillment_surcharge = 500 endif endfor assign total_price = base_price | plus: fulfillment_surcharge %} { "rates": [ { "service_name": {{ "Fulfillment-aware Shipping" | json }}, "service_code": "FULFILLMENT", "currency": {{ shopify_rate_check.currency | json }}, "total_price": {{ total_price }}, "description": {{ "Adds $5.00 when Printful-fulfilled items are present" | json }} } ] } ``` * Flags items fulfilled externally and adds a handling surcharge. ## Fee per warehouse prefix ```liquid theme={null} {% liquid assign seen_prefixes = "" assign prefix_count = 0 for item in shopify_rate_check.items if item.requires_shipping assign prefix = item.sku | split: "-" | first assign marker = "|" | append: prefix | append: "|" unless seen_prefixes contains marker assign seen_prefixes = seen_prefixes | append: marker assign prefix_count = prefix_count | plus: 1 endunless endif endfor assign shipping_price = prefix_count | times: 800 %} { "rates": [ { "service_name": {{ "Per Warehouse Fee" | json }}, "service_code": "WAREHOUSE_PREFIX", "currency": {{ shopify_rate_check.currency | json }}, "total_price": {{ shipping_price }}, "description": {{ "Charges $8.00 for each distinct SKU prefix (warehouse)" | json }} } ] } ``` * Treats the SKU prefix as a warehouse identifier and charges per unique location. ## Market-aware rounding ```liquid theme={null} {% liquid assign cart_subtotal = 0 for item in shopify_rate_check.items assign line_total = item.price | times: item.quantity assign cart_subtotal = cart_subtotal | plus: line_total endfor assign base_shipping = cart_subtotal | times: 8 | divided_by: 100 if shopify_rate_check.currency == "JPY" assign shipping_price = base_shipping | plus: 49 | divided_by: 50 | times: 50 assign description = "Rounded up to the nearest ¥50 for Japan" else assign dollars = base_shipping | divided_by: 100 assign shipping_price = dollars | plus: 1 | times: 100 | minus: 5 assign description = "Rounded to a .95 ending for non-JPY orders" endif %} { "rates": [ { "service_name": {{ "Market Aware Shipping" | json }}, "service_code": "ROUNDING", "currency": {{ shopify_rate_check.currency | json }}, "total_price": {{ shipping_price }}, "description": {{ description | json }} } ] } ``` * Rounds to market-friendly amounts depending on currency. ## Max-of rules ```liquid theme={null} {% liquid assign cart_subtotal = 0 for item in shopify_rate_check.items assign line_total = item.price | times: item.quantity assign cart_subtotal = cart_subtotal | plus: line_total endfor assign percent_price = cart_subtotal | times: 7 | divided_by: 100 assign floor_price = 900 assign shipping_price = floor_price | at_least: percent_price %} { "rates": [ { "service_name": {{ "Best of Percentage or Floor" | json }}, "service_code": "MAX_RULE", "currency": {{ shopify_rate_check.currency | json }}, "total_price": {{ shipping_price }}, "description": {{ "Charges 7% of order value with a $9.00 minimum" | json }} } ] } ``` * Ensures shipping never drops below the floor while scaling with order value. Need to debug scenarios quickly? Jump to the [Troubleshooting Checklist](../troubleshooting). # null Source: https://docs.ratelab.app/use-cases/index # Shipping Logic Examples Rate Lab includes ready-made templates for common shipping scenarios. Use these as starting points for your own shipping strategies - copy the code, adapt it to your needs, and test it in the IDE. ## How to use these examples 1. Find an example that matches your needs (or is close to it). 2. Copy the Liquid code from the example. 3. Paste it into your Rate Lab template editor (left panel). 4. Modify values and logic to fit your specific requirements. 5. Click **Run** to test how it works with different order scenarios. ## Scenario categories * [Cart & Pricing Strategies](cart-and-pricing)\ Percentage-based pricing, tiered rates, and cart minimums. * [Vendor-Based Logic](vendor-operations)\ Allocate surcharges, caps, and fees per vendor or fulfillment partner. * [Destination Controls](destination-controls)\ Adjust rates based on geography, hazmat rules, or shipping restrictions. * [Product-Level Qualifiers](product-qualifiers)\ Detect properties, weight classes, or SKUs to influence pricing and descriptions. * [Fulfillment & Fees](fulfillment-fees)\ Introduce service fees, warehouse prefixes, or special handling costs. Prefer the basics first? Start with the default scenario highlighted in [Cart & Pricing Strategies](cart-and-pricing#default-rate-lab-function). # null Source: https://docs.ratelab.app/use-cases/product-qualifiers # Product-Level Qualifiers Adjust shipping based on product attributes - SKUs, vendors, properties, weight classes, or special handling requirements. ## Block express for hazmat goods ```liquid theme={null} {% liquid assign has_hazmat = false for item in shopify_rate_check.items if item.sku | upcase contains "HAZ" assign has_hazmat = true endif endfor assign standard_price = 1500 assign express_price = 2900 %} { "rates": [ { "service_name": {{ "Ground Shipping" | json }}, "service_code": "GROUND", "currency": {{ shopify_rate_check.currency | json }}, "total_price": {{ standard_price }}, "description": {{ "Always available ground transport" | json }} } {% unless has_hazmat %} , { "service_name": {{ "Express Air" | json }}, "service_code": "EXPRESS", "currency": {{ shopify_rate_check.currency | json }}, "total_price": {{ express_price }}, "description": {{ "2-day express delivery" | json }} } {% endunless %} ] } ``` * Identifies hazardous SKUs by pattern matching. * Suppresses the express option when hazmat inventory is present. ## Ignore digital items ```liquid theme={null} {% liquid assign physical_total = 0 assign physical_quantity = 0 for item in shopify_rate_check.items if item.requires_shipping assign line_total = item.price | times: item.quantity assign physical_total = physical_total | plus: line_total assign physical_quantity = physical_quantity | plus: item.quantity endif endfor if physical_total == 0 assign shipping_price = 0 else assign shipping_price = physical_total | times: 10 | divided_by: 100 assign shipping_price = shipping_price | at_least: 500 endif %} { "rates": [ { "service_name": {{ "Physical Goods Shipping" | json }}, "service_code": "PHYSICAL_ONLY", "currency": {{ shopify_rate_check.currency | json }}, "total_price": {{ shipping_price }}, "description": {{ "Ignores digital items when calculating shipping" | json }} } ] } ``` * Sums only items with `requires_shipping == true`. * Provides a percentage-based fee with a floor when physical goods remain. ## Context-driven descriptions ```liquid theme={null} {% liquid assign includes_glass = false assign vendor_list = shopify_rate_check.items | map: "vendor" | uniq for item in shopify_rate_check.items if item.vendor == "ACME Glassworks" assign includes_glass = true endif endfor assign base_price = 1100 assign description = "Standard packing and delivery" if includes_glass assign base_price = base_price | plus: 400 assign description = description | append: " — includes fragile padding for ACME Glassworks items" endif assign vendor_sentence = vendor_list | join: ", " assign description = description | append: " (" | append: vendor_sentence | append: ")" %} { "rates": [ { "service_name": {{ "Contextual Shipping" | json }}, "service_code": "CONTEXT_DESC", "currency": {{ shopify_rate_check.currency | json }}, "total_price": {{ base_price }}, "description": {{ description | json }} } ] } ``` * Detects fragile goods, applies a surcharge, and updates the description with context. * Includes a vendor rollup to inform the buyer who will ship their items. Next up: [Fulfillment & Fees](fulfillment-fees) covers service charges and warehouse-specific logic. # null Source: https://docs.ratelab.app/use-cases/vendor-operations # Vendor-Based Logic Calculate shipping based on suppliers and fulfillment partners by using vendor information, fulfillment metadata, and per-vendor subtotals. ## Flat fee per vendor ```liquid theme={null} {% liquid assign vendor_list = shopify_rate_check.items | map: "vendor" assign unique_vendors = vendor_list | uniq assign vendor_count = unique_vendors | size assign base_price = 600 assign vendor_fee = vendor_count | times: 500 assign total_price = base_price | plus: vendor_fee %} { "rates": [ { "service_name": {{ "Per Supplier Shipping" | json }}, "service_code": "PER_VENDOR", "currency": {{ shopify_rate_check.currency | json }}, "total_price": {{ total_price }}, "description": {{ "Adds $5.00 for each distinct vendor in the cart" | json }} } ] } ``` * Charges a base $6.00 plus $5.00 per distinct vendor detected. * Great for orders that ship from multiple dropship partners. ## Charge the highest vendor result ```liquid theme={null} {% liquid assign vendor_names = shopify_rate_check.items | map: "vendor" assign unique_vendors = vendor_names | uniq assign max_vendor_rate = 0 for vendor in unique_vendors assign vendor_items = shopify_rate_check.items | where: "vendor", vendor assign vendor_subtotal = 0 for item in vendor_items assign line_total = item.price | times: item.quantity assign vendor_subtotal = vendor_subtotal | plus: line_total endfor assign vendor_rate = vendor_subtotal | times: 6 | divided_by: 100 assign vendor_rate = vendor_rate | at_least: 500 if vendor_rate > max_vendor_rate assign max_vendor_rate = vendor_rate endif endfor assign shipping_price = max_vendor_rate %} { "rates": [ { "service_name": {{ "Max Per-Vendor Shipping" | json }}, "service_code": "PER_VENDOR_MAX", "currency": {{ shopify_rate_check.currency | json }}, "total_price": {{ shipping_price }}, "description": {{ "Compute each vendor separately and charge the highest result" | json }} } ] } ``` * Independently prices each vendor’s portion. * Ensures the single most expensive vendor drives the final shipping cost. ## Vendor-specific surcharge ```liquid theme={null} {% liquid assign base_price = 700 assign fragile_fee = 0 for item in shopify_rate_check.items if item.vendor == "FragileCo" and item.requires_shipping assign fragile_fee = 1500 endif endfor assign total_price = base_price | plus: fragile_fee %} { "rates": [ { "service_name": {{ "Fragile Item Handling" | json }}, "service_code": "FRAGILE", "currency": {{ shopify_rate_check.currency | json }}, "total_price": {{ total_price }}, "description": {{ "Adds a $15 fragile handling fee when FragileCo items are present" | json }} } ] } ``` * Adds a one-time surcharge when FragileCo inventory appears in the order. * Keeps other vendors at the standard pricing tier. ## Percentage for a vendor subset ```liquid theme={null} {% liquid assign base_price = 600 assign acme_subtotal = 0 for item in shopify_rate_check.items if item.vendor == "ACME Outdoors" assign line_total = item.price | times: item.quantity assign acme_subtotal = acme_subtotal | plus: line_total endif endfor assign acme_shipping = acme_subtotal | times: 15 | divided_by: 100 assign acme_shipping = acme_shipping | at_least: 0 assign total_price = base_price | plus: acme_shipping %} { "rates": [ { "service_name": {{ "ACME Gear Shipping" | json }}, "service_code": "ACME_PERCENT", "currency": {{ shopify_rate_check.currency | json }}, "total_price": {{ total_price }}, "description": {{ "15% surcharge on ACME Outdoors items plus base handling" | json }} } ] } ``` * Isolates one vendor’s subtotal and charges a percentage-based add-on. * Useful when partners require their own markup on top of shared handling. Continue with [Destination Controls](destination-controls) to see geography-aware pricing.