docs/developer/admin/extending-ui.mdx
Spree Admin Dashboard allows you easily extend existing pages and screens with your own code, without any need to modify the core codebase. This allows you to easily inject your custom UI elements without compromising the integrity of the core codebase. Which in effect allows you to safely update your Spree installation to the latest version.
The entire system works on the basis of injection points which are declared throughout the admin dashboard and allows you to push your own code there. Each injection point is identified by a key, eg. body_end.
Let's say you want to add a new footer to the admin dashboard. You'll need to generate a template in your application:
Ensure you have the proper directory to store your templates:
mkdir -p app/views/spree/admin/shared
Create a new partial template file (partial templates file names start with underscore)
touch app/views/spree/admin/shared/_additional_footer.html.erb
Add your own code to the partial
<div class="mx-auto bg-light p-3 rounded-lg text-center w-10">
Copyright <%= current_store.name %> <%= Time.current.year %>
</div>
Register your partial in config/initializers/spree.rb
<Warning>
For older versions of Spree you need to add `_partials` suffix for all injection points,
eg. `body_end_partials` instead of `body_end`.
</Warning>
Restart your web server and you should see your new footer.
<Frame> </Frame> <Info> Making further changes to the partial template will not require you to restart the web server. They will be picked up automatically. </Info>The Spree.admin.partials object provides a clean API for registering partials to injection points. This API is available in Spree 5.2 and later.
You can list all available injection points programmatically:
# In Rails console or initializer
Spree.admin.partials.keys
# => ["head", "body_start", "body_end", "dashboard_analytics", "product_form", ...]
Each injection point is an array that you can append to:
# Add a single partial
Spree.admin.partials.product_form << 'spree/admin/products/erp_section'
# Add multiple partials
Spree.admin.partials.dashboard_sidebar << 'spree/admin/dashboard/analytics_widget'
Spree.admin.partials.dashboard_sidebar << 'spree/admin/dashboard/inventory_widget'
To see which partials are registered for a specific injection point:
Spree.admin.partials.product_form
# => ["spree/admin/products/erp_section"]
You can also replace all partials for an injection point:
Spree.admin.partials.product_form = ['my/custom/partial']
Here's a list of all places you can inject your custom code:
Injects code into the `<head>` tag
Injects code into the `<body>` tag, before the main content
Injects code into the `<body>` tag, after the main content
<Frame>
</Frame>
Injects code into the dashboard analytics section, eg.
```erb
<div class="card">
<div class="card-body">
<h5 class="card-title">Top ERP products</h5>
</div>
<div class="card-footer">
<%# ... my custom content ... %>
</div>
</div>
```
<Frame>
</Frame>
Injects code into the dashboard sidebar, eg.
```erb
<div class="card">
<div class="card-body">
<h5 class="card-title">Latest ERP syncs</h5>
</div>
<div class="card-footer">
<%# ... my custom content ... %>
</div>
</div>
```
Injects code into the page actions area (top right of the page) for the orders list page. This is useful for adding custom buttons, export options, or other actions.
```erb
<%= link_to "Export to ERP", export_orders_to_erp_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the orders list page. This is useful for adding notifications, alerts, or additional information.
```erb
<div class="alert alert-info">
<strong>Processing:</strong> Orders are automatically processed and shipped within 24 hours.
</div>
```
<Frame>
</Frame>
#### Variables
<ParamField path="f" type="Spree::Admin::FormBuilder">
The [Spree::Admin::FormBuilder](/developer/admin/form-builder) object.
</ParamField>
Injects code into the orders list filters, to add custom filters.
This partial has access to the `f` variable, which is the form builder for the filters, eg.
```erb
<%= f.spree_text_field :q_number_cont, data: { filters_target: :input } %>
```
<Tip>
* `q_number_cont` - The name of the filter field. For filtering we're using [ransack](/developer/core-concepts/search-filtering) gem, so the name of the filter field is the name of the attribute we're filtering by.
* `data: { filters_target: :input }` - Needed for the [Stimulus Filters controller](https://github.com/spree/spree/blob/main/admin/app/javascript/spree/admin/controllers/filters_controller.js) to work.
</Tip>
<Frame>
</Frame>
#### Variables
<ParamField path="order" type="Spree::Order">
The [Spree::Order](https://github.com/spree/spree/blob/main/core/app/models/spree/order.rb) object.
</ParamField>
Injects code into the order page dropdown. This partial has access to the `order` variable.
To add an additional dropdown item, you can use the following code:
```erb
<%= link_to "View Order in ERP", "https://erp.com/orders/#{order.number}", class: "dropdown-item", target: "_blank" %>
```
<Tip>
* `dropdown-item` is a CSS class for styling the dropdown item
* `target: "_blank"` is used to open the link in a new tab
</Tip>
<Frame>
</Frame>
#### Variables
<ParamField path="order" type="Spree::Order">
The [Spree::Order](https://github.com/spree/spree/blob/main/core/app/models/spree/order.rb) object.
</ParamField>
Injects code into the order page header.
To add an additional action button near the `...` button, you can use the following code:
<Frame>
</Frame>
Injects code into the order page header.
To add an additional action button near the `...` button, you can use the following code:
```erb
<%= content_for :page_actions do %>
<%= link_to "Send to ERP", "#", class: "btn btn-primary" %>
<% end %>
```
To add an inline alert to the order page, you can use the following code:
```erb
<%= content_for :page_alerts do %>
<% if order.sent_to_erp_at.blank? %>
<div class="alert alert-success">Order sent to ERP at <%= local_time(order.sent_to_erp_at) %></div>
<% else %>
<div class="alert alert-danger">Order not sent to ERP</div>
<% end %>
<% end %>
```
<Tip>
`local_time` is a helper for displaying the time in the user's timezone in a human readable **format** (based on the browser's timezone).
</Tip>
<Frame>
</Frame>
#### Variables
<ParamField path="order" type="Spree::Order">
The [Spree::Order](https://github.com/spree/spree/blob/main/core/app/models/spree/order.rb) object.
</ParamField>
Injects code into the order page body. This partial has access to the `order` variable.
To add a new section to the order page, you can use the following code:
```erb
<div class="card mb-6">
<div class="card-header">
<h5 class="card-title">ERP Integration</h5>
</div>
<div class="card-body">
<% if order.sent_to_erp_at.blank? %>
<p class="text-muted text-center">Order not sent to ERP</p>
<% else %>
<ul class="list-group list-group-flush">
<li class="list-group-item">
<strong>ERP Order ID:</strong> <%= order.erp_order_id %>
</li>
<li class="list-group-item">
<strong>Sent to ERP at:</strong> <%= local_time(order.sent_to_erp_at) %>
</li>
</ul>
<% end %>
</div>
</div>
```
<Frame>
</Frame>
#### Variables
<ParamField path="order" type="Spree::Order">
The [Spree::Order](https://github.com/spree/spree/blob/main/core/app/models/spree/order.rb) object.
</ParamField>
Injects code into the order page sidebar. This partial has access to the `order` variable.
Injects code into the page actions area (top right of the page) for the customers list page. This is useful for adding custom buttons, export options, or other actions.
```erb
<%= link_to "Sync with CRM", sync_customers_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the customers list page. This is useful for adding notifications, alerts, or additional information.
```erb
<div class="alert alert-info">
<strong>Note:</strong> Customer data is synced with CRM every hour.
</div>
```
#### Variables
<ParamField path="f" type="ActionView::Helpers::FormBuilder">
The [Spree::Admin::FormBuilder](/developer/admin/form-builder) object.
</ParamField>
Injects code into the customers list filters. This partial has access to the `f` variable, which is the form builder for the filters.
```erb
<%= f.spree_select :custom_field_eq, [["VIP", "vip"], ["Regular", "regular"]], { include_blank: true }, { data: { filters_target: :input } } %>
```
<Tip>
* Use [ransack](/developer/core-concepts/search-filtering) search syntax for filter field names
* Include `data: { filters_target: :input }` for proper integration with the Stimulus Filters controller
</Tip>
Injects code into the page actions area for the stock items list page.
```erb
<%= link_to "Export to WMS", export_stock_to_wms_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the stock items list page.
```erb
<div class="alert alert-warning">
<strong>Warning:</strong> Low stock items require attention.
</div>
```
#### Variables
<ParamField path="f" type="Spree::Admin::FormBuilder">
The [Spree::Admin::FormBuilder](/developer/admin/form-builder) object.
</ParamField>
Injects code into the stock items list filters.
```erb
<%= f.spree_number_field :count_on_hand_lt,
label: "Stock Below",
data: { filters_target: :input } %>
```
<Tip>
Use [ransack](/developer/core-concepts/search-filtering) search syntax for filter field names (e.g., `_lt` for "less than").
</Tip>
Injects code into the page actions area for the admin users list page.
```erb
<%= link_to "Export Users", export_admin_users_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the admin users list page.
```erb
<div class="alert alert-info">
<strong>Security:</strong> Review admin access regularly.
</div>
```
Injects code into the page actions area for the classifications list page.
```erb
<%= link_to "Bulk Update", bulk_update_classifications_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the classifications list page.
```erb
<div class="alert alert-info">
<strong>Tip:</strong> Use drag and drop to reorder classifications.
</div>
```
Injects code into the page actions area for the coupon codes list page.
```erb
<%= link_to "Generate Bulk Codes", bulk_generate_coupons_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the coupon codes list page.
```erb
<div class="alert alert-warning">
<strong>Notice:</strong> Expired codes will be automatically cleaned up.
</div>
```
Injects code into the page actions area for the custom domains list page.
```erb
<%= link_to "Verify All Domains", verify_all_domains_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the custom domains list page.
```erb
<div class="alert alert-info">
<strong>SSL:</strong> SSL certificates are automatically managed.
</div>
```
Injects code into the page actions area for the customer returns list page.
```erb
<%= link_to "Export Returns Report", export_returns_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the customer returns list page.
```erb
<div class="alert alert-info">
<strong>Processing:</strong> Returns are processed within 3-5 business days.
</div>
```
#### Variables
<ParamField path="f" type="Spree::Admin::FormBuilder">
The [Spree::Admin::FormBuilder](/developer/admin/form-builder) object.
</ParamField>
Injects code into the customer returns list filters.
```erb
<%= f.spree_select :reason_eq,
[["Damaged", "damaged"], ["Wrong Item", "wrong_item"]],
{ include_blank: true, label: "Return Reason" },
{ data: { filters_target: :input } } %>
```
<Tip>
Use [ransack](/developer/core-concepts/search-filtering) search syntax for filter field names (e.g., `_eq` for "equals").
</Tip>
Injects code into the page actions area for the digital assets list page.
```erb
<%= link_to "Bulk Upload", bulk_upload_assets_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the digital assets list page.
```erb
<div class="alert alert-info">
<strong>Storage:</strong> Assets are stored in cloud storage with CDN.
</div>
```
Injects code into the page actions area for the exports list page.
```erb
<%= link_to "Schedule Export", new_scheduled_export_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the exports list page.
```erb
<div class="alert alert-info">
<strong>Retention:</strong> Export files are kept for 30 days.
</div>
```
Injects code into the page actions area for the gift cards list page.
```erb
<%= link_to "Bulk Generate", bulk_generate_gift_cards_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the gift cards list page.
```erb
<div class="alert alert-info">
<strong>Security:</strong> Gift card codes are encrypted at rest.
</div>
```
#### Variables
<ParamField path="f" type="Spree::Admin::FormBuilder">
The [Spree::Admin::FormBuilder](/developer/admin/form-builder) object.
</ParamField>
Injects code into the gift cards list filters.
```erb
<%= f.spree_number_field :balance_gt,
label: "Balance Greater Than",
step: 0.01,
data: { filters_target: :input } %>
```
<Tip>
Use [ransack](/developer/core-concepts/search-filtering) search syntax for filter field names (e.g., `_gt` for "greater than").
</Tip>
Injects code into the page actions area for the integrations list page.
```erb
<%= link_to "Test All Connections", test_integrations_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the integrations list page.
```erb
<div class="alert alert-warning">
<strong>Status:</strong> Check integration health regularly.
</div>
```
Injects code into the page actions area for the invitations list page.
```erb
<%= link_to "Resend All Pending", resend_pending_invitations_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the invitations list page.
```erb
<div class="alert alert-info">
<strong>Expiry:</strong> Invitations expire after 7 days.
</div>
```
Injects code into the page actions area for the option types list page.
```erb
<%= link_to "Import Options", import_option_types_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the option types list page.
```erb
<div class="alert alert-info">
<strong>Variants:</strong> Option types are used to create product variants.
</div>
```
Injects code into the page actions area for the pages list page.
```erb
<%= link_to "Export Content", export_pages_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the pages list page.
```erb
<div class="alert alert-info">
<strong>SEO:</strong> Remember to optimize page content for search engines.
</div>
```
Injects code into the page actions area for the payment methods list page.
```erb
<%= link_to "Test All Gateways", test_payment_gateways_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the payment methods list page.
```erb
<div class="alert alert-warning">
<strong>Configuration:</strong> Ensure all payment methods are properly configured.
</div>
```
Injects code into the page actions area for the post categories list page.
```erb
<%= link_to "Reorder Categories", reorder_post_categories_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the post categories list page.
```erb
<div class="alert alert-info">
<strong>Organization:</strong> Use categories to organize your blog posts.
</div>
```
Injects code into the page actions area for the posts list page.
```erb
<%= link_to "Schedule Posts", schedule_posts_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the posts list page.
```erb
<div class="alert alert-info">
<strong>Publishing:</strong> Posts can be scheduled for future publication.
</div>
```
#### Variables
<ParamField path="f" type="Spree::Admin::FormBuilder">
The [Spree::Admin::FormBuilder](/developer/admin/form-builder) object.
</ParamField>
Injects code into the posts list filters.
```erb
<%= f.spree_select :published_eq,
[["Published", true], ["Draft", false]],
{ include_blank: true, label: "Publication Status" },
{ data: { filters_target: :input } } %>
```
<Tip>
Use [ransack](/developer/core-concepts/search-filtering) search syntax for filter field names.
</Tip>
Injects code into the page actions area for the promotions list page.
```erb
<%= link_to "Clone Selected", clone_promotions_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the promotions list page.
```erb
<div class="alert alert-info">
<strong>Scheduling:</strong> Promotions can be scheduled to start and end automatically.
</div>
```
#### Variables
<ParamField path="f" type="Spree::Admin::FormBuilder">
The [Spree::Admin::FormBuilder](/developer/admin/form-builder) object.
</ParamField>
Injects code into the promotions list filters.
```erb
<%= f.spree_select :active_eq,
[["Active", true], ["Inactive", false]],
{ include_blank: true, label: "Active Status" },
{ data: { filters_target: :input } } %>
```
<Tip>
Use [ransack](/developer/core-concepts/search-filtering) search syntax for filter field names.
</Tip>
Injects code into the page actions area for the properties list page.
```erb
<%= link_to "Import Properties", import_properties_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the properties list page.
```erb
<div class="alert alert-info">
<strong>Usage:</strong> Properties are used to add custom attributes to products.
</div>
```
Injects code into the page actions area for the refund reasons list page.
```erb
<%= link_to "Export Reasons", export_refund_reasons_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the refund reasons list page.
```erb
<div class="alert alert-info">
<strong>Analytics:</strong> Track refund reasons to identify common issues.
</div>
```
Injects code into the page actions area for the reimbursement types list page.
```erb
<%= link_to "Configure Defaults", configure_reimbursement_defaults_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the reimbursement types list page.
```erb
<div class="alert alert-info">
<strong>Processing:</strong> Define how customers are reimbursed for returns.
</div>
```
Injects code into the page actions area for the reports list page.
```erb
<%= link_to "Schedule Report", schedule_report_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the reports list page.
```erb
<div class="alert alert-info">
<strong>Automation:</strong> Reports can be scheduled to run automatically.
</div>
```
Injects code into the page actions area for the return authorization reasons list page.
```erb
<%= link_to "Export Reasons", export_return_reasons_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the return authorization reasons list page.
```erb
<div class="alert alert-info">
<strong>Policy:</strong> Define clear return reasons to streamline the process.
</div>
```
Injects code into the page actions area for the return authorizations list page.
```erb
<%= link_to "Bulk Process", bulk_process_returns_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the return authorizations list page.
```erb
<div class="alert alert-info">
<strong>Processing:</strong> Returns are processed in order of submission.
</div>
```
Injects code into the page actions area for the roles list page.
```erb
<%= link_to "Export Permissions", export_role_permissions_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the roles list page.
```erb
<div class="alert alert-warning">
<strong>Security:</strong> Review role permissions regularly for security.
</div>
```
Injects code into the page actions area for the shipping categories list page.
```erb
<%= link_to "Calculate Rates", calculate_shipping_rates_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the shipping categories list page.
```erb
<div class="alert alert-info">
<strong>Organization:</strong> Use categories to group products with similar shipping requirements.
</div>
```
Injects code into the page actions area for the shipping methods list page.
```erb
<%= link_to "Test Integrations", test_shipping_integrations_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the shipping methods list page.
```erb
<div class="alert alert-info">
<strong>Configuration:</strong> Ensure shipping methods are properly configured for all zones.
</div>
```
Injects code into the page actions area for the stock locations list page.
```erb
<%= link_to "Sync Inventory", sync_all_locations_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the stock locations list page.
```erb
<div class="alert alert-info">
<strong>Management:</strong> Stock locations help manage inventory across multiple warehouses.
</div>
```
Injects code into the page actions area for the stock transfers list page.
```erb
<%= link_to "Bulk Transfer", bulk_stock_transfer_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the stock transfers list page.
```erb
<div class="alert alert-info">
<strong>Tracking:</strong> All stock transfers are logged for audit purposes.
</div>
```
#### Variables
<ParamField path="f" type="Spree::Admin::FormBuilder">
The [Spree::Admin::FormBuilder](/developer/admin/form-builder) object.
</ParamField>
Injects code into the stock transfers list filters.
```erb
<%= f.spree_select :status_eq,
[["Pending", "pending"], ["Completed", "completed"]],
{ include_blank: true, label: "Transfer Status" },
{ data: { filters_target: :input } } %>
```
<Tip>
Use [ransack](/developer/core-concepts/search-filtering) search syntax for filter field names.
</Tip>
Injects code into the page actions area for the store credit categories list page.
```erb
<%= link_to "Set Default Category", set_default_credit_category_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the store credit categories list page.
```erb
<div class="alert alert-info">
<strong>Organization:</strong> Use categories to organize different types of store credits.
</div>
```
Injects code into the page actions area for the store credits list page.
```erb
<%= link_to "Bulk Issue Credits", bulk_issue_credits_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the store credits list page.
```erb
<div class="alert alert-info">
<strong>Management:</strong> Store credits can be issued for returns, promotions, or customer service.
</div>
```
Injects code into the page actions area for the tax categories list page.
```erb
<%= link_to "Update Tax Rates", update_all_tax_rates_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the tax categories list page.
```erb
<div class="alert alert-warning">
<strong>Compliance:</strong> Ensure tax categories comply with local regulations.
</div>
```
Injects code into the page actions area for the tax rates list page.
```erb
<%= link_to "Import Tax Updates", import_tax_updates_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the tax rates list page.
```erb
<div class="alert alert-warning">
<strong>Updates:</strong> Tax rates should be reviewed and updated regularly.
</div>
```
Injects code into the page actions area for the taxonomies list page.
```erb
<%= link_to "Rebuild Tree", rebuild_taxonomy_tree_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the taxonomies list page.
```erb
<div class="alert alert-info">
<strong>Navigation:</strong> Taxonomies are used to create product category navigation.
</div>
```
Injects code into the page actions area for the themes list page.
```erb
<%= link_to "Preview All", preview_all_themes_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the themes list page.
```erb
<div class="alert alert-info">
<strong>Customization:</strong> Themes control the visual appearance of your storefront.
</div>
```
Injects code into the page actions area for the webhooks subscribers list page.
```erb
<%= link_to "Test All Webhooks", test_all_webhooks_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the webhooks subscribers list page.
```erb
<div class="alert alert-warning">
<strong>Monitoring:</strong> Monitor webhook delivery status and failures.
</div>
```
Injects code into the page actions area for the zones list page.
```erb
<%= link_to "Import Zones", import_zones_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the zones list page.
```erb
<div class="alert alert-info">
<strong>Geography:</strong> Zones define geographic regions for shipping and taxation.
</div>
```
Injects code into the page actions area (top right of the page) for the products list page. This is useful for adding custom buttons, export options, or other actions.
```erb
<%= link_to "Sync with PIM", sync_products_path, class: "btn btn-secondary" %>
```
Injects code between the page header and the main content area for the products list page. This is useful for adding notifications, alerts, or additional information.
```erb
<div class="alert alert-info">
<strong>Inventory:</strong> Product inventory is synced with warehouse systems every 15 minutes.
</div>
```
<Frame>
</Frame>
#### Variables
<ParamField path="f" type="Spree::Admin::FormBuilder">
The [Spree::Admin::FormBuilder](/developer/admin/form-builder) object.
</ParamField>
Injects code into the products list filters. This partial has access to the `f` variable, which is the form builder for the filters.
To add a new filter field, you can use the following code:
```erb
<%= f.spree_text_field :q_name_cont, data: { filters_target: :input } %>
```
<Tip>
* `q_name_cont` is the name of the filter field. For filtering we're using [ransack](/developer/core-concepts/search-filtering) gem, so the name of the filter field is the name of the attribute we're filtering by.
* `data: { filters_target: :input }` is needed for the [Stimulus Filters controller](https://github.com/spree/spree/blob/main/admin/app/javascript/spree/admin/controllers/filters_controller.js) to work.
</Tip>
<Frame>
</Frame>
Injects code into the products page dropdown. This partial has access to the `product` variable.
To add an additional dropdown item, you can use the following code:
```erb
<%= link_to "View Product in WMS", "https://wms.com/products/#{product.id}", class: "dropdown-item", target: "_blank" %>
```
<Info>
Your code will be placed before the dropdown divider.
</Info>
<Frame>
</Frame>
#### Variables
<ParamField path="f" type="Spree::Admin::FormBuilder">
The [Spree::Admin::FormBuilder](/developer/admin/form-builder) object.
</ParamField>
<ParamField path="product" type="Spree::Product">
The [Spree::Product](https://github.com/spree/spree/blob/main/core/app/models/spree/product.rb) object.
</ParamField>
Injects code into the product form. This partial has access to the `f` variable, which is the form builder for the product form, and the `product` variable.
To add a new section to the product form, you can use the following code:
```erb
<div class="card mb-6">
<div class="card-header">
<h5 class="card-title">ERP Integration</h5>
</div>
<div class="card-body">
<%= f.spree_text_field :erp_product_id %>
</div>
</div>
```
<Info>
The partial will be displayed for both new product form and edit product form.
</Info>
<Tip>
If you want to display the partial only on the edit product form, you can use the following code:
```erb
<% if product.persisted? %>
<%# ... your code ... %>
<% end %>
```
And similarly for the new product form.
```erb
<% if product.new_record? %>
<%# ... your code ... %>
<% end %>
```
</Tip>
<Frame>
</Frame>
#### Variables
<ParamField path="f" type="Spree::Admin::FormBuilder">
The [Spree::Admin::FormBuilder](/developer/admin/form-builder) object.
</ParamField>
<ParamField path="product" type="Spree::Product">
The [Spree::Product](https://github.com/spree/spree/blob/main/core/app/models/spree/product.rb) object.
</ParamField>
Injects code into the product form sidebar. This partial has access to the `f` variable, which is the form builder for the product form, and the `product` variable.
To add a new section to the product form sidebar, you can use the following code:
```erb
<div class="card mb-6">
<div class="card-header">
<h5 class="card-title">ERP Integration</h5>
</div>
<div class="card-body">
<%= f.spree_text_field :erp_product_id %>
</div>
</div>
```
<Info>
The partial will be displayed for both new product form and edit product form.
</Info>
<Tip>
If you want to display the partial only on the edit product form, you can use the following code:
```erb
<% if product.persisted? %>
<%# ... your code ... %>
<% end %>
```
And similarly for the new product form.
```erb
<% if product.new_record? %>
<%# ... your code ... %>
<% end %>
```
</Tip>
#### Variables
<ParamField path="f" type="Spree::Admin::FormBuilder">
The [Spree::Admin::FormBuilder](/developer/admin/form-builder) object.
</ParamField>
<ParamField path="shipping_method" type="Spree::ShippingMethod">
The [Spree::ShippingMethod](https://github.com/spree/spree/blob/main/core/app/models/spree/shipping_method.rb) object.
</ParamField>
Injects code into the shipping method form. This partial has access to the `f` variable, which is the form builder for the shipping method form, and the `shipping_method` variable.
To add a new section to the shipping method form, you can use the following code:
```erb
<div class="card mb-6">
<div class="card-header">
<h5 class="card-title">ERP Integration</h5>
</div>
<div class="card-body">
<%= f.spree_text_field :erp_shipping_method_id %>
</div>
</div>
```
<Frame>
</Frame>
#### Variables
<ParamField path="f" type="Spree::Admin::FormBuilder">
The [Spree::Admin::FormBuilder](/developer/admin/form-builder) object.
</ParamField>
<ParamField path="store" type="Spree::Store">
The [Spree::Store](https://github.com/spree/spree/blob/main/core/app/models/spree/store.rb) object.
</ParamField>
Injects code into the store settings form. This partial has access to the `f` variable, which is the form builder for the store form, and the `store` variable.
To add a new section to the store form, you can use the following code:
```erb
<div class="card mb-6">
<div class="card-header">
<h5 class="card-title">ERP Integration</h5>
</div>
<div class="card-body">
<%= f.spree_text_field :erp_store_id %>
</div>
</div>
```