Sidekick Extensions
Shopify Sidekick is the AI assistant built directly into the Shopify Admin. It helps merchants manage their stores through natural language -- answering questions about sales, writing product descriptions, generating discount codes, and more. With Sidekick Extensions, developers can teach Sidekick about their app's capabilities, allowing merchants to interact with third-party app functionality without ever leaving the conversational interface.
Sidekick Extensions are currently in developer preview. The API surface is evolving, but the core patterns described in this lesson are stable. You can begin building and testing extensions today through the Shopify Partners program.
Why Sidekick Extensions Matter
Before Sidekick Extensions, app functionality was siloed. A merchant using a loyalty program app had to navigate to that app's UI, learn its interface, and manually trigger actions. With Sidekick Extensions, the same merchant can say:
"Show me my top 10 loyalty program members this month"
...and Sidekick routes the request to your app, retrieves the data, and presents it conversationally. This is not a gimmick -- it fundamentally changes how merchants discover and use app features.
The Merchant Experience
Building a Sidekick Extension
A Sidekick Extension consists of three main components:
- Extension manifest -- Declares what your extension can do
- Action handlers -- Functions that execute when Sidekick invokes your extension
- Response formatters -- Structure data for Sidekick to present to merchants
Extension Manifest
The manifest tells Sidekick what capabilities your app exposes. It uses a declarative schema that describes actions, parameters, and return types.
# shopify.extension.toml
[extension]
type = "sidekick_extension"
name = "Loyalty Program Assistant"
handle = "loyalty-sidekick"
[[extension.capabilities]]
name = "get_member_stats"
description = "Retrieve loyalty program statistics including total members, points issued, and redemption rates"
parameters = []
[[extension.capabilities]]
name = "lookup_member"
description = "Look up a specific loyalty program member by name or email"
[[extension.capabilities.parameters]]
name = "query"
type = "string"
description = "Customer name or email to search for"
required = true
[[extension.capabilities]]
name = "issue_bonus_points"
description = "Issue bonus loyalty points to a customer segment"
[[extension.capabilities.parameters]]
name = "segment"
type = "string"
description = "Customer segment identifier"
required = true
[[extension.capabilities.parameters]]
name = "points"
type = "number"
description = "Number of bonus points to issue"
required = true
Sidekick uses your capability descriptions to decide when to route a merchant's request to your extension. Write descriptions that are specific and action-oriented. Instead of "manages loyalty data," write "retrieve loyalty program statistics including total members, points issued, and redemption rates." The more precise your descriptions, the more accurately Sidekick will match merchant intents.
Action Handlers
Action handlers are the server-side functions that Sidekick calls when it identifies a matching capability. They receive structured parameters and return data that Sidekick formats for the merchant.
// extensions/sidekick/src/handlers.ts
import { SidekickActionHandler } from '@shopify/sidekick-extensions';
export const getMemberStats: SidekickActionHandler = async (context) => {
const { session, admin } = context;
// Query your app's database for loyalty stats
const stats = await db.loyaltyStats.aggregate({
shopId: session.shop,
period: 'current_month',
});
return {
type: 'data_summary',
data: {
totalMembers: stats.totalMembers,
activeMembers: stats.activeThisMonth,
pointsIssued: stats.pointsIssuedThisMonth,
pointsRedeemed: stats.pointsRedeemedThisMonth,
redemptionRate: (stats.pointsRedeemedThisMonth / stats.pointsIssuedThisMonth * 100).toFixed(1),
topReward: stats.mostPopularReward,
},
summary: `Your loyalty program has ${stats.totalMembers.toLocaleString()} members. This month, ${stats.activeThisMonth.toLocaleString()} members were active, with a ${(stats.pointsRedeemedThisMonth / stats.pointsIssuedThisMonth * 100).toFixed(1)}% redemption rate.`,
};
};
export const lookupMember: SidekickActionHandler = async (context) => {
const { session, params } = context;
const { query } = params;
const members = await db.loyaltyMembers.search({
shopId: session.shop,
query,
limit: 5,
});
if (members.length === 0) {
return {
type: 'not_found',
summary: `No loyalty members found matching "${query}".`,
};
}
return {
type: 'member_list',
data: members.map((m) => ({
name: m.name,
email: m.email,
tier: m.tier,
pointsBalance: m.pointsBalance,
lifetimeSpend: m.lifetimeSpend,
memberSince: m.createdAt,
})),
summary: `Found ${members.length} member(s) matching "${query}".`,
};
};
export const issueBonusPoints: SidekickActionHandler = async (context) => {
const { session, params } = context;
const { segment, points } = params;
// Validate the action before executing
const segmentSize = await db.segments.count({
shopId: session.shop,
segmentId: segment,
});
return {
type: 'confirmation_required',
action: 'issue_bonus_points',
summary: `This will issue ${points} bonus points to ${segmentSize} customers in the "${segment}" segment. Total points cost: ${points * segmentSize}. Confirm?`,
params: { segment, points, affectedCustomers: segmentSize },
};
};
Any Sidekick Extension action that modifies data (issuing points, deleting records, updating settings) must return a confirmation_required response type first. Sidekick will present the confirmation to the merchant before executing. Never auto-execute destructive operations from a Sidekick handler.
Sidekick Pulse: Proactive Merchant Recommendations
Sidekick Pulse is the proactive counterpart to the reactive query model. Instead of waiting for a merchant to ask a question, Pulse allows your extension to push insights to merchants when something noteworthy happens.
Pulse Event Types
| Event Type | Description | Example |
|---|---|---|
insight | Data-driven observation | "Your loyalty redemption rate increased 23% this week" |
alert | Something that needs attention | "15 loyalty members have expiring points in 3 days" |
suggestion | Actionable recommendation | "Consider running a double-points promotion -- your top segment hasn't purchased in 14 days" |
celebration | Positive milestone | "Your loyalty program just hit 1,000 members!" |
// Registering a Pulse event from your app backend
import { SidekickPulse } from '@shopify/sidekick-extensions';
const pulse = new SidekickPulse({
appId: process.env.SHOPIFY_APP_ID,
});
// Push a proactive insight
await pulse.emit({
shopId: 'shop_abc123',
type: 'suggestion',
priority: 'medium',
title: 'Double Points Opportunity',
message: 'Your VIP segment (234 customers) averages 45 days between purchases. They are currently at 38 days. A targeted double-points weekend could drive re-engagement.',
actions: [
{
label: 'Create Double Points Event',
capability: 'create_promotion',
params: { type: 'double_points', segment: 'vip', duration: '48h' },
},
{
label: 'Dismiss',
type: 'dismiss',
},
],
});
Custom App Generation
Sidekick can also help merchants generate custom app logic through natural language. When a merchant describes a workflow that does not exist as a built-in feature or installed app, Sidekick can generate Shopify Flow automations or simple custom scripts.
As an extension developer, you can register templates that Sidekick uses when generating solutions in your domain:
// Register generation templates for your app's domain
export const generationTemplates = [
{
domain: 'loyalty',
template: 'points_rule',
description: 'Create a custom points earning rule',
schema: {
trigger: ['order_created', 'product_reviewed', 'referral_completed'],
condition: 'string', // Liquid-compatible condition
pointsFormula: 'string', // e.g., "order.total * 2"
},
example: {
trigger: 'order_created',
condition: 'order.total > 100',
pointsFormula: 'order.total * 1.5',
},
},
];
Flow Automation via Sidekick
Sidekick Extensions can register Flow triggers and actions that merchants can incorporate into Shopify Flow automations through natural language.
A merchant saying "When a VIP customer places an order over $100, give them double loyalty points and send them a thank-you email" triggers Sidekick to:
- Identify the trigger (order created)
- Add the conditions (customer tagged VIP, order total > $100)
- Wire your extension's "issue points" action with a 2x multiplier
- Add a Shopify Email action for the thank-you
Theme Editing via Sidekick Commands
If your app includes theme app extensions (covered in a later module), Sidekick can help merchants configure and place your app blocks through natural language:
"Add the loyalty points widget below the add-to-cart button on product pages"
Sidekick translates this into the correct theme editor operations, placing your app block in the right section of the merchant's theme.
Use the Shopify CLI command shopify app dev --sidekick-debug to enable verbose logging of Sidekick's routing decisions. This shows you exactly how Sidekick interprets merchant queries and why it does or does not route to your extension. This is invaluable during development.
Best Practices
- Keep capabilities focused -- Each capability should do one thing well. Prefer many small capabilities over a few large ones.
- Write human-readable summaries -- Sidekick presents your summary text directly to merchants. Write it as you would speak to a store owner.
- Handle errors gracefully -- Return helpful error messages that Sidekick can relay. "Unable to fetch stats" is useless; "Could not load loyalty stats because the app needs to complete initial sync -- this takes about 5 minutes after installation" is helpful.
- Respect rate limits -- Sidekick may invoke your handlers frequently. Cache expensive queries and use background jobs for heavy lifting.
- Log everything -- Since you cannot see Sidekick's UI during development, comprehensive logging is your best debugging tool.
Continue to AI Shopping Agents to learn how to build a complete conversational shopping assistant that uses the Catalog API and Checkout Kit.