Skip to main content

Interacting with Shopify Admin

Learn how to authenticate and handle requests from Shopify Admin in your React Router app.

The authenticate.admin function handles authentication for embedded apps and merchant custom apps. It verifies app installation and provides context for interacting with the Admin API.

This guide covers authentication patterns, API usage, and request handling for your app.


Anchor to authAuthenticating requests

To authenticate admin requests you can call authenticate.admin(request) in a loader or an action.

If there's a session for this user, then this loader will return null. If there's no session for the user, then the package will perform token exchange and create a new session.

Tip

If you are authenticating more than one route, then we recommend using React router layout routes to automatically authenticate them.

Authenticating requests

/app/routes/**/*.tsx

import {LoaderFunction, ActionFunction} from 'react-router';

import {authenticate} from '~/shopify.server';

export const loader: LoaderFunction = async ({request}) => {
await authenticate.admin(request);

// App logic

return null;
};

export const action: ActionFunction = async ({request}) => {
await authenticate.admin(request);

// App logic

return null;
};

When redirecting outside the app, and in certain error scenarios, the package will throw a response with specific headers.

To ensure the headers are set correctly use the provided ErrorBoundary and headers exports.

Configure headers and error boundaries

/app/routes/**/*.tsx

import {useRouteError} from 'react-router';
import {boundary} from '@shopify/shopify-app-react-router';

export function ErrorBoundary() {
return boundary.error(useRouteError());
}

export const headers = (headersArgs) => {
return boundary.headers(headersArgs);
};

Anchor to graphql-apiUsing the GraphQL API

Once a request is authenticated, authenticate.admin will return an admin object that contains a GraphQL client that can interact with the GraphQL Admin API.

Make GraphQL requests

/app/routes/**/*.tsx

import {ActionFunction} from 'react-router';

import {authenticate} from '../shopify.server';

export const action: ActionFunction = async ({request}) => {
const {admin} = await authenticate.admin(request);

const response = await admin.graphql(
`#graphql
mutation populateProduct($input: ProductInput!) {
productCreate(input: $input) {
product {
id
}
}
}`,
{
variables: {
input: {
title: 'New product',
variants: [{price: 100}],
},
},
},
);
const parsedResponse = await response.json();

return {data: parsedResponse.data};
};

Anchor to cors-authAuthenticating cross-origin admin requests

If your React Router server is authenticating an admin extension, then a request from the extension to the server will be cross-origin.

Here authenticate.admin provides a cors function to add the required cross-origin headers.

Add cross-origin headers

/app/routes/**/*.tsx

import {LoaderFunction} from 'react-router';

import {authenticate} from '~/shopify.server';

export const loader: LoaderFunction = async ({request}) => {
const {cors} = await authenticate.admin(request);

// App logic

return cors({my: 'data'});
};

Anchor to graphql-api-backgroundUsing the GraphQL API in background jobs

You may need to interact with the Admin API when working outside of Shopify requests. To do so use the unauthenticated.admin function.

This enables apps to integrate with 3rd party services and perform background tasks.

Caution

This function doesn't perform any validation and shouldn't rely on raw user input.

When using this function, consider the following:

Background tasks

Apps should ensure that the shop domain is authenticated when enqueueing jobs.

3rd party service requests

Apps must obtain the shop domain from the 3rd party service in a secure way.

Make GraphQL requests in background jobs

/app/jobs/**/*.tsx

// /background-jobs/**/*.ts
import { unauthenticated } from "../shopify.server";

// Background job set up

const shop = 'mystore.myshopify.com'
const { admin } = await unauthenticated.admin(shop);

const response = await admin.graphql(
`#graphql
mutation populateProduct($input: ProductInput!) {
productCreate(input: $input) {
product {
id
}
}
}
`,
{ variables: { input: { title: "Product Name" } } }
);

const productData = await response.json();

// Background job complete