Step-by-step playbooks for common shop launches, sales, and migrations.
These five playbooks walk through complete flows for a Discord supporter tier, a Telegram-only shop, a subscription switch, a Black Friday sale, and a platform migration.
In your Shoppex dashboard, open Channels → Discord.
Click Connect Discord. This is the OAuth step that links your Discord identity to your
Shoppex account.
Pick the target server from the dropdown that appears.
Click Invite Bot. Discord opens its OAuth approval flow asking you to authorize the
Shoppex bot on the server you picked.
The bot requests Manage Roles, Kick Members, View Channels, Send Messages,
and Embed Links. Accept.
Discord redirects you back to Shoppex with the bot connected.
In your Discord server settings, you will now see the Shoppex bot listed as a member.
Important: its role in the server hierarchy must sit above any role you intend to sell.
This is a Discord rule: bots can only manage roles below their own. If needed, drag the
Shoppex role up in Server Settings → Roles.
In Discord → Server Settings → Roles → Create Role. Give it a name like Supporter,
pick a color, set any permissions for private channels you want this role to see.You can now connect this role to a Shoppex product.
The subscription auto-renews against the gateway the buyer used at signup.
If renewal succeeds, the role stays. Neither you nor the buyer needs to do anything.
If a card or PayPal renewal fails, the provider retries and the role stays. It is removed
when Stripe stops retrying or the subscription is canceled.
A crypto or balance renewal has 7 days to be paid (1 to 30, in Settings › Store ›
Subscriptions). The role stays during these days. Unpaid, the subscription goes on hold
and the role is removed until the buyer pays, or the subscription ends, as you set it. See
Subscriptions.
Buyers can cancel anytime from their customer dashboard. Cancellation behavior depends on the
gateway: see Subscriptions for the specifics. Stripe and
crypto cancel at the end of the billing period. PayPal cancels immediately.
“Can I have multiple supporter tiers?” Yes. Create a separate product per tier
(Bronze / Silver / Gold), bound to different roles. A buyer can hold several at once.“Can I grant roles across multiple servers?” Not from one product. Assign Role binds
to one role on one server. To cover multiple servers, create multiple products and either
bundle them or use addons.“What if a buyer leaves my Discord server?” Shoppex cannot grant a role to someone who is
not in the server. The order pauses in pending-fulfillment until they rejoin. After they
rejoin, you can re-trigger fulfillment from the order page.“What if I delete the role?” Shoppex cannot grant a role that no longer exists. Existing
holders lose it implicitly, because the role is gone, and new orders fail to fulfill.
Do not delete a Discord role that is tied to an active subscription. Existing holders lose
the role, and new orders fail to fulfill.
See Subscriptions for trials, plan changes, retries, and pauses on
any subscription product.
DM your bot from a different Telegram account. Ask about a product, or say “I want to
buy X”. The agent will:
Find the product in your catalog.
Reply with the product info and a Pay now button.
Tapping the button opens the Shoppex hosted checkout in Telegram’s in-app browser.
The buyer pays through your normal gateways.
Order confirmation is delivered both through email and (if the buyer linked Discord/Telegram
to their customer profile) directly in the chat.
The payment itself happens on checkout.shoppex.io, not inside Telegram natively. The bot
generates a Shoppex payment link and hands it over through an inline button.
For ongoing engagement:Broadcasts are one-off announcements to a list. Draft a message, pick a segment or all
users, schedule it for later, or send immediately. Statuses: DRAFT, SCHEDULED, SENDING,
COMPLETED, CANCELLED, FAILED.Journeys are automated triggers. They fire when an event happens for a user. Available
trigger types:
ORDER_COMPLETED — thank-you flow after a purchase.
ABANDONED_CART — nudge buyers who opened checkout but did not pay.
PAYMENT_REMINDER — invoice past due reminder.
SUBSCRIPTION_RENEWAL — renewal heads-up.
MANUAL — fired by you or the API on demand.
Journeys can branch and wait, for example “if a buyer has not paid after 4 hours, send the
discount code”.
If you do not want anyone visiting yourshop.shoppex.io, turn off the managed storefront from
Settings → Shop. The field is managedStorefrontEnabled. Turn it off, and optionally add
a redirect URL, for example to your Telegram bot’s t.me link.After that, the public storefront URL no longer serves your shop. The Telegram bot is the
only entry point. Payment links and direct checkout URLs still work. They do not depend on
the storefront.
“Can the bot accept payment directly in Telegram (no redirect)?” Not currently. Shoppex
generates a Shoppex-hosted checkout URL and the bot sends it as an inline button. The buyer
taps, pays in Telegram’s in-app browser. There is no native Telegram Stars or native Telegram
payments integration.“Can buyers manage their subscription from the bot?” Yes for queries through the agent (“show
me my subscriptions”), but cancel and upgrade actions still go through their customer
dashboard on Shoppex.“Multiple bots for the same shop?” Each shop can connect multiple bots. This is useful for
testing in a separate bot before you swap the primary bot, or for running different language
versions.
This playbook moves a product line from single-use codes, like Steam keys or activation
tokens, to an auto-renewing subscription.It keeps the old product running, launches the new one, and moves customers over during the
renewal cycle. This is the safest migration path.
Technically Shoppex allows changing a product’s type (the type field is mutable on update).
But changing SERIALS to SUBSCRIPTION on a live product does not carry over what you
actually need. It creates no automatic Stripe plan, migrates no past buyers to the new
billing terms, and handles no pending serial deliveries.The clean path is to create a new subscription product alongside the old one, then
deactivate the old one once customers have moved.
Open Products → New product, the same page used in Discord supporter tier above:
Type: Subscription
Title: the new name (for example “Pro Access — Monthly”)
Price: monthly amount
Billing interval: Day / Week / Month / Year (and a count, for example interval=Month,
count=1 for monthly)
Trial period: optional, up to 60 days
In the Discord section (if applicable), bind a supporter role with Assign Role so
subscribers get access automatically. See Discord supporter tier
above for the full Discord setup.If your old product delivered files or serials on each purchase, set the subscription
product’s delivery type to match. Subscriptions can deliver SERIALS, FILE, SERVICE,
or DYNAMIC content on each renewal.Save the product. It is now live on your storefront.
There is no automated way to convert a buyer’s past one-time purchase into a subscription.
The payment method changes from one-off to recurring, and the gateway agreement is different.
The buyer must subscribe again on their own.The most reliable way to nudge them: offer a discount coupon on the first month of
subscription, restricted to existing customers. Create the coupon at Discounts
(/coupons):
Type: PERCENTAGE (or FIXED)
Value: whatever feels right (20-50% on first month is typical for migration)
validUntil: a hard cutoff
maxUses: total count to cap exposure
Share the code in the same announcement. See Black Friday sale below for the full set of
coupon fields and limits.
When the cutover date arrives, deactivate the old product instead of deleting it. From the
old product’s settings, toggle it inactive. It disappears from your storefront, but the past
orders, delivered codes, and customer records all stay intact.
Do not delete the old product. Deleting it breaks historical order references. Toggle it
inactive instead.
If the old product granted a Discord role, those grants stay. The buyer keeps the role until
you remove it manually. Most merchants either:
Let the old grants stand as a goodwill gesture (existing customers keep access forever).
Set a date and bulk-revoke from the Discord side, with a clear announcement.
Subscription-bound roles are auto-revoked on cancel (when Remove role on cancel is on for
the subscription product), so the role lifecycle is automatic going forward.
“Will the new subscription auto-charge buyers who had recurring billing somewhere else?”
No. Recurring billing is per-product per-buyer per-gateway. The new subscription is a fresh
authorization. The buyer goes through checkout once to set it up.“Can I keep both running indefinitely?” Yes. Some merchants keep a one-time purchase
option for buyers who prefer not to subscribe, alongside the subscription as the default. Make
sure the pricing makes the subscription the clearly better deal.
This two-week walkthrough runs a major sale on Shoppex, built around Black Friday but equally
usable for Cyber Monday, end-of-quarter sales, or a launch.
Pick the discount strategy. Coupon types Shoppex supports:
PERCENTAGE — N% off the order.
FIXED — fixed-amount discount.
(There is no built-in BOGO. For buy-one-get-one, use bundle products instead.)For each coupon, configurable limits:
maxUses — total redemptions across all buyers (cap the exposure).
minOrderAmount — minimum order subtotal to be eligible.
maxDiscount — cap the absolute discount (useful for percent codes on big orders).
validFrom / validUntil — time window. Coupon code returns invalid outside these times.
Product / variant binding — restrict to specific products. Without bindings, coupon
applies to anything.
Decide your codes:
A general code (BF25 for 25% off everything, capped at $X).
Product-line specific codes (PRO-BF for the Pro tier only).
VIP code with bigger discount, low max-uses, shared only with your top customers.
Create them at Discounts (/coupons).Build your email lists and segments. In Marketing → Email (/marketing/email), your
list of buyers is automatically maintained. Build segments based on what you want to target:
All past buyers.
Buyers in the last 90 days (recent and warm).
High-value buyers (LTV > $X).
Trial-only buyers (never converted to paid).
Segments are saved filters. Once you build one, it stays current as new customers come in.Draft the email. Email Marketing’s template system is MJML-based. You can either:
Use the builder to drag-and-drop the email.
Write MJML directly if you want pixel-precise control.
Personalize the email with variables: first name, the buyer’s most-bought category, or the
discount code itself. These variables come from the campaign-recipient context.Send a test to yourself before you schedule the campaign. A broken template can render
differently in each mail client.Build a parallel Telegram blast (if you use Telegram). The same idea works on the
Telegram side. Store → Telegram → Broadcasts → New broadcast.
Pick the target segment.
Compose the message (include the coupon code or a deeplink).
Schedule everything in advance. Do not manually click “Send” at 9am. Set the schedule the
night before instead. Both campaigns (emailMarketingCampaigns.scheduleAt) and Telegram
broadcasts support scheduled send. You wake up to the campaigns already going out.Make sure your coupons’ validFrom matches the announcement time. If you email at 9am with
a code that says “valid from 10am”, buyers will hit “invalid code” on the first 100 tries,
and you will lose them.Watch the dashboard. During the sale, watch these live indicators:
Email campaign status — sent / delivered / opened / clicked counts, available per
campaign.
Telegram broadcasts — same kind of stats, per broadcast.
Shoppex does not have a built-in coupon analytics dashboard. To see how many sales each code
drove, filter Orders by coupon code. Every order with a redeemed coupon has the code attached,
so you can read the count and revenue from there.React if something underperforms. If the email got delivered but conversions are flat,
consider:
A follow-up email 12-24 hours later with a different angle (urgency, social proof).
Lower the coupon’s minOrderAmount if you are getting “cart abandoned because code did not
apply” complaints.
Create a deeper discount code for an off-hours segment.
If conversions are too strong on a wholesale-margin product, you can mark the coupon
inactive during the sale. Buyers who already redeemed it are unaffected, but the code stops
working for everyone else.
Filter Orders by each coupon code. Count: total redemptions, average order value, total
revenue.
Compare the results against the same week last month, or last year if you have the data.
This shows the real lift from the sale, not only orders from your existing buyers.
Check Email Marketing stats: open rate, click rate, conversion rate per campaign.
Note which segment converted best. That is where you focus for the next campaign.
Save the coupons, but mark them inactive. Keeping the codes intact preserves your historical
record, since orders that redeemed them stay linked.
Forgetting maxUses on a percent code shared publicly. If someone leaks it, you end up
refunding a thousand orders. Always cap maxUses.
Email templates that break on iOS Mail. Test before scheduling. MJML compiles to
cross-client HTML but you still want to eyeball it.
Coupon stacking. Shoppex applies one coupon per cart. If buyers complain that they
cannot use both codes, that is expected. Pick which coupon wins, usually the larger
discount.
Shipping a sale on a day where one gateway is down. Test Stripe, PayPal, crypto
before the announcement goes out.
This guide migrates an existing shop from Sell.app, SellAuth, or Komerza to
Shoppex, using the same flow for every platform except the export step.The export step is the only part that differs per platform. The whole migration usually takes
one to two hours of active work, plus a few hours of DNS propagation in the background.
Step 1 — Export your data from your current platform
You are looking for: products with prices and descriptions, license keys / serial pools,
and customer order history if available. Most platforms expose this under “Data Export”,
“Backup”, or “Tools” in their dashboard. Exact menu paths shift over time, so check the
current vendor docs if anything has moved.The data shape you need is the same regardless of platform. The dump needs one row per
product, and one row per remaining serial or license key. If you have that, in CSV or JSON,
you can re-import everything.You do not need to re-upload customers. Shoppex creates new customer records as buyers come
in. Save the export anyway: it is your archive.
Step 2 — Sign up for Shoppex and pick your shop URL
At dashboard.shoppex.io, create an account. Pick a slug for
your default URL (for example yourshop.shoppex.io).If you plan to use a custom domain, the slug does not matter long-term. Buyers will reach
the custom domain instead.
This is the biggest difference from your old platform: you connect your own gateway
accounts, not Shoppex’s. Open Settings → Payment gateways. Set up each one you want:
Stripe — paste publishable and secret key from your Stripe dashboard.
PayPal SDK — paste client ID and secret from PayPal Developer Console.
PayPal F&F — your PayPal Business email.
Cash App — your $cashtag and Gmail forwarding.
Crypto — your wallet addresses, or Cryptomus / Oxapay API keys.
See Payment gateways for the full per-provider walkthrough.Important: if you were using merchant-of-record on the old platform (some platforms
operate as MoR by default), you will need to switch to your own gateways now. Shoppex does
not operate as MoR. Funds settle directly to your own Stripe, PayPal, or wallet accounts.
License keys / activation codes / Steam keys → Serials or Licenses (Licenses if
you need HWID-locking).
Discord access → Subscription, and assign a Discord role from the product’s Discord
section, the same role-binding steps as Discord supporter tier
above.
Monthly billing → Subscription.
Custom service / boost / design → Service.
If it is a serials product, paste your old key pool into the Serials tab.
If you have many products, doing this by hand is tedious. The Developer
API lets you script it. Write a small migration tool that reads your
old export and sends one product at a time to /dev/v1/products. There is no bulk-create
endpoint. Do not run too many requests at once, and respect the rate limit. The contracts are
documented in API Reference → Products.
You can choose between two strategies, depending on how much downtime you can tolerate.Cleanest: dual-domain transition. Keep your old shop running on its current domain. Set
up Shoppex on a new domain (for example new.yourbrand.com or yourbrand.shop). Test
thoroughly. When ready, swap DNS so the main domain points at Shoppex.This means you have two shops live at the same time for a few days while you confirm
Shoppex works for your buyers. You have no revenue gap during the switch.Fastest: direct swap. Update DNS on the day you are ready. Old shop goes dark when DNS
propagates.For the actual DNS setup, see Custom domain.
Shoppex URLs look different from your old platform’s. Old buyers, old social posts, and
search-engine results will hit dead URLs unless you redirect.If you control the old platform’s domain, set up a redirect rule. For Cloudflare:
Add the old domain to Cloudflare.
Rules → Redirect Rules → “If URL contains /product/, then 301 to
https://yourbrand.shoppex.io/product/{path}”.
For domains you cannot redirect, for example third-party platforms hosting old links, there
is nothing to do. You lose those click-throughs.
Send an email or Discord announcement explaining the move. Include:
The new shop URL.
Tell buyers that existing subscriptions on the old platform do not carry over. Stripe and
PayPal do not transfer subscriptions between merchants, so buyers must re-authorize the
recurring charge on Shoppex.
A link to your support channel for questions.
The subscription point is the most painful part of any migration. Communicate this clearly.
Monitor the new shop for a week or two. Check that there are no support tickets about missing
items, that search results are updated, and that social posts point at the new shop. Then
close the old account. Keep the export file permanently. It is your historical record.
Subscriptions do not migrate. This is the biggest surprise for most merchants. Buyers
must re-subscribe on Shoppex with their own payment method. Plan a transition window of a
month where you message them, ideally with a discount code to make it easier.
License keys you sold but never delivered, for example ones still in the old shop’s
pool, go into the Shoppex Serials pool. Once sold and delivered, they stay with the buyer
forever.
Customer wallet balances on the old shop cannot transfer. If buyers had store credit
on your old platform, you can manually re-credit their Shoppex wallet from the Customers
page as a goodwill gesture.
Disputes filed on old gateway accounts stay with those gateways. Watch your old
Stripe / PayPal dashboards for a few months after the cut-over.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Shoppex","colors":{"primary":"#7C3AED","light":"#A78BFA","dark":"#6D28D9"},"logo":{"light":"https://mintcdn.com/shoppex/-b-8YcG0h9UQ6CtI/logo/light.svg?fit=max\u0026auto=format\u0026n=-b-8YcG0h9UQ6CtI\u0026q=85\u0026s=f9f78c42d17f9c45132fbd41cfdf401b","dark":"https://mintcdn.com/shoppex/-b-8YcG0h9UQ6CtI/logo/dark.svg?fit=max\u0026auto=format\u0026n=-b-8YcG0h9UQ6CtI\u0026q=85\u0026s=fff5c87a9643e76fda746d99e4c17801"},"favicon":"https://mintcdn.com/shoppex/u3ztnB0b9rxdxJkJ/favicon.svg?fit=max\u0026auto=format\u0026n=u3ztnB0b9rxdxJkJ\u0026q=85\u0026s=2fd07ab5131df2b2ca66d80a48d54ed5","api":{"playground":{"display":"interactive"},"examples":{"languages":["curl","javascript","python","php","go"]},"mdx":{"auth":{"method":"bearer","name":"Authorization"},"server":"https://api.shoppex.io"}},"appearance":{"default":"system","strict":false},"navbar":{"primary":{"type":"button","label":"Dashboard","href":"https://dashboard.shoppex.io"}},"footer":{"socials":{"github":"https://github.com/ShoppexIO"}},"search":{"prompt":"Search Shoppex docs..."},"fonts":{"heading":{"family":"Geist","weight":700},"body":{"family":"Geist"}},"styling":{"codeblocks":"system","latex":true},"contextual":{"options":["copy","view","chatgpt","claude","cursor","vscode"],"display":"header"},"metadata":{"timestamp":false},"navigation":{"global":{"anchors":[{"anchor":"Discord","icon":"discord","href":"https://discord.gg/VjrptT6Nvx"},{"anchor":"Telegram","icon":"telegram","href":"https://t.me/shoppexhq"}]},"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"shoppex","hasAudioNarration":false,"actualSubdomain":"shoppex","customDomains":["docs.shoppex.io"],"gitSource":{"type":"github","owner":"shoppexio","repo":"shoppex","deployBranch":"main","contentDirectory":"apps/docs","isPrivate":true,"mountPath":"","label":""},"chroma":{"liveDeploymentHistoryId":"6ae7619cf80d76da9488ba63","collectionId":"d36d0199-1caa-441d-bd1a-11d56fa76795","schemaVersion":"v3","latestBuiltDeploymentHistoryId":"6ae7619cf80d76da9488ba63"},"entitlements":{},"buildId":"6ae7619cf80d76da9488ba63","clientVersion":"0.0.4054","searchFilterCounts":[{"language":"default","tag":"API reference","count":320},{"language":"default","tag":"Products","count":45},{"language":"default","tag":"Developers","count":43},{"language":"default","tag":"Telegram","count":31},{"language":"default","tag":"Guides","count":23},{"language":"default","tag":"Store","count":20},{"language":"default","tag":"Affiliates","count":18},{"language":"default","tag":"Customers","count":17},{"language":"default","tag":"Themes","count":17},{"language":"default","tag":"Email Marketing","count":17}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"byok-sep-25","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-updated-9-15","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":true},"customCss":[],"page":{"pagePath":"playbooks/overview","slug":"/playbooks/overview","pageMetadata":{"title":"Playbooks","description":"Step-by-step playbooks for common shop launches, sales, and migrations.","icon":"book-open","href":"/playbooks/overview"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Step-by-step playbooks for common shop launches, sales, and migrations.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,em:`em`,li:`li`,ol:`ol`,p:`p`,strong:`strong`,ul:`ul`,..._provideComponents(),...props.components},{Heading,Warning}=_components;if(!Heading)_missingMdxReference(`Heading`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsx(_components.p,{children:`These five playbooks walk through complete flows for a Discord supporter tier, a Telegram-only shop, a subscription switch, a Black Friday sale, and a platform migration.`}),`\n`,_jsx(Heading,{level:`2`,id:`discord-supporter-tier`,children:`Discord supporter tier`}),`\n`,_jsx(_components.p,{children:`This walkthrough takes you from a Discord server with no monetization to a working paid\nsupporter tier in about 20 minutes.`}),`\n`,_jsx(Heading,{level:`3`,id:`what-you-will-have-at-the-end`,children:`What you will have at the end`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`A Discord role that gets granted automatically when someone subscribes on your shop.`}),`\n`,_jsx(_components.li,{children:`The role is revoked when the subscription is canceled or fails, as long as “Remove role on\ncancel” stays on. This setting is on by default.`}),`\n`,_jsx(_components.li,{children:`A customer dashboard your buyers use to manage their subscription themselves.`}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`prerequisites`,children:`Prerequisites`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`A Discord server you own (you need `,_jsx(_components.code,{children:`Manage Server`}),` permission).`]}),`\n`,_jsxs(_components.li,{children:[`A Shoppex shop with at least one payment gateway connected. If you do not have one, do\n`,_jsx(_components.a,{href:`/start/quickstart`,children:`Quickstart`}),` first.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`step-1-—-connect-discord-and-invite-the-bot`,children:`Step 1 — Connect Discord and invite the bot`}),`\n`,_jsxs(_components.p,{children:[`In your Shoppex dashboard, open `,_jsx(_components.strong,{children:`Channels → Discord`}),`.`]}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Click `,_jsx(_components.strong,{children:`Connect Discord`}),`. This is the OAuth step that links your Discord identity to your\nShoppex account.`]}),`\n`,_jsx(_components.li,{children:`Pick the target server from the dropdown that appears.`}),`\n`,_jsxs(_components.li,{children:[`Click `,_jsx(_components.strong,{children:`Invite Bot`}),`. Discord opens its OAuth approval flow asking you to authorize the\nShoppex bot on the server you picked.`]}),`\n`,_jsxs(_components.li,{children:[`The bot requests `,_jsx(_components.strong,{children:`Manage Roles`}),`, `,_jsx(_components.strong,{children:`Kick Members`}),`, `,_jsx(_components.strong,{children:`View Channels`}),`, `,_jsx(_components.strong,{children:`Send Messages`}),`,\nand `,_jsx(_components.strong,{children:`Embed Links`}),`. Accept.`]}),`\n`,_jsx(_components.li,{children:`Discord redirects you back to Shoppex with the bot connected.`}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`In your Discord server settings, you will now see the Shoppex bot listed as a member.\n`,_jsx(_components.strong,{children:`Important:`}),` its role in the server hierarchy must sit `,_jsx(_components.em,{children:`above`}),` any role you intend to sell.\nThis is a Discord rule: bots can only manage roles below their own. If needed, drag the\nShoppex role up in `,_jsx(_components.strong,{children:`Server Settings → Roles`}),`.`]}),`\n`,_jsx(Heading,{level:`3`,id:`step-2-—-create-the-supporter-role`,children:`Step 2 — Create the supporter role`}),`\n`,_jsxs(_components.p,{children:[`In Discord → `,_jsx(_components.strong,{children:`Server Settings → Roles → Create Role`}),`. Give it a name like `,_jsx(_components.code,{children:`Supporter`}),`,\npick a color, set any permissions for private channels you want this role to see.`]}),`\n`,_jsx(_components.p,{children:`You can now connect this role to a Shoppex product.`}),`\n`,_jsx(Heading,{level:`3`,id:`step-3-—-create-the-subscription-product`,children:`Step 3 — Create the subscription product`}),`\n`,_jsxs(_components.p,{children:[`Back in Shoppex → `,_jsx(_components.strong,{children:`Products → New product`}),`.`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Type:`}),` Subscription (this is the product’s `,_jsx(_components.strong,{children:`Type`}),` field, not the Discord role. The\nDiscord role comes next.)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Title:`}),` “Supporter — Monthly” (or whatever fits).`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Price:`}),` Set monthly amount and billing interval.`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`Then scroll to the product’s `,_jsx(_components.strong,{children:`Discord`}),` section and:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Toggle `,_jsx(_components.strong,{children:`Assign Role`}),` on.`]}),`\n`,_jsx(_components.li,{children:`Pick the server.`}),`\n`,_jsxs(_components.li,{children:[`Pick the `,_jsx(_components.code,{children:`Supporter`}),` role (loaded live from your server).`]}),`\n`,_jsxs(_components.li,{children:[`Leave `,_jsx(_components.strong,{children:`Remove role on cancel`}),` on (the default) so the role gets revoked when the\nsubscription ends.`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`Save the product. It is now live on `,_jsx(_components.code,{children:`yourshop.shoppex.io`}),`.`]}),`\n`,_jsx(Heading,{level:`3`,id:`step-4-—-test-the-flow-yourself`,children:`Step 4 — Test the flow yourself`}),`\n`,_jsx(_components.p,{children:`Open your shop in an incognito window. Buy the product with one of your own gateways (or use\na Stripe test key if you connected one). You will see:`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsx(_components.li,{children:`Checkout asks you to link your Discord account.`}),`\n`,_jsx(_components.li,{children:`You authorize through Discord OAuth.`}),`\n`,_jsx(_components.li,{children:`You pay.`}),`\n`,_jsx(_components.li,{children:`Within a few seconds, the Supporter role appears on your Discord account.`}),`\n`]}),`\n`,_jsx(_components.p,{children:`If anything stalls, the order page in your dashboard tells you exactly which step is pending.`}),`\n`,_jsx(Heading,{level:`3`,id:`step-5-—-announce-it`,children:`Step 5 — Announce it`}),`\n`,_jsx(_components.p,{children:`Share the product link in your server (or anywhere). Buyers click → checkout → done.`}),`\n`,_jsx(Heading,{level:`3`,id:`what-happens-when-someone-subscribes`,children:`What happens when someone subscribes`}),`\n`,_jsx(_components.p,{children:`Each month:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`The subscription auto-renews against the gateway the buyer used at signup.`}),`\n`,_jsx(_components.li,{children:`If renewal succeeds, the role stays. Neither you nor the buyer needs to do anything.`}),`\n`,_jsx(_components.li,{children:`If a card or PayPal renewal fails, the provider retries and the role stays. It is removed\nwhen Stripe stops retrying or the subscription is canceled.`}),`\n`,_jsxs(_components.li,{children:[`A crypto or balance renewal has 7 days to be paid (1 to 30, in `,_jsx(_components.strong,{children:`Settings › Store ›\nSubscriptions`}),`). The role stays during these days. Unpaid, the subscription goes on hold\nand the role is removed until the buyer pays, or the subscription ends, as you set it. See\n`,_jsx(_components.a,{href:`/selling/subscriptions#renewals`,children:`Subscriptions`}),`.`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`Buyers can cancel anytime from their customer dashboard. Cancellation behavior depends on the\ngateway: see `,_jsx(_components.a,{href:`/selling/subscriptions#cancellation`,children:`Subscriptions`}),` for the specifics. Stripe and\ncrypto cancel at the end of the billing period. PayPal cancels immediately.`]}),`\n`,_jsx(Heading,{level:`3`,id:`common-questions`,children:`Common questions`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`“Can I have multiple supporter tiers?”`}),` Yes. Create a separate product per tier\n(Bronze / Silver / Gold), bound to different roles. A buyer can hold several at once.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`“Can I grant roles across multiple servers?”`}),` Not from one product. `,_jsx(_components.strong,{children:`Assign Role`}),` binds\nto one role on one server. To cover multiple servers, create multiple products and either\nbundle them or use addons.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`“What if a buyer leaves my Discord server?”`}),` Shoppex cannot grant a role to someone who is\nnot in the server. The order pauses in pending-fulfillment until they rejoin. After they\nrejoin, you can re-trigger fulfillment from the order page.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`“What if I delete the role?”`}),` Shoppex cannot grant a role that no longer exists. Existing\nholders lose it implicitly, because the role is gone, and new orders fail to fulfill.`]}),`\n`,_jsx(Warning,{children:_jsx(_components.p,{children:`Do not delete a Discord role that is tied to an active subscription. Existing holders lose\nthe role, and new orders fail to fulfill.`})}),`\n`,_jsxs(_components.p,{children:[`See `,_jsx(_components.a,{href:`/selling/subscriptions`,children:`Subscriptions`}),` for trials, plan changes, retries, and pauses on\nany subscription product.`]}),`\n`,_jsx(Heading,{level:`2`,id:`telegram-only-shop`,children:`Telegram-only shop`}),`\n`,_jsx(_components.p,{children:`This playbook connects a Telegram bot for sales and, if you want, hides the web storefront so\nTelegram is the only sales channel.`}),`\n`,_jsx(Heading,{level:`3`,id:`what-you-will-have-at-the-end-2`,children:`What you will have at the end`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`A Telegram bot connected to your Shoppex shop.`}),`\n`,_jsx(_components.li,{children:`The bot answers buyer questions and creates payment links right in the chat.`}),`\n`,_jsx(_components.li,{children:`Broadcasts and journeys to bring buyers back.`}),`\n`,_jsxs(_components.li,{children:[`(Optional) The web storefront at `,_jsx(_components.code,{children:`yourshop.shoppex.io`}),` disabled, so the bot is the only\nsales channel.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`prerequisites-2`,children:`Prerequisites`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`A Telegram bot you have created with `,_jsx(_components.strong,{children:`@BotFather`}),` on Telegram. You will need its API\ntoken, the long string that BotFather sends you after `,_jsx(_components.code,{children:`/newbot`}),`.`]}),`\n`,_jsx(_components.li,{children:`A Shoppex shop with at least one payment gateway connected.`}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`step-1-—-connect-the-bot`,children:`Step 1 — Connect the bot`}),`\n`,_jsxs(_components.p,{children:[`Open your Shoppex dashboard at `,_jsx(_components.strong,{children:`Store → Telegram`}),` (`,_jsx(_components.code,{children:`/store/telegram`}),`).`]}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Click `,_jsx(_components.strong,{children:`Connect bot`}),` or `,_jsx(_components.strong,{children:`Add bot`}),`.`]}),`\n`,_jsx(_components.li,{children:`Paste the bot token from BotFather.`}),`\n`,_jsx(_components.li,{children:`Save.`}),`\n`]}),`\n`,_jsx(_components.p,{children:`Shoppex verifies the token, fetches the bot’s profile, and registers it against your shop.\nThe bot is now connected and listening.`}),`\n`,_jsx(Heading,{level:`3`,id:`step-2-—-turn-on-the-ai-sales-agent`,children:`Step 2 — Turn on the AI sales agent`}),`\n`,_jsxs(_components.p,{children:[`In the same Telegram page, configure the bot’s `,_jsx(_components.strong,{children:`Agent`}),`. There are three modes:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:_jsx(_components.code,{children:`CUSTOMER_SALES`})}),` — the bot talks to buyers, answers product questions, creates payment\nlinks when they want to buy.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:_jsx(_components.code,{children:`MERCHANT_ASSISTANT`})}),` — the bot works for you only: DM it to check orders or get daily\nrevenue. It does not talk to buyers.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:_jsx(_components.code,{children:`BOTH`})}),` — the same bot serves buyers and you, distinguished by who is chatting.`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`For a sales-channel use case, pick `,_jsx(_components.strong,{children:_jsx(_components.code,{children:`CUSTOMER_SALES`})}),` (or `,_jsx(_components.code,{children:`BOTH`}),` if you also want to use\nthe bot yourself).`]}),`\n`,_jsx(Heading,{level:`3`,id:`step-3-—-test-a-purchase`,children:`Step 3 — Test a purchase`}),`\n`,_jsx(_components.p,{children:`DM your bot from a different Telegram account. Ask about a product, or say “I want to\nbuy X”. The agent will:`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsx(_components.li,{children:`Find the product in your catalog.`}),`\n`,_jsxs(_components.li,{children:[`Reply with the product info and a `,_jsx(_components.strong,{children:`Pay now`}),` button.`]}),`\n`,_jsx(_components.li,{children:`Tapping the button opens the Shoppex hosted checkout in Telegram’s in-app browser.`}),`\n`,_jsx(_components.li,{children:`The buyer pays through your normal gateways.`}),`\n`,_jsx(_components.li,{children:`Order confirmation is delivered both through email and (if the buyer linked Discord/Telegram\nto their customer profile) directly in the chat.`}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`The payment itself happens on `,_jsx(_components.code,{children:`checkout.shoppex.io`}),`, not inside Telegram natively. The bot\ngenerates a Shoppex payment link and hands it over through an inline button.`]}),`\n`,_jsx(Heading,{level:`3`,id:`step-4-—-build-out-user-management`,children:`Step 4 — Build out user management`}),`\n`,_jsxs(_components.p,{children:[`Once buyers start interacting, the `,_jsx(_components.strong,{children:`Users`}),` section of the Telegram dashboard fills up.\nYou can:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`See who has chatted with the bot (with last-seen, total interactions).`}),`\n`,_jsx(_components.li,{children:`Toggle per-user notification settings.`}),`\n`,_jsxs(_components.li,{children:[`Build `,_jsx(_components.strong,{children:`Segments`}),`, saved filters like “buyers in the last 30 days” or “VIPs over $500”.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`step-5-—-set-up-broadcasts-and-journeys`,children:`Step 5 — Set up broadcasts and journeys`}),`\n`,_jsx(_components.p,{children:`For ongoing engagement:`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Broadcasts`}),` are one-off announcements to a list. Draft a message, pick a segment or all\nusers, schedule it for later, or send immediately. Statuses: `,_jsx(_components.code,{children:`DRAFT`}),`, `,_jsx(_components.code,{children:`SCHEDULED`}),`, `,_jsx(_components.code,{children:`SENDING`}),`,\n`,_jsx(_components.code,{children:`COMPLETED`}),`, `,_jsx(_components.code,{children:`CANCELLED`}),`, `,_jsx(_components.code,{children:`FAILED`}),`.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Journeys`}),` are automated triggers. They fire when an event happens for a user. Available\ntrigger types:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`ORDER_COMPLETED`}),` — thank-you flow after a purchase.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`ABANDONED_CART`}),` — nudge buyers who opened checkout but did not pay.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`PAYMENT_REMINDER`}),` — invoice past due reminder.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`SUBSCRIPTION_RENEWAL`}),` — renewal heads-up.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`MANUAL`}),` — fired by you or the API on demand.`]}),`\n`]}),`\n`,_jsx(_components.p,{children:`Journeys can branch and wait, for example “if a buyer has not paid after 4 hours, send the\ndiscount code”.`}),`\n`,_jsx(Heading,{level:`3`,id:`step-6-—-optional-disable-the-web-storefront`,children:`Step 6 — (Optional) Disable the web storefront`}),`\n`,_jsxs(_components.p,{children:[`If you do not want anyone visiting `,_jsx(_components.code,{children:`yourshop.shoppex.io`}),`, turn off the managed storefront from\n`,_jsx(_components.strong,{children:`Settings → Shop`}),`. The field is `,_jsx(_components.code,{children:`managedStorefrontEnabled`}),`. Turn it off, and optionally add\na redirect URL, for example to your Telegram bot’s t.me link.`]}),`\n`,_jsx(_components.p,{children:`After that, the public storefront URL no longer serves your shop. The Telegram bot is the\nonly entry point. Payment links and direct checkout URLs still work. They do not depend on\nthe storefront.`}),`\n`,_jsx(Heading,{level:`3`,id:`common-questions-2`,children:`Common questions`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`“Can the bot accept payment directly in Telegram (no redirect)?”`}),` Not currently. Shoppex\ngenerates a Shoppex-hosted checkout URL and the bot sends it as an inline button. The buyer\ntaps, pays in Telegram’s in-app browser. There is no native Telegram Stars or native Telegram\npayments integration.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`“Can buyers manage their subscription from the bot?”`}),` Yes for queries through the agent (“show\nme my subscriptions”), but cancel and upgrade actions still go through their customer\ndashboard on Shoppex.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`“Multiple bots for the same shop?”`}),` Each shop can connect multiple bots. This is useful for\ntesting in a separate bot before you swap the primary bot, or for running different language\nversions.`]}),`\n`,_jsx(Heading,{level:`2`,id:`switch-to-recurring`,children:`Switch to recurring`}),`\n`,_jsx(_components.p,{children:`This playbook moves a product line from single-use codes, like Steam keys or activation\ntokens, to an auto-renewing subscription.`}),`\n`,_jsx(_components.p,{children:`It keeps the old product running, launches the new one, and moves customers over during the\nrenewal cycle. This is the safest migration path.`}),`\n`,_jsx(Heading,{level:`3`,id:`why-not-edit-the-existing-product`,children:`Why not edit the existing product?`}),`\n`,_jsxs(_components.p,{children:[`Technically Shoppex allows changing a product’s `,_jsx(_components.code,{children:`type`}),` (the type field is mutable on update).\nBut changing `,_jsx(_components.code,{children:`SERIALS`}),` to `,_jsx(_components.code,{children:`SUBSCRIPTION`}),` on a live product does not carry over what you\nactually need. It creates no automatic Stripe plan, migrates no past buyers to the new\nbilling terms, and handles no pending serial deliveries.`]}),`\n`,_jsxs(_components.p,{children:[`The clean path is to `,_jsx(_components.strong,{children:`create a new subscription product`}),` alongside the old one, then\ndeactivate the old one once customers have moved.`]}),`\n`,_jsx(Heading,{level:`3`,id:`step-1-—-create-the-subscription-product`,children:`Step 1 — Create the subscription product`}),`\n`,_jsxs(_components.p,{children:[`Open `,_jsx(_components.strong,{children:`Products → New product`}),`, the same page used in Discord supporter tier above:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Type:`}),` Subscription`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Title:`}),` the new name (for example “Pro Access — Monthly”)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Price:`}),` monthly amount`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Billing interval:`}),` Day / Week / Month / Year (and a count, for example interval=Month,\ncount=1 for monthly)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Trial period:`}),` optional, up to 60 days`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`In the `,_jsx(_components.strong,{children:`Discord`}),` section (if applicable), bind a supporter role with `,_jsx(_components.strong,{children:`Assign Role`}),` so\nsubscribers get access automatically. See `,_jsx(_components.a,{href:`#discord-supporter-tier`,children:`Discord supporter tier`}),`\nabove for the full Discord setup.`]}),`\n`,_jsxs(_components.p,{children:[`If your old product delivered files or serials on each purchase, set the subscription\nproduct’s `,_jsx(_components.strong,{children:`delivery type`}),` to match. Subscriptions can deliver `,_jsx(_components.code,{children:`SERIALS`}),`, `,_jsx(_components.code,{children:`FILE`}),`, `,_jsx(_components.code,{children:`SERVICE`}),`,\nor `,_jsx(_components.code,{children:`DYNAMIC`}),` content on each renewal.`]}),`\n`,_jsx(_components.p,{children:`Save the product. It is now live on your storefront.`}),`\n`,_jsx(Heading,{level:`3`,id:`step-2-—-announce-the-change-to-existing-buyers`,children:`Step 2 — Announce the change to existing buyers`}),`\n`,_jsx(_components.p,{children:`Email or message your existing customer list. Be explicit:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`The old product (one-time codes) is staying available through a specific date.`}),`\n`,_jsx(_components.li,{children:`The new subscription product is now live. Mention its benefits: for example a lower\nmonthly price, better access, or automatic renewal.`}),`\n`,_jsx(_components.li,{children:`After the cutover date, only the subscription product will be sold.`}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`Tools available to you: the built-in email marketing (`,_jsx(_components.strong,{children:`Marketing → Email`}),`), Telegram\nbroadcasts if you have a bot, and Discord announcements.`]}),`\n`,_jsx(Heading,{level:`3`,id:`step-3-—-move-the-old-buyers`,children:`Step 3 — Move the old buyers`}),`\n`,_jsx(_components.p,{children:`There is no automated way to convert a buyer’s past one-time purchase into a subscription.\nThe payment method changes from one-off to recurring, and the gateway agreement is different.\nThe buyer must subscribe again on their own.`}),`\n`,_jsxs(_components.p,{children:[`The most reliable way to nudge them: offer a discount coupon on the first month of\nsubscription, restricted to existing customers. Create the coupon at `,_jsx(_components.strong,{children:`Discounts`}),`\n(`,_jsx(_components.code,{children:`/coupons`}),`):`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Type: `,_jsx(_components.code,{children:`PERCENTAGE`}),` (or `,_jsx(_components.code,{children:`FIXED`}),`)`]}),`\n`,_jsx(_components.li,{children:`Value: whatever feels right (20-50% on first month is typical for migration)`}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`validUntil`}),`: a hard cutoff`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`maxUses`}),`: total count to cap exposure`]}),`\n`]}),`\n`,_jsx(_components.p,{children:`Share the code in the same announcement. See Black Friday sale below for the full set of\ncoupon fields and limits.`}),`\n`,_jsx(Heading,{level:`3`,id:`step-4-—-wind-down-the-old-product`,children:`Step 4 — Wind down the old product`}),`\n`,_jsx(_components.p,{children:`When the cutover date arrives, deactivate the old product instead of deleting it. From the\nold product’s settings, toggle it inactive. It disappears from your storefront, but the past\norders, delivered codes, and customer records all stay intact.`}),`\n`,_jsx(Warning,{children:_jsx(_components.p,{children:`Do not delete the old product. Deleting it breaks historical order references. Toggle it\ninactive instead.`})}),`\n`,_jsx(Heading,{level:`3`,id:`what-about-discord-roles-already-granted`,children:`What about Discord roles already granted?`}),`\n`,_jsx(_components.p,{children:`If the old product granted a Discord role, those grants stay. The buyer keeps the role until\nyou remove it manually. Most merchants either:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Let the old grants stand as a goodwill gesture (existing customers keep access forever).`}),`\n`,_jsx(_components.li,{children:`Set a date and bulk-revoke from the Discord side, with a clear announcement.`}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`Subscription-bound roles are auto-revoked on cancel (when `,_jsx(_components.strong,{children:`Remove role on cancel`}),` is on for\nthe subscription product), so the role lifecycle is automatic going forward.`]}),`\n`,_jsx(Heading,{level:`3`,id:`common-questions-3`,children:`Common questions`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`“Will the new subscription auto-charge buyers who had recurring billing somewhere else?”`}),`\nNo. Recurring billing is per-product per-buyer per-gateway. The new subscription is a fresh\nauthorization. The buyer goes through checkout once to set it up.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`“Can I keep both running indefinitely?”`}),` Yes. Some merchants keep a one-time purchase\noption for buyers who prefer not to subscribe, alongside the subscription as the default. Make\nsure the pricing makes the subscription the clearly better deal.`]}),`\n`,_jsx(Heading,{level:`2`,id:`black-friday-sale`,children:`Black Friday sale`}),`\n`,_jsx(_components.p,{children:`This two-week walkthrough runs a major sale on Shoppex, built around Black Friday but equally\nusable for Cyber Monday, end-of-quarter sales, or a launch.`}),`\n`,_jsx(Heading,{level:`3`,id:`what-you-will-do`,children:`What you will do`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Prep your catalog (which products are on sale, by how much).`}),`\n`,_jsx(_components.li,{children:`Create coupon codes, with limits and product-targeting.`}),`\n`,_jsx(_components.li,{children:`Build the buyer list to email and Telegram-blast.`}),`\n`,_jsx(_components.li,{children:`Schedule the email campaign for the moment the sale opens.`}),`\n`,_jsx(_components.li,{children:`Track conversions live and react if something underperforms.`}),`\n`,_jsx(_components.li,{children:`Run the post-mortem.`}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`two-weeks-before-—-prep`,children:`Two weeks before — prep`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Pick the discount strategy.`}),` Coupon types Shoppex supports:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:_jsx(_components.code,{children:`PERCENTAGE`})}),` — N% off the order.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:_jsx(_components.code,{children:`FIXED`})}),` — fixed-amount discount.`]}),`\n`]}),`\n`,_jsx(_components.p,{children:`(There is no built-in BOGO. For buy-one-get-one, use bundle products instead.)`}),`\n`,_jsx(_components.p,{children:`For each coupon, configurable limits:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`maxUses`}),` — total redemptions across all buyers (cap the exposure).`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`minOrderAmount`}),` — minimum order subtotal to be eligible.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`maxDiscount`}),` — cap the absolute discount (useful for percent codes on big orders).`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`validFrom`}),` / `,_jsx(_components.code,{children:`validUntil`}),` — time window. Coupon code returns invalid outside these times.`]}),`\n`,_jsx(_components.li,{children:`Product / variant binding — restrict to specific products. Without bindings, coupon\napplies to anything.`}),`\n`]}),`\n`,_jsx(_components.p,{children:`Decide your codes:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`A general code (`,_jsx(_components.code,{children:`BF25`}),` for 25% off everything, capped at $X).`]}),`\n`,_jsxs(_components.li,{children:[`Product-line specific codes (`,_jsx(_components.code,{children:`PRO-BF`}),` for the Pro tier only).`]}),`\n`,_jsx(_components.li,{children:`VIP code with bigger discount, low max-uses, shared only with your top customers.`}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`Create them at `,_jsx(_components.strong,{children:`Discounts`}),` (`,_jsx(_components.code,{children:`/coupons`}),`).`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Build your email lists and segments.`}),` In `,_jsx(_components.strong,{children:`Marketing → Email`}),` (`,_jsx(_components.code,{children:`/marketing/email`}),`), your\nlist of buyers is automatically maintained. Build segments based on what you want to target:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`All past buyers.`}),`\n`,_jsx(_components.li,{children:`Buyers in the last 90 days (recent and warm).`}),`\n`,_jsx(_components.li,{children:`High-value buyers (LTV > $X).`}),`\n`,_jsx(_components.li,{children:`Trial-only buyers (never converted to paid).`}),`\n`]}),`\n`,_jsx(_components.p,{children:`Segments are saved filters. Once you build one, it stays current as new customers come in.`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Draft the email.`}),` Email Marketing’s template system is `,_jsx(_components.strong,{children:`MJML-based`}),`. You can either:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Use the `,_jsx(_components.strong,{children:`builder`}),` to drag-and-drop the email.`]}),`\n`,_jsx(_components.li,{children:`Write MJML directly if you want pixel-precise control.`}),`\n`]}),`\n`,_jsx(_components.p,{children:`Personalize the email with variables: first name, the buyer’s most-bought category, or the\ndiscount code itself. These variables come from the campaign-recipient context.`}),`\n`,_jsx(_components.p,{children:`Send a test to yourself before you schedule the campaign. A broken template can render\ndifferently in each mail client.`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Build a parallel Telegram blast (if you use Telegram).`}),` The same idea works on the\nTelegram side. `,_jsx(_components.strong,{children:`Store → Telegram → Broadcasts → New broadcast.`})]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Pick the target segment.`}),`\n`,_jsx(_components.li,{children:`Compose the message (include the coupon code or a deeplink).`}),`\n`,_jsx(_components.li,{children:`Schedule for the same moment as the email.`}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`sale-day-—-go-live`,children:`Sale day — go live`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Schedule everything in advance.`}),` Do not manually click “Send” at 9am. Set the schedule the\nnight before instead. Both campaigns (`,_jsx(_components.code,{children:`emailMarketingCampaigns.scheduleAt`}),`) and Telegram\nbroadcasts support scheduled send. You wake up to the campaigns already going out.`]}),`\n`,_jsxs(_components.p,{children:[`Make sure your coupons’ `,_jsx(_components.code,{children:`validFrom`}),` matches the announcement time. If you email at 9am with\na code that says “valid from 10am”, buyers will hit “invalid code” on the first 100 tries,\nand you will lose them.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Watch the dashboard.`}),` During the sale, watch these live indicators:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Analytics → Revenue`}),` (`,_jsx(_components.code,{children:`/analytics`}),`) — running revenue total.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Orders`}),` page — orders coming in, filterable.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Email campaign status`}),` — sent / delivered / opened / clicked counts, available per\ncampaign.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Telegram broadcasts`}),` — same kind of stats, per broadcast.`]}),`\n`]}),`\n`,_jsx(_components.p,{children:`Shoppex does not have a built-in coupon analytics dashboard. To see how many sales each code\ndrove, filter Orders by coupon code. Every order with a redeemed coupon has the code attached,\nso you can read the count and revenue from there.`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`React if something underperforms.`}),` If the email got delivered but conversions are flat,\nconsider:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`A follow-up email 12-24 hours later with a different angle (urgency, social proof).`}),`\n`,_jsxs(_components.li,{children:[`Lower the coupon’s `,_jsx(_components.code,{children:`minOrderAmount`}),` if you are getting “cart abandoned because code did not\napply” complaints.`]}),`\n`,_jsx(_components.li,{children:`Create a deeper discount code for an off-hours segment.`}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`If conversions are `,_jsx(_components.em,{children:`too`}),` strong on a wholesale-margin product, you can mark the coupon\ninactive during the sale. Buyers who already redeemed it are unaffected, but the code stops\nworking for everyone else.`]}),`\n`,_jsx(Heading,{level:`3`,id:`after-the-sale-—-post-mortem`,children:`After the sale — post-mortem`}),`\n`,_jsx(_components.p,{children:`Within a few days of close:`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsx(_components.li,{children:`Filter Orders by each coupon code. Count: total redemptions, average order value, total\nrevenue.`}),`\n`,_jsx(_components.li,{children:`Compare the results against the same week last month, or last year if you have the data.\nThis shows the real lift from the sale, not only orders from your existing buyers.`}),`\n`,_jsx(_components.li,{children:`Check Email Marketing stats: open rate, click rate, conversion rate per campaign.`}),`\n`,_jsx(_components.li,{children:`Note which segment converted best. That is where you focus for the next campaign.`}),`\n`]}),`\n`,_jsx(_components.p,{children:`Save the coupons, but mark them inactive. Keeping the codes intact preserves your historical\nrecord, since orders that redeemed them stay linked.`}),`\n`,_jsx(Heading,{level:`3`,id:`common-pitfalls`,children:`Common pitfalls`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsxs(_components.strong,{children:[`Forgetting `,_jsx(_components.code,{children:`maxUses`})]}),` on a percent code shared publicly. If someone leaks it, you end up\nrefunding a thousand orders. Always cap `,_jsx(_components.code,{children:`maxUses`}),`.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Email templates that break on iOS Mail.`}),` Test before scheduling. MJML compiles to\ncross-client HTML but you still want to eyeball it.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Coupon stacking.`}),` Shoppex applies one coupon per cart. If buyers complain that they\ncannot use both codes, that is expected. Pick which coupon wins, usually the larger\ndiscount.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Shipping a sale on a day where one gateway is down.`}),` Test Stripe, PayPal, crypto\n`,_jsx(_components.em,{children:`before`}),` the announcement goes out.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`migrate-to-shoppex`,children:`Migrate to Shoppex`}),`\n`,_jsxs(_components.p,{children:[`This guide migrates an existing shop from `,_jsx(_components.strong,{children:`Sell.app`}),`, `,_jsx(_components.strong,{children:`SellAuth`}),`, or `,_jsx(_components.strong,{children:`Komerza`}),` to\nShoppex, using the same flow for every platform except the export step.`]}),`\n`,_jsx(_components.p,{children:`The export step is the only part that differs per platform. The whole migration usually takes\none to two hours of active work, plus a few hours of DNS propagation in the background.`}),`\n`,_jsx(Heading,{level:`3`,id:`what-you-will-have-at-the-end-3`,children:`What you will have at the end`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`All your products live on Shoppex with the same SKUs.`}),`\n`,_jsx(_components.li,{children:`Payment gateways connected to your own accounts.`}),`\n`,_jsx(_components.li,{children:`Custom domain pointing at Shoppex (optional).`}),`\n`,_jsx(_components.li,{children:`Old shop links redirecting (manual on your side).`}),`\n`,_jsx(_components.li,{children:`No data lost.`}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`step-1-—-export-your-data-from-your-current-platform`,children:`Step 1 — Export your data from your current platform`}),`\n`,_jsxs(_components.p,{children:[`You are looking for: `,_jsx(_components.strong,{children:`products with prices and descriptions, license keys / serial pools,\nand customer order history if available`}),`. Most platforms expose this under “Data Export”,\n“Backup”, or “Tools” in their dashboard. Exact menu paths shift over time, so check the\ncurrent vendor docs if anything has moved.`]}),`\n`,_jsx(_components.p,{children:`The data shape you need is the same regardless of platform. The dump needs one row per\nproduct, and one row per remaining serial or license key. If you have that, in CSV or JSON,\nyou can re-import everything.`}),`\n`,_jsx(_components.p,{children:`You do not need to re-upload customers. Shoppex creates new customer records as buyers come\nin. Save the export anyway: it is your archive.`}),`\n`,_jsx(Heading,{level:`3`,id:`step-2-—-sign-up-for-shoppex-and-pick-your-shop-url`,children:`Step 2 — Sign up for Shoppex and pick your shop URL`}),`\n`,_jsxs(_components.p,{children:[`At `,_jsx(_components.a,{href:`https://dashboard.shoppex.io`,children:`dashboard.shoppex.io`}),`, create an account. Pick a slug for\nyour default URL (for example `,_jsx(_components.code,{children:`yourshop.shoppex.io`}),`).`]}),`\n`,_jsx(_components.p,{children:`If you plan to use a custom domain, the slug does not matter long-term. Buyers will reach\nthe custom domain instead.`}),`\n`,_jsx(Heading,{level:`3`,id:`step-3-—-connect-payment-gateways`,children:`Step 3 — Connect payment gateways`}),`\n`,_jsxs(_components.p,{children:[`This is the biggest difference from your old platform: `,_jsx(_components.strong,{children:`you connect your own gateway\naccounts`}),`, not Shoppex’s. Open `,_jsx(_components.strong,{children:`Settings → Payment gateways`}),`. Set up each one you want:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Stripe`}),` — paste publishable and secret key from your Stripe dashboard.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`PayPal SDK`}),` — paste client ID and secret from PayPal Developer Console.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`PayPal F\u0026F`}),` — your PayPal Business email.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Cash App`}),` — your `,_jsx(_components.code,{children:`$cashtag`}),` and Gmail forwarding.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Crypto`}),` — your wallet addresses, or Cryptomus / Oxapay API keys.`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`See `,_jsx(_components.a,{href:`/payments/gateways`,children:`Payment gateways`}),` for the full per-provider walkthrough.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Important:`}),` if you were using merchant-of-record on the old platform (some platforms\noperate as MoR by default), you will need to switch to your own gateways now. Shoppex does\nnot operate as MoR. Funds settle directly to your own Stripe, PayPal, or wallet accounts.`]}),`\n`,_jsx(Heading,{level:`3`,id:`step-4-—-recreate-your-products`,children:`Step 4 — Recreate your products`}),`\n`,_jsx(_components.p,{children:`For each product on your old shop:`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Products → New product`}),` in Shoppex.`]}),`\n`,_jsx(_components.li,{children:`Set the same title, description, price.`}),`\n`,_jsxs(_components.li,{children:[`Pick the fulfillment mode that matches:`,`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Files → `,_jsx(_components.strong,{children:`File`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`License keys / activation codes / Steam keys → `,_jsx(_components.strong,{children:`Serials`}),` or `,_jsx(_components.strong,{children:`Licenses`}),` (Licenses if\nyou need HWID-locking).`]}),`\n`,_jsxs(_components.li,{children:[`Discord access → `,_jsx(_components.strong,{children:`Subscription`}),`, and assign a Discord role from the product’s Discord\nsection, the same role-binding steps as `,_jsx(_components.a,{href:`#discord-supporter-tier`,children:`Discord supporter tier`}),`\nabove.`]}),`\n`,_jsxs(_components.li,{children:[`Monthly billing → `,_jsx(_components.strong,{children:`Subscription`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`Custom service / boost / design → `,_jsx(_components.strong,{children:`Service`}),`.`]}),`\n`]}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`If it is a serials product, paste your old key pool into the `,_jsx(_components.strong,{children:`Serials`}),` tab.`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`If you have many products, doing this by hand is tedious. The `,_jsx(_components.a,{href:`/developers/quickstart`,children:`Developer\nAPI`}),` lets you script it. Write a small migration tool that reads your\nold export and sends one product at a time to `,_jsx(_components.code,{children:`/dev/v1/products`}),`. There is no bulk-create\nendpoint. Do not run too many requests at once, and respect the rate limit. The contracts are\ndocumented in `,_jsx(_components.a,{href:`/developers/api-overview`,children:`API Reference → Products`}),`.`]}),`\n`,_jsx(Heading,{level:`3`,id:`step-5-—-move-your-custom-domain`,children:`Step 5 — Move your custom domain`}),`\n`,_jsx(_components.p,{children:`You can choose between two strategies, depending on how much downtime you can tolerate.`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Cleanest: dual-domain transition.`}),` Keep your old shop running on its current domain. Set\nup Shoppex on a new domain (for example `,_jsx(_components.code,{children:`new.yourbrand.com`}),` or `,_jsx(_components.code,{children:`yourbrand.shop`}),`). Test\nthoroughly. When ready, swap DNS so the main domain points at Shoppex.`]}),`\n`,_jsx(_components.p,{children:`This means you have two shops live at the same time for a few days while you confirm\nShoppex works for your buyers. You have no revenue gap during the switch.`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Fastest: direct swap.`}),` Update DNS on the day you are ready. Old shop goes dark when DNS\npropagates.`]}),`\n`,_jsxs(_components.p,{children:[`For the actual DNS setup, see `,_jsx(_components.a,{href:`/storefront/custom-domain`,children:`Custom domain`}),`.`]}),`\n`,_jsx(Heading,{level:`3`,id:`step-6-—-redirect-your-old-product-links`,children:`Step 6 — Redirect your old product links`}),`\n`,_jsx(_components.p,{children:`Shoppex URLs look different from your old platform’s. Old buyers, old social posts, and\nsearch-engine results will hit dead URLs unless you redirect.`}),`\n`,_jsx(_components.p,{children:`If you control the old platform’s domain, set up a redirect rule. For Cloudflare:`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsx(_components.li,{children:`Add the old domain to Cloudflare.`}),`\n`,_jsxs(_components.li,{children:[`Rules → Redirect Rules → “If URL contains `,_jsx(_components.code,{children:`/product/`}),`, then 301 to\n`,_jsx(_components.code,{children:`https://yourbrand.shoppex.io/product/{path}`}),`”.`]}),`\n`]}),`\n`,_jsx(_components.p,{children:`For domains you cannot redirect, for example third-party platforms hosting old links, there\nis nothing to do. You lose those click-throughs.`}),`\n`,_jsx(Heading,{level:`3`,id:`step-7-—-notify-your-customers`,children:`Step 7 — Notify your customers`}),`\n`,_jsx(_components.p,{children:`Send an email or Discord announcement explaining the move. Include:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`The new shop URL.`}),`\n`,_jsx(_components.li,{children:`Tell buyers that existing subscriptions on the old platform do not carry over. Stripe and\nPayPal do not transfer subscriptions between merchants, so buyers must re-authorize the\nrecurring charge on Shoppex.`}),`\n`,_jsx(_components.li,{children:`A link to your support channel for questions.`}),`\n`]}),`\n`,_jsx(_components.p,{children:`The subscription point is the most painful part of any migration. Communicate this clearly.`}),`\n`,_jsx(Heading,{level:`3`,id:`step-8-—-shut-down-the-old-shop`,children:`Step 8 — Shut down the old shop`}),`\n`,_jsx(_components.p,{children:`Monitor the new shop for a week or two. Check that there are no support tickets about missing\nitems, that search results are updated, and that social posts point at the new shop. Then\nclose the old account. Keep the export file permanently. It is your historical record.`}),`\n`,_jsx(Heading,{level:`3`,id:`common-pitfalls-2`,children:`Common pitfalls`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Subscriptions do not migrate.`}),` This is the biggest surprise for most merchants. Buyers\nmust re-subscribe on Shoppex with their own payment method. Plan a transition window of a\nmonth where you message them, ideally with a discount code to make it easier.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`License keys you sold but never delivered`}),`, for example ones still in the old shop’s\npool, go into the Shoppex Serials pool. Once sold and delivered, they stay with the buyer\nforever.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Customer wallet balances on the old shop`}),` cannot transfer. If buyers had store credit\non your old platform, you can manually re-credit their Shoppex wallet from the Customers\npage as a goodwill gesture.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Disputes filed on old gateway accounts`}),` stay with those gateways. Watch your old\nStripe / PayPal dashboards for a few months after the cut-over.`]}),`\n`]})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"codeStyling":"system","config":{},"pageMetadata":{"title":"Playbooks","description":"Step-by-step playbooks for common shop launches, sales, and migrations.","icon":"book-open","href":"/playbooks/overview"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Discord supporter tier","slug":"discord-supporter-tier","depth":2,"children":[{"title":"What you will have at the end","slug":"what-you-will-have-at-the-end","depth":3,"children":[]},{"title":"Prerequisites","slug":"prerequisites","depth":3,"children":[]},{"title":"Step 1 — Connect Discord and invite the bot","slug":"step-1-—-connect-discord-and-invite-the-bot","depth":3,"children":[]},{"title":"Step 2 — Create the supporter role","slug":"step-2-—-create-the-supporter-role","depth":3,"children":[]},{"title":"Step 3 — Create the subscription product","slug":"step-3-—-create-the-subscription-product","depth":3,"children":[]},{"title":"Step 4 — Test the flow yourself","slug":"step-4-—-test-the-flow-yourself","depth":3,"children":[]},{"title":"Step 5 — Announce it","slug":"step-5-—-announce-it","depth":3,"children":[]},{"title":"What happens when someone subscribes","slug":"what-happens-when-someone-subscribes","depth":3,"children":[]},{"title":"Common questions","slug":"common-questions","depth":3,"children":[]}]},{"title":"Telegram-only shop","slug":"telegram-only-shop","depth":2,"children":[{"title":"What you will have at the end","slug":"what-you-will-have-at-the-end-2","depth":3,"children":[]},{"title":"Prerequisites","slug":"prerequisites-2","depth":3,"children":[]},{"title":"Step 1 — Connect the bot","slug":"step-1-—-connect-the-bot","depth":3,"children":[]},{"title":"Step 2 — Turn on the AI sales agent","slug":"step-2-—-turn-on-the-ai-sales-agent","depth":3,"children":[]},{"title":"Step 3 — Test a purchase","slug":"step-3-—-test-a-purchase","depth":3,"children":[]},{"title":"Step 4 — Build out user management","slug":"step-4-—-build-out-user-management","depth":3,"children":[]},{"title":"Step 5 — Set up broadcasts and journeys","slug":"step-5-—-set-up-broadcasts-and-journeys","depth":3,"children":[]},{"title":"Step 6 — (Optional) Disable the web storefront","slug":"step-6-—-optional-disable-the-web-storefront","depth":3,"children":[]},{"title":"Common questions","slug":"common-questions-2","depth":3,"children":[]}]},{"title":"Switch to recurring","slug":"switch-to-recurring","depth":2,"children":[{"title":"Why not edit the existing product?","slug":"why-not-edit-the-existing-product","depth":3,"children":[]},{"title":"Step 1 — Create the subscription product","slug":"step-1-—-create-the-subscription-product","depth":3,"children":[]},{"title":"Step 2 — Announce the change to existing buyers","slug":"step-2-—-announce-the-change-to-existing-buyers","depth":3,"children":[]},{"title":"Step 3 — Move the old buyers","slug":"step-3-—-move-the-old-buyers","depth":3,"children":[]},{"title":"Step 4 — Wind down the old product","slug":"step-4-—-wind-down-the-old-product","depth":3,"children":[]},{"title":"What about Discord roles already granted?","slug":"what-about-discord-roles-already-granted","depth":3,"children":[]},{"title":"Common questions","slug":"common-questions-3","depth":3,"children":[]}]},{"title":"Black Friday sale","slug":"black-friday-sale","depth":2,"children":[{"title":"What you will do","slug":"what-you-will-do","depth":3,"children":[]},{"title":"Two weeks before — prep","slug":"two-weeks-before-—-prep","depth":3,"children":[]},{"title":"Sale day — go live","slug":"sale-day-—-go-live","depth":3,"children":[]},{"title":"After the sale — post-mortem","slug":"after-the-sale-—-post-mortem","depth":3,"children":[]},{"title":"Common pitfalls","slug":"common-pitfalls","depth":3,"children":[]}]},{"title":"Migrate to Shoppex","slug":"migrate-to-shoppex","depth":2,"children":[{"title":"What you will have at the end","slug":"what-you-will-have-at-the-end-3","depth":3,"children":[]},{"title":"Step 1 — Export your data from your current platform","slug":"step-1-—-export-your-data-from-your-current-platform","depth":3,"children":[]},{"title":"Step 2 — Sign up for Shoppex and pick your shop URL","slug":"step-2-—-sign-up-for-shoppex-and-pick-your-shop-url","depth":3,"children":[]},{"title":"Step 3 — Connect payment gateways","slug":"step-3-—-connect-payment-gateways","depth":3,"children":[]},{"title":"Step 4 — Recreate your products","slug":"step-4-—-recreate-your-products","depth":3,"children":[]},{"title":"Step 5 — Move your custom domain","slug":"step-5-—-move-your-custom-domain","depth":3,"children":[]},{"title":"Step 6 — Redirect your old product links","slug":"step-6-—-redirect-your-old-product-links","depth":3,"children":[]},{"title":"Step 7 — Notify your customers","slug":"step-7-—-notify-your-customers","depth":3,"children":[]},{"title":"Step 8 — Shut down the old shop","slug":"step-8-—-shut-down-the-old-shop","depth":3,"children":[]},{"title":"Common pitfalls","slug":"common-pitfalls-2","depth":3,"children":[]}]}],"codeExamples":{}},"jsLinks":[],"subdomain":"shoppex","siteName":"Shoppex","title":"Playbooks - Shoppex","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-10-27T15:44:09.916Z","originalFileLocation":"playbooks/overview.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Step-by-step playbooks for common shop launches, sales, and migrations.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Shoppex\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/shoppex/C3ATQpi32YQbyPeI/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/shoppex/C3ATQpi32YQbyPeI/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/shoppex/C3ATQpi32YQbyPeI/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/shoppex/C3ATQpi32YQbyPeI/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/shoppex/C3ATQpi32YQbyPeI/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/shoppex/C3ATQpi32YQbyPeI/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/shoppex/C3ATQpi32YQbyPeI/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/shoppex/C3ATQpi32YQbyPeI/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/shoppex/C3ATQpi32YQbyPeI/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Playbooks - Shoppex\">\u003cmeta data-mint-head property=\"og:description\" content=\"Step-by-step playbooks for common shop launches, sales, and migrations.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Shoppex\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.shoppex.io/playbooks/overview\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://shoppex.mintlify.app/_mintlify/api/og/v2?division=Playbooks\u0026amp;title=Playbooks\u0026amp;description=Step-by-step+playbooks+for+common+shop+launches%2C+sales%2C+and+migrations.\u0026amp;theme=da6d0d265cebcb7611011ed9\u0026amp;signature=6eaff7dc5c7696020c858085c36a62aca8a24bb1b39a622a6a3781aeb07fa693\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Playbooks - Shoppex\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Step-by-step playbooks for common shop launches, sales, and migrations.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://shoppex.mintlify.app/_mintlify/api/og/v2?division=Playbooks\u0026amp;title=Playbooks\u0026amp;description=Step-by-step+playbooks+for+common+shop+launches%2C+sales%2C+and+migrations.\u0026amp;theme=da6d0d265cebcb7611011ed9\u0026amp;signature=6eaff7dc5c7696020c858085c36a62aca8a24bb1b39a622a6a3781aeb07fa693\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/shoppex/C3ATQpi32YQbyPeI/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Shoppex\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#7C3AED\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.shoppex.io/playbooks/overview\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/playbooks/overview.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.shoppex.io/#organization\",\"name\":\"Shoppex\",\"url\":\"https://docs.shoppex.io\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/shoppex/-b-8YcG0h9UQ6CtI/logo/light.svg?fit=max\u0026auto=format\u0026n=-b-8YcG0h9UQ6CtI\u0026q=85\u0026s=f9f78c42d17f9c45132fbd41cfdf401b\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.shoppex.io#website\",\"name\":\"Shoppex\",\"url\":\"https://docs.shoppex.io\",\"publisher\":{\"@id\":\"https://docs.shoppex.io/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.shoppex.io/playbooks/overview#webpage\",\"url\":\"https://docs.shoppex.io/playbooks/overview\",\"name\":\"Playbooks\",\"description\":\"Step-by-step playbooks for common shop launches, sales, and migrations.\",\"dateModified\":\"2026-10-27T15:44:09.916Z\",\"isPartOf\":{\"@id\":\"https://docs.shoppex.io#website\"},\"breadcrumb\":{\"@id\":\"https://docs.shoppex.io/playbooks/overview#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.shoppex.io/playbooks/overview#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Shoppex\",\"item\":\"https://docs.shoppex.io\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Playbooks\",\"item\":\"https://docs.shoppex.io/playbooks/overview\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://docs.shoppex.io/playbooks/overview#article\",\"headline\":\"Playbooks\",\"name\":\"Playbooks\",\"description\":\"Step-by-step playbooks for common shop launches, sales, and migrations.\",\"url\":\"https://docs.shoppex.io/playbooks/overview\",\"mainEntityOfPage\":{\"@id\":\"https://docs.shoppex.io/playbooks/overview#webpage\"},\"dateModified\":\"2026-10-27T15:44:09.916Z\",\"publisher\":{\"@id\":\"https://docs.shoppex.io/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.shoppex.io#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Shoppex\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"Shoppex","nav":{"global":{"anchors":[{"anchor":"Discord","icon":"discord","href":"https://discord.gg/VjrptT6Nvx"},{"anchor":"Telegram","icon":"telegram","href":"https://t.me/shoppexhq"}]},"tabs":[{"tab":"Guides","icon":"book-open","groups":[{"group":"Get started","pages":[{"title":"Quickstart","icon":"rocket","href":"/start/quickstart"}]},{"group":"Selling","pages":[{"title":"Products","icon":"box","href":"/selling/products"},{"title":"Physical products","icon":"truck","href":"/selling/physical-products"},{"title":"Orders","icon":"receipt","href":"/selling/orders"},{"title":"Abandoned Carts","icon":"cart-shopping","href":"/selling/abandoned-checkouts"},{"title":"Email Templates and Variables","icon":"envelope","href":"/selling/email-templates"},{"title":"Send Buyer Emails From Your Own Resend Account","icon":"paper-plane","href":"/selling/email-sending"},{"title":"Serials \u0026 license keys","icon":"key","href":"/selling/serials-and-licenses"},{"title":"Subscriptions","icon":"arrows-rotate","href":"/selling/subscriptions"},{"title":"Discord roles","icon":"discord","href":"/selling/discord-roles"},{"title":"Automations","icon":"bolt","href":"/selling/automations"}]},{"group":"Payments","pages":[{"title":"Payment gateways","icon":"plug","href":"/payments/gateways"},{"title":"Checkout","icon":"credit-card","href":"/payments/checkout"},{"title":"Refunds and disputes","icon":"rotate-left","href":"/payments/refunds"},{"title":"Chargeback Shield","icon":"shield-halved","href":"/payments/chargeback-shield"},{"title":"Shoppex Wallet","icon":"bitcoin-sign","href":"/payments/crypto-wallet"}]},{"group":"Customers","pages":[{"title":"Customers","icon":"users","href":"/customers/overview"},{"title":"Customer accounts","icon":"circle-user","href":"/customers/customer-accounts"},{"title":"Support inbox","icon":"inbox","href":"/customers/inbox"},{"title":"Resellers","icon":"handshake","href":"/customers/resellers"}]},{"group":"Account","pages":[{"title":"Team and stores","icon":"user-group","href":"/account/team"},{"title":"Security","description":"2FA, active sessions, and the audit trail.","icon":"lock","href":"/account/security"}]},{"group":"Playbooks","pages":[{"title":"Playbooks","icon":"book-open","href":"/playbooks/overview"}]}]},{"tab":"Storefront","icon":"palette","pages":[{"title":"Storefront","href":"/storefront/themes"}]},{"tab":"Developers","icon":"code","pages":[{"title":"Developers","href":"/developers/quickstart"}]},{"tab":"API reference","icon":"terminal","pages":[{"title":"API reference","href":"/api-reference/account-\u0026-auth/get-current-account"}]}]},"basePath":"","title":"Playbooks - Shoppex","buildId":"dpl_345ReqzYaAjzS9QpeJemsKdb7KDj","deploymentId":"dpl_345ReqzYaAjzS9QpeJemsKdb7KDj","dynamics":[],"chunks":[]}