Sidekick Extensions
Shopify Sidekick은 Shopify Admin에 직접 내장된 AI 어시스턴트입니다. 자연어를 통해 판매자가 스토어를 관리할 수 있도록 도와줍니다 -- 매출에 대한 질문에 답하고, 제품 설명을 작성하고, 할인 코드를 생성하는 등의 작업을 수행합니다. Sidekick Extensions를 통해 개발자는 Sidekick에 앱의 기능을 알려줄 수 있으며, 판매자가 대화형 인터페이스를 벗어나지 않고도 서드파티 앱 기능과 상호작용할 수 있게 합니다.
Sidekick Extensions는 현재 개발자 프리뷰 단계에 있습니다. API 인터페이스는 계속 발전하고 있지만, 이 레슨에서 설명하는 핵심 패턴은 안정적입니다. Shopify Partners 프로그램을 통해 지금 바로 Extension을 구축하고 테스트할 수 있습니다.
Sidekick Extension이 중요한 이유
Sidekick Extensions 이전에는 앱 기능이 분리되어 있었습니다. 로열티 프로그램 앱을 사용하는 판매자는 해당 앱의 UI로 이동하고, 인터페이스를 익히고, 수동으로 작업을 트리거해야 했습니다. Sidekick Extensions를 사용하면 같은 판매자가 이렇게 말할 수 있습니다:
"이번 달 로열티 프로그램 상위 10명의 회원을 보여주세요"
...그러면 Sidekick이 요청을 앱으로 라우팅하고, 데이터를 가져와서, 대화형으로 제공합니다. 이것은 단순한 기믹이 아닙니다 -- 판매자가 앱 기능을 발견하고 사용하는 방식을 근본적으로 변화시킵니다.
판매자 경험
Sidekick Extension 구축
Sidekick Extension은 세 가지 주요 구성 요소로 이루어져 있습니다:
- Extension 매니페스트 -- Extension이 수행할 수 있는 작업을 선언합니다
- 액션 핸들러 -- Sidekick이 Extension을 호출할 때 실행되는 함수입니다
- 응답 포맷터 -- Sidekick이 판매자에게 제공할 데이터를 구조화합니다
Extension 매니페스트
매니페스트는 앱이 노출하는 기능을 Sidekick에 알려줍니다. 액션, 파라미터, 반환 타입을 설명하는 선언적 스키마를 사용합니다.
# 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은 기능 설명을 사용하여 판매자의 요청을 Extension으로 라우팅할 시기를 결정합니다. 구체적이고 행동 지향적인 설명을 작성하십시오. "로열티 데이터를 관리합니다" 대신 "총 회원 수, 발급된 포인트, 교환율을 포함한 로열티 프로그램 통계를 검색합니다"라고 작성하십시오. 설명이 정밀할수록 Sidekick이 판매자의 의도를 더 정확하게 매칭합니다.
액션 핸들러
액션 핸들러는 Sidekick이 매칭되는 기능을 식별했을 때 호출하는 서버 측 함수입니다. 구조화된 파라미터를 받아 Sidekick이 판매자에게 포맷하여 제공할 데이터를 반환합니다.
// 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 },
};
};
데이터를 수정하는 모든 Sidekick Extension 액션(포인트 발급, 레코드 삭제, 설정 업데이트)은 먼저 confirmation_required 응답 타입을 반환해야 합니다. Sidekick은 실행 전에 판매자에게 확인을 제시합니다. Sidekick 핸들러에서 파괴적 작업을 자동 실행하지 마십시오.
Sidekick Pulse: 능동적 판매자 추천
Sidekick Pulse는 반응형 쿼리 모델의 능동적 대응 기능입니다. 판매자가 질문할 때까지 기다리는 대신, Pulse는 주목할 만한 일이 발생했을 때 Extension이 판매자에게 인사이트를 푸시할 수 있게 합니다.
Pulse 이벤트 유형
| 이벤트 유형 | 설명 | 예시 |
|---|---|---|
insight | 데이터 기반 관찰 | "이번 주 로열티 교환율이 23% 증가했습니다" |
alert | 주의가 필요한 사항 | "15명의 로열티 회원 포인트가 3일 후 만료됩니다" |
suggestion | 실행 가능한 추천 | "더블 포인트 프로모션을 고려해 보세요 -- 상위 세그먼트가 14일간 구매하지 않았습니다" |
celebration | 긍정적 마일스톤 | "로열티 프로그램 회원이 1,000명을 달성했습니다!" |
// 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',
},
],
});
커스텀 앱 생성
Sidekick은 또한 판매자가 자연어를 통해 커스텀 앱 로직을 생성하도록 도울 수 있습니다. 판매자가 기본 기능이나 설치된 앱으로 존재하지 않는 워크플로우를 설명하면, Sidekick은 Shopify Flow 자동화 또는 간단한 커스텀 스크립트를 생성할 수 있습니다.
Extension 개발자로서, Sidekick이 해당 도메인에서 솔루션을 생성할 때 사용하는 템플릿을 등록할 수 있습니다:
// 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',
},
},
];
Sidekick을 통한 Flow 자동화
Sidekick Extensions는 판매자가 자연어를 통해 Shopify Flow 자동화에 통합할 수 있는 Flow 트리거 및 액션을 등록할 수 있습니다.
판매자가 "VIP 고객이 $100 이상 주문하면 더블 로열티 포인트를 주고 감사 이메일을 보내줘"라고 말하면 Sidekick이 다음을 수행합니다:
- 트리거를 식별합니다 (주문 생성)
- 조건을 추가합니다 (고객 태그 VIP, 주문 합계 > $100)
- Extension의 "포인트 발급" 액션을 2배 배수로 연결합니다
- 감사 메시지를 위한 Shopify Email 액션을 추가합니다
Sidekick 명령을 통한 테마 편집
앱에 테마 앱 Extension이 포함되어 있는 경우(이후 모듈에서 다룸), Sidekick은 판매자가 자연어를 통해 앱 블록을 구성하고 배치할 수 있도록 도와줍니다:
"제품 페이지의 장바구니 담기 버튼 아래에 로열티 포인트 위젯을 추가해 주세요"
Sidekick이 이것을 올바른 테마 편집기 작업으로 변환하여 판매자 테마의 적절한 섹션에 앱 블록을 배치합니다.
Shopify CLI 명령어 shopify app dev --sidekick-debug를 사용하여 Sidekick의 라우팅 결정에 대한 상세 로깅을 활성화하십시오. 이를 통해 Sidekick이 판매자 쿼리를 어떻게 해석하는지, Extension으로 라우팅하는 이유와 하지 않는 이유를 정확히 확인할 수 있습니다. 개발 중에 매우 유용합니다.
모범 사례
- 기능을 집중적으로 유지하십시오 -- 각 기능은 하나의 작업을 잘 수행해야 합니다. 적은 수의 큰 기능보다 많은 수의 작은 기능을 선호하십시오.
- 사람이 읽을 수 있는 요약을 작성하십시오 -- Sidekick은 요약 텍스트를 판매자에게 직접 제공합니다. 스토어 소유자에게 말하듯 작성하십시오.
- 오류를 우아하게 처리하십시오 -- Sidekick이 전달할 수 있는 유용한 오류 메시지를 반환하십시오. "통계를 가져올 수 없습니다"는 쓸모없습니다. "앱이 초기 동기화를 완료해야 하므로 로열티 통계를 로드할 수 없습니다 -- 설치 후 약 5분 소요됩니다"가 유용합니다.
- Rate Limit을 준수하십시오 -- Sidekick이 핸들러를 자주 호출할 수 있습니다. 비용이 큰 쿼리를 캐시하고 무거운 작업에는 백그라운드 작업을 사용하십시오.
- 모든 것을 로깅하십시오 -- 개발 중에 Sidekick의 UI를 볼 수 없으므로, 포괄적인 로깅이 최고의 디버깅 도구입니다.
AI 쇼핑 에이전트로 진행하여 Catalog API와 Checkout Kit을 사용하는 완전한 대화형 쇼핑 어시스턴트를 구축하는 방법을 알아보십시오.