All Tutorials

Get started building a product subscription app extension

All Tutorials

Get started building a product subscription app extension

Get started building a product subscription app extension

This tutorial explains how to get started building a product subscription app extension using Argo. For more information on the business logic behind subscriptions, refer to the Selling plan API.

How a product subscription app extension looks in Shopify

Shopify renders a new section, called a subscription card, on the product page to display subscription information to the merchant:

Argo card on product page

If a merchant clicks create subscription plan, then an app overlay appears. Your extension built with Argo is responsible for rendering the content and creating the subscription plan.

Scaffold a product subscription app extension

You can use the Shopify app CLI to create a product subscription app extension scaffold, and then run the app extension simulator in your local development environment.

  1. Install the Shopify App CLI.

  2. Open a terminal and enter the following command to create a new product subscription app extension:

    Terminal
    $ shopify create extension --type=PRODUCT_SUBSCRIPTION --name="My subscription extension"
  3. At the prompt, select your programming language and framework preferences for development: JavaScript or TypeScript, and whether you want to use React. For this tutorial we're using React with Typescript.

  4. Navigate to the project folder and start a local server:

    Terminal
    $ cd subscription_extension/
    $ shopify serve

    The terminal output of the shopify serve command contains a local URL that you can open to run the app extension simulator: http://0.0.0.0:PORT.

    The extension simulator is a browser tool that allows you to preview how your code will render on Shopify. You can edit your code and observe its UI effects by refreshing the simulator.

    Extension simulator example

  5. In the app extension simulator, set the action dropdown to the create extension mode and then click the Show extension button to launch your Argo script in an app overlay with the specified inputs.

You can find the extension script in the extension folder at src/index.tsx or src/index.js. The script contains four extension point callback functions, one for each of the four modes: Add, Create, Remove, and Edit. For more information on the available extension modes, refer to Create and manage a product subscription app extension.

Extension points

The product subscription app extension uses multiple extension points. Each extension point is triggered by a different merchant action, receives different data, and is responsible for handling a distinct part of the subscription experience.

The different extension points are:

  • Admin::Product::SubscriptionPlan::Add
  • Admin::Product::SubscriptionPlan::Create
  • Admin::Product::SubscriptionPlan::Edit
  • Admin::Product::SubscriptionPlan::Remove

They must be rendered separately.

Javascript:

import {extend} from '@shopify/argo-admin';
function Add(root, api) { root.appendChild(root.createText('Hello, world')); root.mount(); } function Create() { /* ... */ } function Edit() { /* ... */ } function Remove() { /* ... */ }
extend( 'Admin::Product::SubscriptionPlan::Add', Add, ); extend( 'Admin::Product::SubscriptionPlan::Create', Create, ); extend( 'Admin::Product::SubscriptionPlan::Edit', Edit, ); extend( 'Admin::Product::SubscriptionPlan::Remove', Remove, );

React:

import {extend, render, Text} from '@shopify/argo-admin-react';
function Add() { return <Text>Hello, world</Text>; } function Create() { /* ... */ } function Edit() { /* ... */ } function Remove() { /* ... */ }
extend( 'Admin::Product::SubscriptionPlan::Add', render(() => <Add />), ); extend( 'Admin::Product::SubscriptionPlan::Create', render(() => <Create />), ); extend( 'Admin::Product::SubscriptionPlan::Edit', render(() => <Edit />), ); extend( 'Admin::Product::SubscriptionPlan::Remove', render(() => <Remove />), );

Data

Your extension receives data from the host page in your extension. In this example, the current product is being rendered inside the extension as (Product 1):

Argo subscriptions app overlay

In src/index.tsx or src/index.js, find the Create extension point callback function. In the first line of the function, the data variable is assigned to the input data passed into the extension from the host page.

Javascript:

In vanilla JavaScript, input data is passed into the extension point callback function:

import {extend, Card} from '@shopify/argo-admin';
function Create(root, api) { const data = api.data;
// ...
const planTitleCard = root.createComponent(Card, { sectioned: true, title: `Create subscription plan for Product id ${data.productId}`, }); root.appendChild(planTitleCard);
root.mount(); }
extend('Admin::Product::SubscriptionPlan::Create', Create);

Refer to the full source for the JavaScript product subscription app extension template.

React:

In React, access input data with the useData hook:

import {extend, render, useData, Card} from '@shopify/argo-admin-react';
function Create() { const data = useData();
// ...
return ( // ... <Card title={`Create subscription plan for Product id ${data.productId}`} sectioned > ... </Card> ) }
extend('Admin::Product::SubscriptionPlan::Create', render(() => <Create />);

Refer to the full source for the React product subscription app extension template.

Components

The final section of the Create function renders the UI components that appear in the canvas of the app overlay. Refer to components available to the product subscription app extension.

Argo subscriptions app overlay

Javascript:

import {extend, Card, Text, TextField, Stack} from '@shopify/argo-admin';
function Create(api, root) { // ...
const planDetailsCard = root.createComponent(Card, { sectioned: true, title: 'Delivery and discount', }); rootStack.appendChild(planDetailsCard);
const stack = root.createComponent(Stack); planDetailsCard.appendChild(stack);
const deliveryFrequencyField = root.createComponent(TextField, { type: 'number', label: 'Delivery frequency (in weeks)', value: undefined, onChange(value) { deliveryFrequencyField.updateProps({ value, }); }, }); stack.appendChild(deliveryFrequencyField);
const percentageOffField = root.createComponent(TextField, { type: 'number', label: 'Percentage off (%)', value: undefined, onChange(value) { percentageOffField.updateProps({ value, }); }, }); stack.appendChild(percentageOffField);
const actionsElement = root.createComponent(Stack, {distribution: 'fill'}); rootStack.appendChild(actionsElement); actionsElement.appendChild(secondaryButton);
const primaryButtonStack = root.createComponent(Stack, { distribution: 'trailing', }); actionsElement.appendChild(primaryButtonStack); primaryButtonStack.appendChild(primaryButton);
root.mount(); }
extend('Admin::Product::SubscriptionPlan::Create', Create);

Refer to the full source for the JavaScript product subscription app extension template.

React:

import {extend, render, Card, Text, TextField, Stack} from '@shopify/argo-admin-react';
function Create() { // ...
return ( <> <Text size="titleLarge">Create plan</Text> <Card title={`Create subscription plan for Product id ${data.productId}`} sectioned> <TextField label="Plan title" value={planTitle} onAfterChange={setPlanTitle} /> </Card> <Card title="Delivery and discount" sectioned> <Stack> <TextField type="number" label="Delivery frequency (in weeks)" value={deliveryFrequency} onAfterChange={setDeliveryFrequency} /> <TextField type="number" label="Percentage off (%)" value={percentageOff} onAfterChange={setPercentageOff} /> </Stack> </Card> {actions} </> ); }
extend('Admin::Product::SubscriptionPlan::Create', render(() => <Create />);

Refer to the full source for the React product subscription app extension template.

Next steps