Respond - Liquid Tag Reference
On this page
The respond simple tag sends a custom HTTP response and stops rendering immediately. Use it in a Liquid controller to return JSON from API endpoints, send error responses, or override the default page rendering.
:::note
This tag works only inside a Liquid controller template (at controllers/<controller>/<action>.liquid). It is typically used in the before or after blocks. Once called, normal page rendering is skipped.
:::
When respond runs
Use respond to short-circuit rendering and send a custom response:
```liquid
{% before %} {% assign product_id = current_request.params.id %}
{% if product_id == blank %} {% respond body: ‘{“error”: “product_id required”}’, status: 400, layout: false %} {% endif %}
{% params product_id: product_id %} {% endbefore %} ```
When respond is called, rendering stops immediately and the response is sent to the client.
Syntax
```liquid
{% respond body: response_body, status: 200, layout: false %} ```
| Property | Value |
|---|---|
| Tag Name | respond |
| Type | Simple tag |
| Source | StoreConnect |
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
body |
String | Yes | The response body. Pre-serialize objects with the \| json filter. |
status |
Integer | No | HTTP status code. Defaults to 302, so set it explicitly whenever you are returning a body. Common values: 200, 400, 401, 403, 404, 422, 500 |
layout |
Boolean | No | Whether to wrap the response in the page layout (default: true). Set false for JSON and other non-HTML bodies |
notice |
String | No | A flash notice message (available on the redirected page) |
alert |
String | No | A flash alert message (available on the redirected page) |
data |
Hash | No | Additional data to pass to the response (typically for JSON APIs) |
to |
String | No | Redirect path after responding (use with notice/alert) |
What’s available in respond
current_request.params— still accessible- All globals —
current_store,current_customer,current_cart, etc. - Liquid filters — use
| jsonto serialize objects before responding - Liquid objects — render them to JSON or string format
Common tasks with respond
1. Return a JSON error response
```liquid
{% before %} {% assign product_id = current_request.params.id %}
{% if product_id == blank %} {% respond body: ‘{“error”: “product_id is required”}’, status: 400, layout: false %} {% endif %}
{% params product_id: product_id %} {% endbefore %} ```
2. Return cart data as JSON
```liquid
{% before %} {%- new Map result -%} {%- assign result = result | set_key: “cart_count”, current_cart.items.size -%} {%- assign result = result | set_key: “cart_total”, current_cart.total -%} {%- assign result = result | set_key: “status”, “success” -%} {% respond body: result | json, status: 200, layout: false %} {% endbefore %} ```
3. Return HTML error page with status code
```liquid
{% before %} {% assign requested_id = current_request.params.id %}
{% params requested_id: requested_id %}
{% if requested_id == blank %} {% respond body: “<h1>Not Found</h1><p>The requested item does not exist.</p>”, status: 404 %} {% endif %} {% endbefore %} ```
Key behaviors
- Stops rendering immediately — respond terminates the page template rendering
- Replaces page output — the body you provide is sent as the full response
layout: falseis typical for JSON — setlayout: falsewhen returning JSON to avoid wrapping it in the page template- Pre-serialize with
| json— objects must be converted to JSON before sending as a response body - Flash messages supported — include
noticeoralertif you want to show a message on the target page respondruns after response sent — in the final phase, respond is a no-op (the client already has their response)
Best practices
Always validate before responding
```liquid
{% before %} {% assign email = current_request.params.email %}
{% if email == blank %} {% respond body: ‘{“error”: “email is required”}’, status: 400, layout: false %} {% endif %}
{% action “account.send_welcome_email”, email: email %}
{% params email: email %} {% endbefore %} ```
Serialize objects to JSON explicitly
```liquid
{% before %} {%- new Map error_response -%} {%- assign error_response = error_response | set_key: “success”, false -%} {%- assign error_response = error_response | set_key: “message”, “Invalid quantity” -%} {%- assign error_response = error_response | set_key: “code”, “INVALID_QTY” -%}
{% respond body: error_response | json, status: 400, layout: false %} {% endbefore %} ```
Return success with data
```liquid
{% after %} {%- new Map success_response -%} {%- assign success_response = success_response | set_key: “status”, “success” -%} {%- assign success_response = success_response | set_key: “order_id”, current_cart.order_id -%} {%- assign success_response = success_response | set_key: “total”, current_cart.total -%}
{% respond body: success_response | json, status: 200, layout: false %} {% endafter %} ```
Related phases
{% before %}— use respond here to reject requests early{% after %}— use respond here to send custom data after rendering{% final %}— respond does not work in final (response already sent)- See Liquid controller lifecycle for the complete flow
Difference from redirect
{% respond %}— sends a custom response body and HTTP status; rendering stops{% redirect %}— sends a 302 (or custom status) redirect to a different URL- Use case — respond for custom content/JSON; redirect to send the user to a new page
Was this article helpful?
Thanks for your feedback! It helps us improve our docs.