# Methods

URL: https://docs.sparklayer.io/developers/javascript-sdk/reference/methods

Every window.spark method in the SparkLayer SDK, such as getCart, updateCart, getPricingForVariant and fetch, with parameters, return values and examples.

> **For AI assistants:** what to know before writing SparkLayer JavaScript SDK code.
>
> - **What it is:** `window.spark`, added to the storefront by the SparkLayer Core Script (version 4.x). On Shopify the SparkLayer app embed loads it; elsewhere it's `<script async src="https://sparkcdn.io/sparkjs/<SITE_ID>/<live|test>"></script>` in the theme's `<head>`. The old `cdn.sparklayer.io/spark.latest.js` and `spark.1.x.js` files are legacy: never use them.
> - **Options:** Configure it with `window.sparkOptions`, set before the Core Script loads. Extend the object rather than replacing it: `window.sparkOptions = { ...window.sparkOptions, … }`, or the Site ID and other snippets' hooks are lost. Headless only: `window.initSpark(options)` is defined when `window.sparkOptions` isn't set.
> - **When to call it:** Only after SparkLayer is ready: inside the `onReady(spark)` hook, or after a promise resolved from it. Most methods are async; prices and the cart are only available to signed-in B2B customers (check `await spark.isLoggedIn()`).
> - **Products and prices:** Products are looked up by the platform's parent product ID (on Shopify, `product.id`) and variants by SKU: `getPricingForVariant(parentProductId, sku)`, `calculatePricingForVariant(parentProductId, sku, qty)`, `getPackSizeForVariant(parentProductId, sku)`. For instant recalculation, fetch once with `getVariant` and call `calculatePricingForVariantData(variant, qty)`.
> - **Cart:** `updateCart({ products: [{ sku, adjustQuantity }] })` adds or removes relative to what's in the cart (also `customAttributes: [{ key, value }]`, `clearCart: true`). It resolves to the results, or `null` after showing its own error message; it doesn't throw. `getCart()` reads the cart; `openDrawer('cart')` opens it.
> - **Hooks:** `onCartUpdate(cart, results)`, `onCartLoad(cart)`, `onLogout()`, `preCartUpdateListener(input)` (async: return the possibly changed input) and `onCheckoutValidation(cart, cartUiState)` (return `[{ message }]` to block checkout, or `null`). When adding a hook, call any existing one first.
> - **Customising:** Build around SparkLayer or customise its own components, including their HTML. Prefer documented options, hooks, CSS variables and custom slots where they fit; keep direct HTML changes targeted and re-check them after SparkLayer updates.
> - **Docs:** The reference: methods https://docs.sparklayer.io/developers/javascript-sdk/reference/methods.md, hooks https://docs.sparklayer.io/developers/javascript-sdk/reference/hooks.md, options https://docs.sparklayer.io/developers/javascript-sdk/reference/options.md, types https://docs.sparklayer.io/developers/javascript-sdk/reference/types.md (or the same types as a file: https://docs.sparklayer.io/developers/javascript-sdk/spark.d.ts). Setup and waiting for SparkLayer: https://docs.sparklayer.io/developers/javascript-sdk/setup.md. Use only what the reference documents.

## Wait for SparkLayer

`window.spark` is set as soon as the Core Script runs, but its methods only work once SparkLayer is ready. Call them from the `onReady` hook, or add the [Wait for SparkLayer](https://docs.sparklayer.io/developers/javascript-sdk/setup.md#wait-for-sparklayer) snippet and start with `const spark = await window.sparkReady;`, as the examples on this page do.

## The Spark object

The `Spark` object is available as `window.spark`, and is passed to the [`onReady`](https://docs.sparklayer.io/developers/javascript-sdk/reference/hooks.md#onready) and [`onLoad`](https://docs.sparklayer.io/developers/javascript-sdk/reference/hooks.md#onload) hooks. Its public members are:

```typescript
type Spark = {
  options: SparkLayerOptions;
  isLoggedIn(): Promise<boolean>;
  switchImpersonatingCustomer(customerId: string | null): Promise<UserData | null>;
  refreshGlobalData(): Promise<UserData | null>;
  getActiveCustomerVerificationToken(): Promise<string | null>;
  setActiveCompanySection(sectionId: string): Promise<boolean>;
  getProduct(parentProductId: string): Promise<Product>;
  getProductBySlug(slug: string): Promise<Product>;
  getVariant(parentProductId: string, variantSku: string): Promise<ProductVariant>;
  getPriceForProduct(parentProductId: string): Promise<SimplifiedProductPrice>;
  getPricingForVariant(
    parentProductId: string,
    variantSku: string,
  ): Promise<{
    price: number | null;
    rrp: number | null;
    rrpCurrencyCode: string | null;
    priceBreaks: VariantPriceBreak[];
    currencyCode: string;
  }>;
  getRrpPriceForVariant(
    parentProductId: string,
    variantSku: string,
  ): Promise<{ rrp: number | null; currencyCode: string | null }>;
  getPackSizeForVariant(parentProductId: string, variantSku: string): Promise<number>;
  calculatePricingForVariant(
    parentProductId: string,
    variantSku: string,
    qty: number,
    qtyAcrossVariants?: number | null,
  ): Promise<ProductVariantPricing>;
  calculatePricingForVariantData(
    variant: ProductVariantDataPricing,
    qty: number,
    qtyAcrossVariants?: number | null,
  ): ProductVariantPricing;
  getCart(): Promise<Cart | null>;
  getCartCache(): Cart | null;
  updateCart(
    input: Partial<UpdateCart>,
    cartSuccessHandledLocally?: boolean,
    cartErrorsHandledLocally?: boolean,
  ): Promise<CartResults[] | null>;
  addCustomLineItem(customItem: CustomLineItemInput): Promise<Cart | null>;
  externalClearBasket(): Promise<void>;
  openDrawer(initialTab?: DrawerUIState): void;
  closeDrawer(): void;
  uploadFile(fileName: string, fileData: Blob): Promise<string>;
  fetch<Q extends GraphqlQueryOrMutation<unknown, Record<string, unknown>, GraphqlError | GraphqlExtensionError>>(
    query: Q,
    variables?: VariablesOf<Q>,
    useImpersonatingCustomer?: boolean,
    bypassAppProxy?: boolean,
    signal?: AbortSignal,
  ): Promise<FetchResponse<ResponseOf<Q>, ErrorOf<Q>>>;
};
```

### options

**Type:** [`SparkLayerOptions`](https://docs.sparklayer.io/developers/javascript-sdk/reference/types.md#sparklayeroptions)

The options SparkLayer is running with, after merging your `sparkOptions` with the platform defaults. See [Options](https://docs.sparklayer.io/developers/javascript-sdk/reference/options.md).

```javascript title="Any script"
const spark = await window.sparkReady;
console.log(spark.options.platform, spark.options.language);
```

## Customers and session

### isLoggedIn()

Checks whether the user is logged in.

```typescript title="Signature"
isLoggedIn(): Promise<boolean>;
```

**Returns:** `Promise<boolean>`

```javascript title="Any script"
const spark = await window.sparkReady;
if (await spark.isLoggedIn()) {
  // Show B2B content
}
```

### switchImpersonatingCustomer()

Switches the customer a sales agent is impersonating, or ends impersonation when you pass `null`.

```typescript title="Signature"
switchImpersonatingCustomer(customerId: string | null): Promise<UserData | null>;
```

| Name | Type | Description |
| --- | --- | --- |
| `customerId` | `string \| null` | The customer to impersonate, or `null` to end impersonation. |

**Returns:** `Promise<`[`UserData`](https://docs.sparklayer.io/developers/javascript-sdk/reference/types.md#userdata)` | null>`

```javascript title="Any script"
const spark = await window.sparkReady;
const customer = await spark.switchImpersonatingCustomer('<CUSTOMER_ID>');
await spark.switchImpersonatingCustomer(null); // End impersonation
```

### refreshGlobalData()

Refetches the current active customer and site configuration, and updates the cached copy both are read from.

```typescript title="Signature"
refreshGlobalData(): Promise<UserData | null>;
```

**Returns:** `Promise<`[`UserData`](https://docs.sparklayer.io/developers/javascript-sdk/reference/types.md#userdata)` | null>`

```javascript title="Any script"
const spark = await window.sparkReady;
const user = await spark.refreshGlobalData();
```

### getActiveCustomerVerificationToken()

Refetches the current active customer and returns a fresh form customer verification token. It uses the impersonated customer when a sales agent is impersonating, otherwise the logged-in customer.

```typescript title="Signature"
getActiveCustomerVerificationToken(): Promise<string | null>;
```

**Returns:** `Promise<string | null>`

```javascript title="Any script"
const spark = await window.sparkReady;
const token = await spark.getActiveCustomerVerificationToken();
```

### setActiveCompanySection()

Selects the company section used for purchasing. If the cart isn't empty, the user is asked to confirm and the cart is cleared. The page then reloads.

```typescript title="Signature"
setActiveCompanySection(sectionId: string): Promise<boolean>;
```

| Name | Type | Description |
| --- | --- | --- |
| `sectionId` | `string` | The ID of one of the logged-in customer's company sections. |

**Returns:** `Promise<boolean>`: `false` if the section isn't available to the customer, the user cancels, or the cart couldn't be cleared.

```javascript title="Any script"
const spark = await window.sparkReady;
const user = await spark.refreshGlobalData();
const section = user?.companySections[0];
if (section) await spark.setActiveCompanySection(section.id);
```

## Products and pricing

Each method takes your platform's parent product ID and, for a variant, its SKU. Prices are for the logged-in customer.

### getProduct()

Fetches the GraphQL product object for a parent product ID.

```typescript title="Signature"
getProduct(parentProductId: string): Promise<Product>;
```

| Name | Type | Description |
| --- | --- | --- |
| `parentProductId` | `string` | The parent product ID. |

**Returns:** `Promise<`[`Product`](https://docs.sparklayer.io/developers/javascript-sdk/reference/types.md#product)`>`

**Throws:** if the product isn't found or an error occurs fetching it.

```javascript title="Any script"
const spark = await window.sparkReady;
const product = await spark.getProduct('6660191387839');
console.log(product.variants.map((variant) => variant.sku));
```

### getProductBySlug()

Fetches the GraphQL product object for a product slug.

```typescript title="Signature"
getProductBySlug(slug: string): Promise<Product>;
```

| Name | Type | Description |
| --- | --- | --- |
| `slug` | `string` | The product slug. |

**Returns:** `Promise<`[`Product`](https://docs.sparklayer.io/developers/javascript-sdk/reference/types.md#product)`>`

**Throws:** if the product isn't found or an error occurs fetching it.

```javascript title="Any script"
const spark = await window.sparkReady;
const product = await spark.getProductBySlug('mother-mug');
```

### getVariant()

Fetches the GraphQL variant object for a parent product ID and variant SKU.

```typescript title="Signature"
getVariant(parentProductId: string, variantSku: string): Promise<ProductVariant>;
```

| Name | Type | Description |
| --- | --- | --- |
| `parentProductId` | `string` | The parent product ID. |
| `variantSku` | `string` | The variant SKU. |

**Returns:** `Promise<`[`ProductVariant`](https://docs.sparklayer.io/developers/javascript-sdk/reference/types.md#productvariant)`>`

**Throws:** if the product or variant isn't found or an error occurs fetching the product.

```javascript title="Any script"
const spark = await window.sparkReady;
const variant = await spark.getVariant('6660191387839', 'MUG-MOM');
console.log(variant.name, variant.stockDisplay?.status);
```

### getPriceForProduct()

Fetches the pricing for a parent product, including price breaks, the lowest price and the number of prices.

```typescript title="Signature"
getPriceForProduct(parentProductId: string): Promise<SimplifiedProductPrice>;
```

| Name | Type | Description |
| --- | --- | --- |
| `parentProductId` | `string` | The parent product ID. |

**Returns:** `Promise<`[`SimplifiedProductPrice`](https://docs.sparklayer.io/developers/javascript-sdk/reference/types.md#simplifiedproductprice)`>`: all price-related data for the parent product, including price breaks, the lowest price and the number of prices. Use the number of prices to decide whether to show "from" before the price.

**Throws:** if the product isn't found or an error occurs fetching it.

```javascript title="Any script"
const spark = await window.sparkReady;
const { fromPrice, numberOfPrices, currencyCode } = await spark.getPriceForProduct('6660191387839');
const label = `${numberOfPrices > 1 ? 'From ' : ''}${fromPrice} ${currencyCode}`;
```

### getPricingForVariant()

Fetches the pricing for a variant.

```typescript title="Signature"
getPricingForVariant(
  parentProductId: string,
  variantSku: string,
): Promise<{
  price: number | null;
  rrp: number | null;
  rrpCurrencyCode: string | null;
  priceBreaks: VariantPriceBreak[];
  currencyCode: string;
}>;
```

| Name | Type | Description |
| --- | --- | --- |
| `parentProductId` | `string` | The parent product ID. |
| `variantSku` | `string` | The variant SKU. |

**Returns:** all price-related data for the variant: `price`, `rrp`, `rrpCurrencyCode`, `priceBreaks` (each a [`VariantPriceBreak`](https://docs.sparklayer.io/developers/javascript-sdk/reference/types.md#variantpricebreak)) and `currencyCode`.

**Throws:** if the product or variant isn't found or an error occurs fetching the product.

```javascript title="Any script"
const spark = await window.sparkReady;
const pricing = await spark.getPricingForVariant('6660191387839', 'MUG-MOM');
console.log(pricing.price, pricing.currencyCode, pricing.priceBreaks);
```

### getRrpPriceForVariant()

Fetches the RRP for a variant.

```typescript title="Signature"
getRrpPriceForVariant(
  parentProductId: string,
  variantSku: string,
): Promise<{ rrp: number | null; currencyCode: string | null }>;
```

| Name | Type | Description |
| --- | --- | --- |
| `parentProductId` | `string` | The parent product ID. |
| `variantSku` | `string` | The variant SKU. |

**Returns:** the RRP (`null` if not set for the currency) and the currency code.

**Throws:** if the product or variant isn't found or an error occurs fetching the product.

```javascript title="Any script"
const spark = await window.sparkReady;
const { rrp, currencyCode } = await spark.getRrpPriceForVariant('6660191387839', 'MUG-MOM');
```

### getPackSizeForVariant()

Fetches the pack size for a variant.

```typescript title="Signature"
getPackSizeForVariant(parentProductId: string, variantSku: string): Promise<number>;
```

| Name | Type | Description |
| --- | --- | --- |
| `parentProductId` | `string` | The parent product ID. |
| `variantSku` | `string` | The variant SKU. |

**Returns:** `Promise<number>`: the variant's pack size, or `1` if none is set.

**Throws:** if the product or variant isn't found or an error occurs fetching the product.

```javascript title="Any script"
const spark = await window.sparkReady;
const packSize = await spark.getPackSizeForVariant('6660191387839', 'MUG-MOM');
const quantity = Math.ceil(10 / packSize) * packSize; // Round 10 up to whole packs
```

### calculatePricingForVariant()

Returns the price for a quantity of a variant, given its parent product ID and SKU.

```typescript title="Signature"
calculatePricingForVariant(
  parentProductId: string,
  variantSku: string,
  qty: number,
  qtyAcrossVariants?: number | null,
): Promise<ProductVariantPricing>;
```

| Name | Type | Description |
| --- | --- | --- |
| `parentProductId` | `string` | The parent product ID. |
| `variantSku` | `string` | The variant SKU. |
| `qty` | `number` | The quantity to calculate pricing for. |
| `qtyAcrossVariants?` | `number \| null` | For tiered pricing, the quantity across variants (if configured). Defaults to `null`. |

**Returns:** `Promise<`[`ProductVariantPricing`](https://docs.sparklayer.io/developers/javascript-sdk/reference/types.md#productvariantpricing)`>`: the total price (quantity × unit price), the unit price and the price breaks.

**Throws:** if the product or variant isn't found or an error occurs fetching the product.

```javascript title="Any script"
const spark = await window.sparkReady;
const pricing = await spark.calculatePricingForVariant('6660191387839', 'MUG-MOM', 2);
console.log(pricing.totalPrice, pricing.unitPrice, pricing.currencyCode);
```

### calculatePricingForVariantData()

Calculates the pricing for a variant from variant data you already have, without fetching.

```typescript title="Signature"
calculatePricingForVariantData(
  variant: ProductVariantDataPricing,
  qty: number,
  qtyAcrossVariants?: number | null,
): ProductVariantPricing;
```

| Name | Type | Description |
| --- | --- | --- |
| `variant` | [`ProductVariantDataPricing`](https://docs.sparklayer.io/developers/javascript-sdk/reference/types.md#productvariantdatapricing) | Variant data, including the RRP and price breaks. A `ProductVariant` or `CartItem` works. |
| `qty` | `number` | The quantity to calculate pricing for. |
| `qtyAcrossVariants?` | `number \| null` | For tiered pricing, the quantity across variants (if configured). Defaults to `null`. |

**Returns:** [`ProductVariantPricing`](https://docs.sparklayer.io/developers/javascript-sdk/reference/types.md#productvariantpricing): the total price (quantity × unit price), the unit price and the price breaks.

```javascript title="Any script"
const spark = await window.sparkReady;
const variant = await spark.getVariant('6660191387839', 'MUG-MOM');
const pricing = spark.calculatePricingForVariantData(variant, 24); // No request
```

See [Live price as the quantity changes](https://docs.sparklayer.io/developers/javascript-sdk/products-and-pricing.md#live-price-as-the-quantity-changes) for a full example.

## Cart

See [Cart](https://docs.sparklayer.io/developers/javascript-sdk/cart.md) for worked examples.

### getCart()

Fetches the cart from GraphQL.

```typescript title="Signature"
getCart(): Promise<Cart | null>;
```

**Returns:** `Promise<`[`Cart`](https://docs.sparklayer.io/developers/javascript-sdk/reference/types.md#cart)` | null>`: the cart, or `null` if it couldn't be fetched (an error toast is shown).

```javascript title="Any script"
const spark = await window.sparkReady;
const cart = await spark.getCart();
console.log(cart?.items.length, cart?.totals.total.charge.gross.number);
```

### getCartCache()

Gets the cached cart, if available, without a request.

```typescript title="Signature"
getCartCache(): Cart | null;
```

**Returns:** [`Cart`](https://docs.sparklayer.io/developers/javascript-sdk/reference/types.md#cart)` | null`: the cached cart, or `null` if it isn't available.

```javascript title="Any script"
const spark = await window.sparkReady;
const cart = spark.getCartCache() ?? (await spark.getCart());
```

### updateCart()

Runs an update cart mutation, shows the appropriate toasts and returns the result. It makes every change to the cart: adding, updating and removing items, and setting cart-level fields.

```typescript title="Signature"
updateCart(
  input: Partial<UpdateCart>,
  cartSuccessHandledLocally?: boolean,
  cartErrorsHandledLocally?: boolean,
): Promise<CartResults[] | null>;
```

| Name | Type | Description |
| --- | --- | --- |
| `input` | `Partial<`[`UpdateCart`](https://docs.sparklayer.io/developers/javascript-sdk/reference/types.md#updatecart)`>` | Follows the GraphQL `updateCart` mutation's variables. Each product is a [`CartItemInput`](https://docs.sparklayer.io/developers/javascript-sdk/reference/types.md#cartiteminput). |
| `cartSuccessHandledLocally?` | `boolean` | Don't show success toasts, as you'll handle the result yourself (useful in the cart, where the update itself shows the change). Defaults to `false`. |
| `cartErrorsHandledLocally?` | `boolean` | Don't show toasts for the messages in the results, as you'll handle them yourself. Defaults to `false`. |

**Returns:** `Promise<`[`CartResults`](https://docs.sparklayer.io/developers/javascript-sdk/reference/types.md#cartresults)`[] | null>`: the results, or `null` if the update failed. It doesn't throw: on failure it shows an error toast and logs the error to the console. See [What updateCart returns](https://docs.sparklayer.io/developers/javascript-sdk/cart.md#what-updatecart-returns).

```javascript title="Any script"
const spark = await window.sparkReady;
const results = await spark.updateCart({
  products: [{ sku: 'RED-SHIRT-M', adjustQuantity: 1 }],
});
```

### addCustomLineItem()

Adds a custom line item (a free-text name, price and quantity not tied to a SKU) to the cart. The active customer must have custom cart items enabled, otherwise the request is rejected.

```typescript title="Signature"
addCustomLineItem(customItem: CustomLineItemInput): Promise<Cart | null>;
```

| Name | Type | Description |
| --- | --- | --- |
| `customItem` | [`CustomLineItemInput`](https://docs.sparklayer.io/developers/javascript-sdk/reference/types.md#customlineiteminput) | The name, unit price (as a decimal string) and quantity. |

**Returns:** `Promise<`[`Cart`](https://docs.sparklayer.io/developers/javascript-sdk/reference/types.md#cart)` | null>`: the refreshed cart, or `null` if the item couldn't be added.

```javascript title="Any script"
const spark = await window.sparkReady;
const cart = await spark.addCustomLineItem({ name: 'Artwork set-up', quotedPrice: '25.00', quantity: 1 });
```

### externalClearBasket()

Tells SparkLayer to clear the basket. Designed for your order confirmation (thank you) page.

```typescript title="Signature"
externalClearBasket(): Promise<void>;
```

**Returns:** `Promise<void>`

```javascript title="Order confirmation page"
const spark = await window.sparkReady;
await spark.externalClearBasket();
```

## Drawer

### openDrawer()

Opens the SparkLayer drawer, optionally on a specific tab.

```typescript title="Signature"
openDrawer(initialTab?: DrawerUIState): void;
```

| Name | Type | Description |
| --- | --- | --- |
| `initialTab?` | [`DrawerUIState`](https://docs.sparklayer.io/developers/javascript-sdk/reference/types.md#draweruistate) | The tab to open on. Defaults to `"cart"`. |

**Returns:** `void`

```javascript title="Any script"
const spark = await window.sparkReady;
spark.openDrawer('account');
```

To switch a drawer that's already open to another tab, dispatch the [`view-update`](https://docs.sparklayer.io/developers/javascript-sdk/reference/events-and-components.md#view-update) event.

### closeDrawer()

Closes the SparkLayer drawer.

```typescript title="Signature"
closeDrawer(): void;
```

**Returns:** `void`

```javascript title="Any script"
const spark = await window.sparkReady;
spark.closeDrawer();
```

## Files and GraphQL

### uploadFile()

Uploads a file to the SparkLayer file store. Pass the returned ID as a cart item attribute to attach the file (see [Attach a file](https://docs.sparklayer.io/developers/javascript-sdk/cart.md#attach-a-file)).

```typescript title="Signature"
uploadFile(fileName: string, fileData: Blob): Promise<string>;
```

| Name | Type | Description |
| --- | --- | --- |
| `fileName` | `string` | The name of the file, including its extension. It must match the type of the data in `fileData`. |
| `fileData` | `Blob` | The file data as a `Blob`. |

**Returns:** `Promise<string>`: the uploaded file's ID (a GID).

**Throws:** if the file type isn't supported, the file is too large, the file path is invalid, or the upload fails.

```javascript title="Any script"
const spark = await window.sparkReady;
const gid = await spark.uploadFile('design.png', fileBlob);
await spark.updateCart({
  products: [{ sku: 'SHIRT-CUSTOM', adjustQuantity: 1, customAttributes: [{ key: 'Design', value: JSON.stringify([gid]) }] }],
});
```

### fetch()

Runs a GraphQL query or mutation as the authenticated user.

```typescript title="Signature"
fetch<Q>(
  query: Q,
  variables?: VariablesOf<Q>,
  useImpersonatingCustomer?: boolean,
  bypassAppProxy?: boolean,
  signal?: AbortSignal,
): Promise<FetchResponse<ResponseOf<Q>, ErrorOf<Q>>>;
```

**Type parameter:** `Q extends GraphqlQueryOrMutation<unknown, Record<string, unknown>, GraphqlError | GraphqlExtensionError>`. See [`GraphqlQueryOrMutation`](https://docs.sparklayer.io/developers/javascript-sdk/reference/types.md#graphqlqueryormutation).

| Name | Type | Description |
| --- | --- | --- |
| `query` | `Q` | The GraphQL query string. |
| `variables?` | [`VariablesOf<Q>`](https://docs.sparklayer.io/developers/javascript-sdk/reference/types.md#variablesof) | The GraphQL variables. |
| `useImpersonatingCustomer?` | `boolean` | Whether to make the request as the customer being impersonated, rather than as the sales agent. |
| `bypassAppProxy?` | `boolean` | Call the API directly rather than through the platform's app proxy. |
| `signal?` | `AbortSignal` | Aborts the request, for example when its result is no longer needed. |

**Returns:** `Promise<`[`FetchResponse`](https://docs.sparklayer.io/developers/javascript-sdk/reference/types.md#fetchresponse)`<ResponseOf<Q>, ErrorOf<Q>>>`: a standard `Response` object. Check `status`, and call `json()` to get the `data` and `errors`.

```javascript title="Any script"
const spark = await window.sparkReady;
const response = await spark.fetch(`query { loggedInCustomer { id email } }`);
if (response.status === 200) {
  const { data, errors } = await response.json();
  if (!errors?.length) console.log(data.loggedInCustomer.email);
}
```

See [Run a GraphQL query](https://docs.sparklayer.io/developers/javascript-sdk/customers-and-accounts.md#run-a-graphql-query).

## Next steps

- [Types](https://docs.sparklayer.io/developers/javascript-sdk/reference/types.md): Cart, Product, UpdateCart and every other type these methods take and return.
- [Cart](https://docs.sparklayer.io/developers/javascript-sdk/cart.md): Add, update and remove items with updateCart, and attach custom attributes and files.
- [Products and pricing](https://docs.sparklayer.io/developers/javascript-sdk/products-and-pricing.md): Show trade prices and live quantity pricing in your theme.
