Shopify App With Laravel, InertiaJs, and Polaris

Faizan Aalam
9 min readDec 30, 2021

--

Shopify embedded apps are the best way to extend the existing functionality of Shopify to solve the merchant problems at scale, they have extensible platforms and APIs which can be used to build your app. You can also pull Shopify store data through their APIs into your app. this article is about how one can build the Shopify app with Laravel, InertiaJs, and Polaris.

Laravel

Laravel is a free, open-source PHP web framework, created by Taylor Otwell and intended for the development of web applications following the model–view–controller (MVC) architectural pattern and based on Symfony. Let’s start by creating a fresh copy of Laravel (if you are new to the Laravel check out their documentation for getting started).

composer create-project laravel/laravel laravel-shopify-app

This will create a laravel-shopify-app directory, cd the project directory as cd laravel-shopify-app and serve the application as php artisan serve, if you are using Laravel Valet then run valet link to serve your Laravel application if it's not already in the parked folder, make sure to secure the site with valet secure also.

Laravel Breeze

We also have to install Laravel Breeze, it is a minimal, simple implementation of all of Laravel’s authentication features, including login, registration, password reset, email verification, and password confirmation but we are not going to use any of this authentication scaffolding, on the other hand, it also offers an Inertia.js frontend implementation powered by VueJS or ReactJS and exactly this is why we are using this package, let’s install this package.

composer require laravel/breeze --dev

This command will install Laravel Breeze as a dev dependency in our project, after this, we also have to install the InertiaJs implementation with React JS scaffolding.

php artisan breeze:install react

This command will publish all the assets including authentication views, routes, and controllers, you can delete all this which is not required, you can see the ReactJS component and other related stuff in the resources/js/ directory. After this run npm install command to install all of the required npm packages and then run npm run dev to build the npm assets.

Laravel Shopify Integration

Now it's time to start with Shopify integration, we are using osiset/laravel-shopify it's a full-featured Laravel package for aiding in Shopify App development and it’ll work for Laravel 7 and up, run the below command to add it to the project.

composer require osiset/laravel-shopify

We also have to publish its configuration to our project,

php artisan vendor:publish --tag=shopify-config

This command creates a config file as shopify-app.php in config directory, we also need to provide the app_name, api_key, api_secret, and api_scopes to generate a working app.

Shopify App Configuration

Log in to your Shopify dev account, and then click on Apps in the sidebar menu, go ahead and click on Create App button at the top right side, you will be redirected to Create App page.

In the create app page select Public App and then fill in the form as,

  1. App Name: your Shopify app name
  2. App URL: https://<domain>, e.g https://laravel-shopify-app.test
  3. Allowed redirection URL(s): https://<domain>/authenticate, e.g https://laravel-shopify-app.test/authenticate
create app in shopify dev
Screenshot for creating Shopify app in Shopify.dev

you can also use ngrok if you are not using the Laravel valet

Now, click on Create App button at the top right corner, you will be redirected to the created app page, at the left side, you can see App keys and secret, copy and paste this App key and secret in Laravel’s .env file as,

SHOPIFY_API_KEY=shopify-api-key-here
SHOPIFY_API_SECRET=shopify-api-secret-here

Now, open web.php file and replace / (root) route with the following.

Route::get('/', function () {
return view('welcome');
})->middleware(['verify.shopify'])->name('home');

After this open App\Models\User.php (user model) and add the highlighted code to it.

<?phpnamespace App\Models;use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Osiset\ShopifyApp\Contracts\ShopModel as IShopModel;
use Osiset\ShopifyApp\Traits\ShopModel;
class User extends Authenticatable implements IShopModel
{
use HasApiTokens, HasFactory, Notifiable, ShopModel;
..........
..........
}

Make sure to configure the .env file for the database and then run migrations as php artisan migrate.

If you try to browse the app in the browser you’ll get the error Call to a member function getDomain() on null and that's ok.

Testing the App on Shopify

In the app details page in Shopify, click on More actions and then select Test on development store

testing the app on a Shopify development store

It’ll redirect you to a new page where you can select a previously created store or you can create a new one, while creating a new store just fill in the form and select development store and while choosing the previously created store click on a store to install the app in it, in next page you can click on Install unlisted app it’ll install the app in the development store on then you can see the Laravel welcome page.

installing the Shopify app in a development store

InertiaJS and ReactJS

Laravel integration to Shopify is done, now let's work on React part of our application, we already have a Welcome.js page in the resources\js\pages directory, let’s render this page from InertiaJs, open web.php and make the changes as follows,

// Route::get('/', function () {
// return view('welcome');
// })->middleware(['verify.shopify'])->name('home');
Route::get('/', function () {
return Inertia::render('Welcome');
})->middleware(['verify.shopify'])->name('home');

now open resources\js\pages\Welcome.js file and replace it as follows

import React from 'react';
import { Link, Head } from '@inertiajs/inertia-react';
export default function Welcome(props) {
return (
<>
<Head title="Welcome" />
<div className="relative flex items-top justify-center min-h-screen bg-gray-100 dark:bg-gray-900 sm:items-center sm:pt-0">
<div className="max-w-6xl mx-auto sm:px-6 lg:px-8">
Welcome to shopify
</div>
</div>
</>
);
}

just refresh the Shopify app page and you can see the changes, ReactJs part of our page has been done.

Shopify Polaris

Shopify Polaris is a ReactJS component library designed to help developers create the best experience for merchants who use Shopify, we need to install the npm package for this also, run the below command in the Laravel project root.

npm install @shopify/polaris --save

Now, we have to import the Polaris CSS (comes with the Polaris package) in our project, open resources/js/app.js make changes as follows

require('./bootstrap');import React from 'react';
import { render } from 'react-dom';
import { createInertiaApp } from '@inertiajs/inertia-react';
import { InertiaProgress } from '@inertiajs/progress';

import '@shopify/polaris/build/esm/styles.css';
............
............

It’s time to see some Shopify Polaris components in action, open the Welcome.js, and update as follows, you can see all of the Polaris components here.

import React from 'react';
import enTranslations from '@shopify/polaris/locales/en.json';
import {Page, Card, Button, AppProvider} from '@shopify/polaris';
const Welcome = ({ user }) => {
return (
<>
<AppProvider i18n={enTranslations}>
<Page title="Inertia App">
<Card title={ user.name } sectioned>
<Button
primary
onClick
={() => {alert("I am here")} }
>
Click Me
</Button>
</Card>
</Page>
</AppProvider>
</>

);
}
export default Welcome;

Make sure the npm run watch is running, and then reload the Shopify app page, if everything works as expected you’ll see something like this,

Shopify App Page with Polaris and React Component

We are using four components from Shopify Polaris as Page, Card, Button, and AppProvider, the AppProvider is a required component that enables sharing global settings throughout the hierarchy of our application, note that the Polaris ReactJS components will not function without it.

We already know that the AppProvider component is a must in all our pages, so instead of adding it to all the pages again and again we can create a site layout that all of our pages can extend, we already have a Layouts folder in our application (thanks to Laravel Breeze), let's create a new Shopified.js file in this folder and add the code as given below, it’ll be our site layout.

import React from 'react'
import '@shopify/polaris/build/esm/styles.css';
import enTranslations from '@shopify/polaris/locales/en.json';
import {AppProvider} from '@shopify/polaris';
export default function Layout({ children }) {
return (
<main>
<AppProvider i18n={enTranslations}>
{children}
</AppProvider>
</main>
)
}

You can also remove import ‘@shopify/polaris/build/esm/styles.css’; line (we have added earlier) from app.js file.

Now we have to update our Welcome.js file to use our new site layout. let's make some updates to it:

import React from 'react';
import Shopified from "../Layouts/Shopified";
import {Page, Card, Button} from '@shopify/polaris';
const Welcome = ({ user }) => {
return (
<>
<Page title="Inertia App">
<Card title={ user.name } sectioned>
<Button
primary
onClick
={() => {alert("I am here")} }
>
Click Me
</Button>
</Card>
</Page>
</>

);
}
Welcome.layout = page => <Shopified children={page} title="Welcome"/>
export default Welcome;

That’s it we have made it to the end, we used Laravel to build the Shopify app with ReactJs and Polaris Components but there is one more thing I want to add to this article, to understand it let's send a post request from the ReactJs page to the Laravel backend.

First, we have to create a post route in web.php file to handle the post request, update the code as follows,

Route::middleware(['verify.shopify'])->group(function () {
Route::get('/', function () {
return Inertia::render('Welcome');
});
Route::post('/', function() {
dd("its working");
});
});

Now we have to make some changes in Welcome.js file to send a post request to the Laravel, update it as follows

import React from 'react';
import Shopified from "../Layouts/Shopified";
import {Page, Card, Button} from '@shopify/polaris';
import { Inertia } from '@inertiajs/inertia';
const Welcome = ({ user }) => { function handleSubmit(e) {
e.preventDefault()
Inertia.post('/')
}
return (
<>
<Page title="Inertia App">
<Card title={ user.name } sectioned>
<Button
primary
onClick
={handleSubmit}
>
Click Me
</Button>
</Card>
</Page>
</>
);
}
Welcome.layout = page => <Shopified children={page} title="Welcome" />
export default Welcome;

I’ve added another function to handle the button click, in this function we are using the InertiaJs’s post method to send the post request, check if npm run watch is running, if working then reload the page in Shopify and click on the Click Me button, It’ll send the post request to the Laravel backend, but instead of a successful response, it’ll say that the page is expired, this is because of CSRF. We just have to make some changes to the project to make things work, Let’s dig into this.

Sending Post Request

Open the app.blade.php file from resources/views folder and make changes as follows

....
.......
<body class="font-sans antialiased">
@inertia
@env ('local')
<script src="http://localhost:8080/js/bundle.js"></script>
@endenv
@if( \Osiset\ShopifyApp\Util::getShopifyConfig('appbridge_enabled') )
<script src="https://unpkg.com/@shopify/app-bridge{{ \Osiset\ShopifyApp\Util::getShopifyConfig('appbridge_version') ? '@'.config('shopify-app.appbridge_version') : '' }}"></script>
<script src="https://unpkg.com/@shopify/app-bridge-utils{{ \Osiset\ShopifyApp\Util::getShopifyConfig('appbridge_version') ? '@'.config('shopify-app.appbridge_version') : '' }}"></script>

<script
@if( \Osiset\ShopifyApp\Util::getShopifyConfig('turbo_enabled') )
data-turbolinks-eval="false"
@endif
>
var AppBridge = window['app-bridge'];
var actions = AppBridge.actions;
var utils = window['app-bridge-utils'];
var createApp = AppBridge.default;
var app = createApp({
apiKey: "{{ \Osiset\ShopifyApp\Util::getShopifyConfig('api_key', $shopDomain ??Auth::user()->name ) }}", shopOrigin: "{{ $shopDomain ?? Auth::user()->name }}",
host: "{{ \Request::get('host') }}",
forceRedirect: true,
});
</script>
@include('shopify-app::partials.token_handler')
@include('shopify-app::partials.flash_messages')
@endif
</body>
....
......

Now we have to do one more thing, open session.php from config folder and find SESSION_SECURE_COOKIE and replace the whole line as

.....
.......
‘secure’ => env(‘SESSION_SECURE_COOKIE’, true),.......
.....

Now reload the Shopify page and send the request again by clicking on the button and magic!!! it’s working, yes we are done here for now but it’s the beginning, not the end.

Github Repository

Conclusion

Shopify is the leading platform for e-commerce and it has an extensible platform, APIs, and developer tools that help you design apps that solve merchant problems at scale, on other hand, Laravel is a very good framework to build flexible and scalable applications, with the help of InertiaJs framework with Laravel we can build modern single page application with ReactJs, Vuejs, and Svelte, hence in this article we have used these three technologies together to build a demo app for Shopify.

--

--