Master Shopify Embedded Apps with Rails 8

Motivation After building several Shopify embedded apps, I've learned valuable lessons about what works (and what definitely doesn't) in the embedded app environment. Today, I'm sharing these insights to help you avoid common pitfalls and build better Shopify apps. The Challenge Building embedded apps for Shopify presents unique challenges - particularly around navigation, authentication, and user experience. One of the biggest pitfalls? Trying to use regular URL navigation in an embedded app context. Project Setup First, let's look at the proper configuration for a Shopify embedded app: # config/initializers/shopify_app.rb ShopifyApp.configure do |config| config.embedded_app = true config.new_embedded_auth_strategy = false config.scope = "read_customers,write_customers" config.api_version = "2024-10" # Webhook configuration config.webhooks = [ { topic: "app/uninstalled", address: "webhooks/app_uninstalled" }, { topic: "customers/create", address: "webhooks/customers_create" } ] end Do's and Don'ts ✅ DO: Use App Bridge for Navigation // app/javascript/shopify_app.js var AppBridge = window['app-bridge']; var createApp = AppBridge.default; window.app = createApp({ apiKey: data.apiKey, host: data.host, }); var actions = AppBridge.actions; var TitleBar = actions.TitleBar; TitleBar.create(app, { title: data.page, }); ❌ DON'T: Use Regular Rails Links Avoid using regular Rails link_to helpers without proper App Bridge handling: ✅ DO: Handle Authentication Properly class AuthenticatedController

Feb 6, 2025 - 07:13
 0
Master Shopify Embedded Apps with Rails 8

Motivation

After building several Shopify embedded apps, I've learned valuable lessons about what works (and what definitely doesn't) in the embedded app environment. Today, I'm sharing these insights to help you avoid common pitfalls and build better Shopify apps.

The Challenge

Building embedded apps for Shopify presents unique challenges - particularly around navigation, authentication, and user experience. One of the biggest pitfalls? Trying to use regular URL navigation in an embedded app context.

Project Setup

First, let's look at the proper configuration for a Shopify embedded app:

# config/initializers/shopify_app.rb
ShopifyApp.configure do |config|
  config.embedded_app = true
  config.new_embedded_auth_strategy = false
  config.scope = "read_customers,write_customers"
  config.api_version = "2024-10"

  # Webhook configuration
  config.webhooks = [
    { topic: "app/uninstalled", address: "webhooks/app_uninstalled" },
    { topic: "customers/create", address: "webhooks/customers_create" }
  ]
end

Do's and Don'ts

✅ DO: Use App Bridge for Navigation

// app/javascript/shopify_app.js
var AppBridge = window['app-bridge'];
var createApp = AppBridge.default;
window.app = createApp({
  apiKey: data.apiKey,
  host: data.host,
});

var actions = AppBridge.actions;
var TitleBar = actions.TitleBar;
TitleBar.create(app, {
  title: data.page,
});

❌ DON'T: Use Regular Rails Links

Avoid using regular Rails link_to helpers without proper App Bridge handling:

<%# Wrong way %>
<%= link_to "Settings", settings_path %>

<%# Right way %>
<%= link_to "Settings", settings_path(request.query_parameters) %>

✅ DO: Handle Authentication Properly

class AuthenticatedController < ApplicationController
  include ShopifyApp::EnsureHasSession

  before_action :verify_embedded_app_request

  private

  def verify_embedded_app_request
    if ShopifyAPI::Context.embedded? && 
       (!params[:embedded].present? || params[:embedded] != "1")
      redirect_to(ShopifyAPI::Auth.embedded_app_url(params[:host]).to_s + 
                 request.path, 
                 allow_other_host: true)
    end
  end
end

✅ DO: Implement Proper Flash Messages

# app/helpers/application_helper.rb
module ApplicationHelper
  def flash_class(type)
    case type.to_sym
    when :success, :notice
      "bg-green-50"
    when :error, :alert
      "bg-red-50"
    else
      "bg-blue-50"
    end
  end
end

✅ DO: Use Proper Layout for Embedded Apps

<%# app/views/layouts/embedded_app.html.erb %>

 lang="en">
  
    
    <%= csrf_meta_tags %>
    <%= javascript_importmap_tags %>
  
  
     id="app">
      <%= render 'shared/navbar' %>
      <%= yield %>
    
<% if flash[:notice].present? || flash[:error].present? %> <% end %>

❌ DON'T: Forget Query Parameters

When creating links or forms, always include the necessary query parameters:

# app/controllers/application_controller.rb
def maintain_query_parameters
  @query_parameters = request.query_parameters
end

✅ DO: Implement Proper Navigation

<%# app/views/shared/_navbar.html.erb %>
 class="bg-white border-b border-gray-200 fixed w-full z-50">
   class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
     class="flex justify-between h-16">
       class="hidden md:flex md:items-center md:space-x-6">
        <%= link_to "Home", 
            root_path(params.except(:action, :controller).permit!.to_h), 
            class: "text-gray-600 hover:text-gray-900 px-3 py-2" %>