Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 14 additions & 12 deletions config/shopify.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,6 @@
*/
'storefront_token' => env('SHOPIFY_STOREFRONT_TOKEN'),

/**
* Admin API Auth Key
*/
'auth_key' => env('SHOPIFY_AUTH_KEY'),

/**
* Admin API Auth Password
*/
'auth_password' => env('SHOPIFY_AUTH_PASSWORD'),

/**
* Admin Access Token
*/
Expand Down Expand Up @@ -56,7 +46,7 @@
/**
* Admin API version - Set this to a fixed value (eg 2023-07) or null to let the library decide
*/
'api_version' => env('SHOPIFY_API_VERSION', null),
'api_version' => env('SHOPIFY_API_VERSION', '2025-04'),

/**
* Admin connection is a private app, defaults to false
Expand All @@ -80,7 +70,7 @@
* Asset Container to Store the imported Assets
*/
'asset' => [
'path' => env('SHOPIFY_ASSET_PATH', 'shopify'),
'path' => env('SHOPIFY_ASSET_PATH', ''),
'container' => env('SHOPIFY_ASSET_CONTAINER', 'shopify'),
],

Expand Down Expand Up @@ -137,4 +127,16 @@
* (ensure this matches exactly)
*/
'sales_channel' => env('SHOPIFY_SALES_CHANNEL', 'Online Store'),

/**
* Your App's Admin API Auth Key
* Note: this is not required unless you are doing custom integrations using the RestApi
*/
'auth_key' => env('SHOPIFY_AUTH_KEY', 'api-key'),

/**
* Admin API Auth Password
* Note: this is not required unless you are doing custom integrations using the RestApi
*/
'auth_password' => env('SHOPIFY_AUTH_PASSWORD', 'api-password'),
];
2 changes: 1 addition & 1 deletion docs/content/en/CMS/customers.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ If you want Shopify and Statamic to sync users and customers you need to change

## Link Statamic customers from Shopify

To create a link between Shopify customers and Statamic users you need to ensure your Shopify app has `customer read` and `customer write` permissions.
To create a link between Shopify customers and Statamic users you need to ensure your Private Shopify app has `customer read` and `customer write` permissions.

You then need to set up the following webhooks:

Expand Down
1 change: 1 addition & 0 deletions docs/content/en/CMS/webhooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ There is a built method to listen for webhooks sent by Shopify back to your appl
3. Scroll down to **Webhooks** and click **Create Webhook**
4. Enter the URL as shown in the sections below.
5. Leave the type as `JSON` and on the latest API.
6. If this is your first webhook, you will be provided a secret which you should add to your .env as `SHOPIFY_WEBHOOK_SECRET`

<alert type="info">

Expand Down
39 changes: 23 additions & 16 deletions docs/content/en/env.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,22 @@ position: 3

## Required For Admin

| Value | Description |
| -------------------| ------------- |
| `SHOPIFY_APP_URL` | The url to your store (no https://) |
| `SHOPIFY_ADMIN_TOKEN` | The Admin API access token you received when generating your app |
| `SHOPIFY_AUTH_KEY` | The Admin API key found when creating your private app |
| `SHOPIFY_AUTH_PASSWORD` | The Admin API password found when creating your private app |
| Value | Description |
| -------------------|-----------------------------------------------------------------------------------------------------------------------------|
| `SHOPIFY_APP_URL` | The url to your store (no https://) |
| `SHOPIFY_ADMIN_TOKEN` | The Admin API access token you received when generating your app |
| `SHOPIFY_AUTH_KEY` | The Admin API key found when creating your private app. This is optional and only required if you want to use the REST API. |
| `SHOPIFY_AUTH_PASSWORD` | The Admin API password found when creating your private app. This is optional and only required if you want to use the REST API. |

## Required For Frontend

If you are using the JavaScript publishable in the addon you'll need to set the following.

| Value | Description |
| -------------------| ------------- |
| `SHOPIFY_APP_URL` | The url to your myshopify.com store (no https://) |
| `SHOPIFY_STOREFRONT_URL` | The custom url to your store if you have one (no https://) |
| `SHOPIFY_STOREFRONT_TOKEN` | Found when enabling the Storefront API whilst creating your private app |
| Value | Description |
| -------------------|-------------------------------------------------------------------------------------------------------------------|
| `SHOPIFY_APP_URL` | The url to your myshopify.com store (no https://) |
| `SHOPIFY_STOREFRONT_URL` | The custom url to your store if you have one (no https://) |
| `SHOPIFY_STOREFRONT_TOKEN` | Found in the configuration section of your Headless Sales Channel |

## Required For Webhooks

Expand All @@ -35,8 +35,15 @@ If you are using the webhook handlers you'll need the following.

These allow you to tweak how the system works. Please check out the `config/shopify.php` for a full list of options.

| Value | Description |
| -------------------|-------------------------------------------------------------------------------------------------|
| `SHOPIFY_JOB_QUEUE` | The queue to run the shopify jobs on. Allows you to set it to a different one than the default. |
| `SHOPIFY_COLLECTION_HANDLE` | The handle of the collection that contains your Shopify products, defaults to 'products'. |
| `SHOPIFY_SALES_CHANNEL` | The Sales Channel to use for product availability, defaults to 'Online Store'. |
| Value | Description |
|---------------------------|-------------------------------------------------------------------------------------------------|
| `SHOPIFY_API_VERSION` | The version of the storefront and admin APIs you want to target (defaults to '2025-04'). |
| `SHOPIFY_ASSET_CONTAINER` | The asset container you want to use to store assets (defaults to 'shopify') |
| `SHOPIFY_ASSET_PATH` | The path in the container you want to use to store assets (defaults to ''). |
| `SHOPIFY_COLLECTION_HANDLE` | The handle of the collection that contains your Shopify products, defaults to 'products'. |
| `SHOPIFY_JOB_QUEUE` | The queue to run the shopify jobs on. Allows you to set it to a different one than the default. |
| `SHOPIFY_SALES_CHANNEL` | The Sales Channel to use for product availability, defaults to 'Online Store'. |
| `SHOPIFY_TAXONOMY_COLLECTIONS` | The taxonomy handle to use for shopify collections (defaults to 'collections'). |
| `SHOPIFY_TAXONOMY_TAGS` | The taxonomy handle to use for 'tags' of product (defaults to 'tags'). |
| `SHOPIFY_TAXONOMY_TYPE` | The taxonomy handle to use for 'types' of product (defaults to 'type'). |
| `SHOPIFY_TAXONOMY_VENDOR` | The taxonomy handle to use for 'vendors' of product (defaults to 'vendor'). |
41 changes: 33 additions & 8 deletions docs/content/en/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,52 @@ composer require statamic-rad-pack/shopify

If you are on a Windows environment, please set the `SHOPIFY_SESSION_STORAGE_PATH` .env value to a writeable path.

## Creating a Shopify App

To set up a private app on Shopify for this add-on to use, use the following steps:
### Step 1: Using Shopify's Headless app for front end Storefront integration

In you are using the front end code to access the Storefront API we recommend you set up [Shopify's Headless](https://apps.shopify.com/headless) on your store. This app lets you create a new sales channel that you can use to determine which of your products are available on your Statamic site.

Once you have installed the app you should create a new sales channel, with a meaningful name (eg "Statamic").

In the Sales Channel Credentials screen you should now be able to copy your keys as follows:

```bash
SHOPIFY_APP_URL="your-store.myshopify.com"
SHOPIFY_STOREFRONT_TOKEN="{Public access token}"
SHOPIFY_SALES_CHANNEL="{Sales channel name}"
```


### Step 2: Create a private app for Admin API integration
Set up a private app on Shopify for this add-on using the following steps:

1. Visit the "Apps" section in your Shopify admin by clicking on the sidebar menu link, then in the modal that appears "App and sales channel settings".
2. Click "Develop Apps" in the top right.
3. Click "Create an app" in the top right to make a new one.
4. Set a nice name to remember as well as your email.
4. Set a nice name to remember (eg "Statamic Admin") as well as your email.
5. Click the "Configuration" Tab.
1. Click "Configure" next to Admin API Integration.
2. Enable `read_inventory`, `read_metaobjects`, `read_orders`, `read_products`, `read_product_listings`, `read_publications`, `read_translations` and `write_customers`
3. Click "Configure" next to Storefront API Integration.
4. Enable `unauthenticated_read_product_listings`, `unauthenticated_read_product_tags`, `unauthenticated_read_product_inventory`, `unauthenticated_write_customers`, `unauthenticated_write_checkouts`, `unauthenticated_read_customers`, `unauthenticated_read_checkouts`, `unauthenticated_read_metaobjects`
5. Click "Save" in the top right.
6. Click the "API Credentials" tab. Add the `Admin API access token` to your `.env` as `SHOPIFY_ADMIN_TOKEN`, add `API key` as `SHOPIFY_AUTH_KEY`, add `API secret key` as `SHOPIFY_AUTH_PASSWORD`, and add `Storefront API access token` as `SHOPIFY_STOREFRONT_TOKEN`.
6. Click the "API Credentials" tab. Add the `Admin API access token` to your `.env` as `SHOPIFY_ADMIN_TOKEN`.
7. If you've configured the app properly you should see a button that says "Install App". Click this.

### 3. Shopfront redirection
If you are not intending to use the Shopify storefront you should perform redirection from any Shopify URLs to your website.

We recommend installing Shopify's [Hydrogen Redirect Theme](https://github.com/Shopify/hydrogen-redirect-theme), and following their setup instructions.

## Environment Variables
### 4. Finalise your .env
After completing steps 1 and 2 your .env should look as follows:

```bash
SHOPIFY_APP_URL="your-store.myshopify.com"
SHOPIFY_STOREFRONT_TOKEN="{Public access token}"
SHOPIFY_SALES_CHANNEL="{Sales channel name}"
SHOPIFY_ADMIN_TOKEN="{Admin API access token}"
```

Ensure you've set the necessary environment variables as defined in the ["Env Values"](/env) section.
You may also wish to add some of the option values defined in the ["Env Values"](/env) section.

## Publishable Assets

Expand Down
1 change: 0 additions & 1 deletion src/Jobs/ImportSingleProductJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,6 @@ public function handle()

$entry->set(config('shopify.taxonomies.collections'), $collections)->save();
} catch (\Throwable $e) {
dd($e);
Log::error('Could not retrieve collections for product '.$this->data['id']);
Log::error($e->getMessage());
}
Expand Down
6 changes: 3 additions & 3 deletions src/ServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,17 +162,17 @@ private function createNavigation(): void

private function setShopifyApiConfig(): void
{
if (! $key = config('shopify.auth_key')) {
if (! $key = config('shopify.admin_token')) {
return;
}

Context::initialize(
apiKey: $key,
apiKey: config('shopify.auth_key'),
apiSecretKey: config('shopify.auth_password'),
scopes: ['read_metaobjects', 'read_products'],
hostName: config('shopify.url'),
sessionStorage: new FileSessionStorage(config('shopify.session_storage_path', '/tmp/php_sessions')),
apiVersion: config('shopify.api_version') ?? '2025-04',
apiVersion: config('shopify.api_version'),
isEmbeddedApp: false,
isPrivateApp: config('shopify.api_private_app') ?? false,
);
Expand Down
2 changes: 1 addition & 1 deletion src/Tags/Shopify.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public function productPrice()
public function tokens()
{
return "<script>
window.shopifyConfig = { url: '".(config('shopify.storefront_url') ?? config('shopify.url'))."', token: '".config('shopify.storefront_token')."', apiVersion: '".(config('shopify.api_version') ?? '2024-07')."' };
window.shopifyConfig = { url: '".(config('shopify.storefront_url') ?? config('shopify.url'))."', token: '".config('shopify.storefront_token')."', apiVersion: '".config('shopify.api_version')."' };
</script>";
}

Expand Down
4 changes: 2 additions & 2 deletions src/Traits/SavesImagesAndMetafields.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ private function importImages(array $image)
// Check if it exists first - no point double importing.
$asset = Asset::query()
->where('container', config('shopify.asset.container'))
->where('path', config('shopify.asset.path').'/'.$name)
->where('path', Str::replaceStart(config('shopify.asset.path').'/', '/', '').$name)
->first();

if ($asset) {
Expand Down Expand Up @@ -104,7 +104,7 @@ private function cleanupFakeFile(string $name): void
*/
private function getPath(UploadedFile $file): string
{
return Path::assemble(config('shopify.asset.path').'/', $file->getClientOriginalName());
return Path::assemble(config('shopify.asset.path'), $file->getClientOriginalName());
}

/**
Expand Down
2 changes: 1 addition & 1 deletion tests/Unit/TagsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public function outputs_shopify_tokens()
config()->set('shopify.storefront_token', '1234');

$this->assertEquals(str_replace(["\r", "\n"], '', "<script>
window.shopifyConfig = { url: 'abcd', token: '1234', apiVersion: '2024-07' };
window.shopifyConfig = { url: 'abcd', token: '1234', apiVersion: '2025-04' };
</script>"),
str_replace(["\r", "\n"], '', $this->tag('{{ shopify:tokens }}'))
);
Expand Down