---
title: Unauthenticated storefront
description: >-
Allows interacting with the Storefront API when working outside of Shopify
requests.
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.
api_version: v3
api_name: shopify-app-remix
source_url:
html: >-
https://shopify.dev/docs/api/shopify-app-remix/v3/unauthenticated/unauthenticated-storefront
md: >-
https://shopify.dev/docs/api/shopify-app-remix/v3/unauthenticated/unauthenticated-storefront.md
---
# Unauthenticated storefront
Allows interacting with the Storefront API when working outside of Shopify requests. 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.
## unauthenticated.storefront(**[shop](#unauthenticatedstorefront-propertydetail-shop)**)
Creates an unauthenticated Storefront context.
### Parameters
* **shop**
**string**
**required**
### Returns
* **Promise\**
### UnauthenticatedStorefrontContext
* session
The session for the given shop. This comes from the session storage which \`shopifyApp\` uses to store sessions in your database of choice. This will always be an offline session. You can use this to get shop specific data.
```ts
Session
```
* storefront
Method for interacting with the Shopify GraphQL Storefront API for the given store.
```ts
StorefrontContext
```
### StorefrontContext
* graphql
Method for interacting with the Shopify Storefront GraphQL API If you're getting incorrect type hints in the Shopify template, follow \[these instructions]\(https://github.com/Shopify/shopify-app-template-remix/tree/main#incorrect-graphql-hints).
```ts
GraphQLClient
```
### GraphQLClient
* query
```ts
Operation extends keyof Operations
```
* options
```ts
GraphQLQueryOptions
```
interface Promise\ { /\*\* \* Attaches callbacks for the resolution and/or rejection of the Promise. \* @param onfulfilled The callback to execute when the Promise is resolved. \* @param onrejected The callback to execute when the Promise is rejected. \* @returns A Promise for the completion of which ever callback is executed. \*/ then\(onfulfilled?: ((value: T) => TResult1 | PromiseLike\) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike\) | undefined | null): Promise\; /\*\* \* Attaches a callback for only the rejection of the Promise. \* @param onrejected The callback to execute when the Promise is rejected. \* @returns A Promise for the completion of the callback. \*/ catch\(onrejected?: ((reason: any) => TResult | PromiseLike\) | undefined | null): Promise\; }, interface Promise\ {}, Promise: PromiseConstructor, interface Promise\ { readonly \[Symbol.toStringTag]: string; }, interface Promise\ { /\*\* \* Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The \* resolved value cannot be modified from the callback. \* @param onfinally The callback to execute when the Promise is settled (fulfilled or rejected). \* @returns A Promise for the completion of the callback. \*/ finally(onfinally?: (() => void) | undefined | null): Promise\; }
```ts
interface Promise {
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): Promise;
/**
* Attaches a callback for only the rejection of the Promise.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of the callback.
*/
catch(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): Promise;
}, interface Promise {}, Promise: PromiseConstructor, interface Promise {
readonly [Symbol.toStringTag]: string;
}, interface Promise {
/**
* Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The
* resolved value cannot be modified from the callback.
* @param onfinally The callback to execute when the Promise is settled (fulfilled or rejected).
* @returns A Promise for the completion of the callback.
*/
finally(onfinally?: (() => void) | undefined | null): Promise;
}
```
### GraphQLQueryOptions
* apiVersion
The version of the API to use for the request.
```ts
ApiVersion
```
* headers
Additional headers to include in the request.
```ts
Record
```
* signal
An optional AbortSignal to cancel the request.
```ts
AbortSignal
```
* tries
The total number of times to try the request if it fails.
```ts
number
```
* variables
The variables to pass to the operation.
```ts
ApiClientRequestOptions["variables"]
```
Examples
### Examples
* #### Using the offline session
##### Description
Get your app's shop-specific data using the returned offline \`session\` object.
##### app/routes/\*\*\\/.ts
```typescript
import { LoaderFunctionArgs, json } from "@remix-run/node";
import { unauthenticated } from "../shopify.server";
import { getMyAppData } from "~/db/model.server";
export const loader = async ({ request }: LoaderFunctionArgs) => {
const shop = getShopFromExternalRequest(request);
const { session } = await unauthenticated.storefront(shop);
return json(await getMyAppData({shop: session.shop));
};
```
* #### Querying the GraphQL API
##### Description
Use \`storefront.graphql\` to make query / mutation requests.
##### app/routes/\*\*\\/.ts
```typescript
import { json } from "@remix-run/node";
import { authenticate } from "../shopify.server";
export async function action({ request }: ActionFunctionArgs) {
const shop = getShopFromExternalRequest(request);
const { storefront } = await unauthenticated.storefront(shop);
const response = await storefront.graphql(`{blogs(first: 10) { edges { node { id } } } }`);
return json(await response.json());
}
```
* #### Handling GraphQL errors
##### Description
Catch \`GraphqlQueryError\` errors to see error messages from the API.
##### /app/routes/\*\*\\/\*.ts
```typescript
import { ActionFunctionArgs } from "@remix-run/node";
import { authenticate } from "../shopify.server";
export const action = async ({ request }: ActionFunctionArgs) => {
const shop = getShopFromExternalRequest(request);
const { storefront } = await unauthenticated.storefront(shop);
try {
const response = await storefront.graphql(
`#graphql
query incorrectQuery {
products(first: 10) {
nodes {
not_a_field
}
}
}`,
);
return json({ data: await response.json() });
} catch (error) {
if (error instanceof GraphqlQueryError) {
// { errors: { graphQLErrors: [
// { message: "Field 'not_a_field' doesn't exist on type 'Product'" }
// ] } }
return json({ errors: error.body?.errors }, { status: 500 });
}
return json({ message: "An error occurred" }, { status: 500 });
}
}
```
##### /app/shopify.server.ts
```typescript
import { shopifyApp } from "@shopify/shopify-app-remix/server";
const shopify = shopifyApp({
// ...
});
export default shopify;
export const unauthenticated = shopify.unauthenticated;
```
## Related
[Interact with the Storefront API. - API context](https://shopify.dev/docs/api/shopify-app-remix/apis/storefront-api)