Filed under CurateList

Shopify Cart Permalinks: Every Parameter, With Examples

How to build a Shopify cart permalink: URL format, every documented parameter, variant IDs, encoding, spreadsheet formulas, limits and tracking.

A Shopify cart permalink is a URL that loads specific product variants, in specific quantities, into a new checkout. The format is your store domain, then /cart/, then one or more variant_id:quantity pairs separated by commas — for example https://example.myshopify.com/cart/11111111111111:1. Anything after a ? is optional: a discount code, a note, line item properties, pre-filled contact details, or an instruction to land on the cart page instead of checkout. It is free, it needs no app, and it works anywhere you can paste a link.

That is the short answer. The long answer is that most guides to cart permalinks document three parameters, skip the limits, and in at least one case describe a parameter that Shopify’s own documentation says does not work. For this reference we checked every parameter and behaviour against Shopify’s Help Center page on cart permalinks and the developer tutorial Create cart permalinks on shopify.dev. Where a behaviour appears only on third-party blogs, we say so. Where Shopify’s documentation is silent, we say that too, and tell you what to test.

Our vantage point: we build CurateList, a Shopify app that generates cart permalinks from curated product lists, so we have spent more time than is healthy with this URL format and its edge cases. You do not need our app, or any app, to use what follows.

Key takeaways

  • A cart permalink is store-domain/cart/variant_id:quantity with optional query parameters; Shopify says the same link is reusable and creates a new checkout for each customer.
  • Shopify documents these parameters: discount, properties, note, attributes, ref, nine checkout[...] prefill fields, access_token, source_name, storefront, and payment, plus a locale prefix in the path.
  • Selling plans do not work with cart permalinks and the links cannot bypass a storefront password — both are stated limitations in Shopify’s developer documentation.
  • Inventory is not reserved by a link. Shopify holds inventory only when the customer submits payment information, so a permalink is an invitation, not a reservation.
  • For tracking, note, attributes and the discount code travel with the order itself; UTM parameters depend on session tracking that Shopify says can be blocked by apps and private browsers. Use both.

What a cart permalink is, and the four links it gets confused with

Shopify’s Help Center describes cart permalinks as a way to curate the checkout: you choose the variants, quantities and discounts, and the customer arrives with all of it already in place. The same page says you can embed the links in webpages as regular links or buttons, or share them in email campaigns, social posts and chat messages, and that one link can be reused, with each customer who clicks it getting a new checkout.

That last point is the important one. A cart permalink is a recipe, not a cart. Nothing exists on Shopify’s side until someone clicks. Two hundred people can click the same link and each gets their own checkout.

The terminology around it is a mess, because five different kinds of link all get called a “Shopify cart URL” or a “checkout link” in forum threads and blog posts. They behave differently, and picking the wrong one is the most common reason a link campaign disappoints.

Link typeURL patternWhere the customer landsWhat it carriesShopify documentation
Cart permalink/cart/{variant_id}:{qty},{variant_id}:{qty}Checkout, or the cart page with storefront=trueVariants, quantities, discount codes, properties, note, attributes, prefilled contact fieldsHelp Center and shopify.dev
Checkout link (admin-generated)/cart/{variant_id}:1?channel=buy_buttonCheckoutOne variant, quantity 1 by defaultHelp Center — it is a cart permalink created by the Buy Button channel
Add-to-cart link/cart/add?id={variant_id}&quantity=1Reported to add the item to whatever is already in the cartOne or more variants and quantitiesNot documented as a clickable link; the Ajax Cart API reference documents POST /cart/add.js and theme forms that post to /cart/add
Shareable discount link/discount/{CODE}?redirect=/pathHome page, a collection or a product pageOne discount, no productsHelp Center, managing discounts
Draft order invoiceUnique checkout link inside an emailed invoiceCheckout for that one orderCustom prices, reserved inventory, a named customerHelp Center, creating draft orders

Cart permalink vs checkout link

These are the same thing under two names. In the Shopify admin, the Help Center says that if you have the Buy Button channel installed you can open any product, click More actions, choose Create checkout link, select a variant, and copy the result. The link it produces uses the format https://my-shop-name.myshopify.com/cart/variantIDnumber:1?channel=buy_button and, by default, includes one variant at a quantity of 1. That is a cart permalink with a channel tag on the end. If all you need is a one-product link, this is the fastest route and you never have to look up a variant ID.

Developers will meet a third thing that also gets called a checkout URL: the checkoutUrl field on a Storefront API cart, which looks like /cart/c/{token}. That one points at a specific, already-created cart. Shopify’s Storefront API cart guide says it should be requested when the buyer is ready to go to checkout, and requested again if it has gone stale. It is the opposite of a permalink: one cart, one buyer, short-lived.

Cart permalink vs add-to-cart link

The add-to-cart link, /cart/add?id=..., appears in several ranking guides, including Popupsmart’s. It is widely used, but we could not find it documented as a clickable link on help.shopify.com or shopify.dev. What Shopify documents is the Ajax endpoint POST /cart/add.js and theme product forms whose action ends in /cart/add. Treat the link form as reported by third parties, not in Shopify’s documentation. If you want a documented way to land a customer on the cart page with items in it, use a cart permalink with storefront=true.

Cart permalink vs shareable discount link

A shareable discount link carries a discount and no products. Shopify’s Help Center says you get one from Discounts, by opening the discount, clicking Promote and choosing the shareable link option; you can then change /discount/code to /discount/code?redirect=/new-path to pick the landing page. The discount then applies automatically to the customer’s next cart, or to a cart they already have open. Two limits from the same page: a shareable link carries a single discount, and it only works while that discount is active.

Decide between the two with one question: do you know what this person is going to buy? If yes, use a cart permalink with the discount parameter. If no — an influencer’s audience choosing from a collection, say — use the shareable discount link and let them shop.

Anatomy of a cart permalink

Every example below uses a placeholder domain and obviously fake variant IDs. Swap in your own.

One variant

https://example.myshopify.com/cart/11111111111111:1

Domain, /cart/, variant ID, colon, quantity. Shopify’s Help Center gives the steps as: start with your store domain and add /cart/, then add one or more variants using variant_id:quantity. The ID must be a variant ID, not a product ID. A product with no options still has one variant, and that variant has its own ID; finding it is covered below.

Several variants, with quantities

https://example.myshopify.com/cart/11111111111111:2,22222222222222:1,33333333333333:6

Commas separate the pairs. There are no spaces anywhere in the path. Shopify’s documentation does not state a maximum number of variants per link; the practical ceiling is link length, which we cover under limits.

A discount code

https://example.myshopify.com/cart/11111111111111:1?discount=WELCOME10

The discount parameter applies a discount code that already exists in your admin. The link does not create the discount, and it does not override the discount’s rules. If the code has a minimum order amount, an end date or a usage cap, those still apply.

More than one discount code

https://example.myshopify.com/cart/11111111111111:1,22222222222222:1?discount=WELCOME10,FREESHIP

Shopify’s developer tutorial documents multiple codes separated by a comma, and adds a note that you cannot pass a discount code that itself contains a comma through this parameter. Whether the codes actually stack is decided by your discount combination settings, not by the link. Shopify’s discount combinations page caps a single order at 5 product or order discount codes plus 1 shipping discount code, and lists which discount classes are allowed to combine. Shopify’s documentation does not describe what the customer sees when a permalink carries two codes that are not set to combine, so test that case on your own store before you send it.

Stacking is where links get expensive. A permalink that applies a code to a cart of items you have already marked down discounts the reduced price, not the original one. We worked through that margin math in our markdown vs coupon vs bundle decision framework; read the stacking section before you put a code in a link during a sale.

Line item properties

https://example.myshopify.com/cart/11111111111111:1?properties=eyJFbmdyYXZpbmciOiJGb3IgU2FtIiwiR2lmdCB3cmFwIjoiWWVzIn0

Line item properties are the key-value pairs attached to a single line in the cart — engraving text, a monogram, a gift-wrap flag. Shopify’s tutorial is specific about three constraints: you can add up to 25 properties, they are added to the first product in the link, and they have to be supplied as Base64 URL-encoded JSON. The string above is the encoded form of this JSON:

{"Engraving":"For Sam","Gift wrap":"Yes"}

Two consequences follow. First, if only one item in a multi-item link needs properties, put that variant first in the path. Second, you cannot hand-type this parameter; you need an encoder. We cover the encoding rules in their own section.

Note, attributes and ref

https://example.myshopify.com/cart/11111111111111:1?note=Reorder%20link%20sent%20by%20Dana
https://example.myshopify.com/cart/11111111111111:1?attributes[source]=packaging-qr&attributes[batch]=autumn-box
https://example.myshopify.com/cart/11111111111111:1?ref=newsletter-october

Shopify groups these three under conversion tracking. According to the developer tutorial, you can add multiple attributes parameters; note and attributes show up in the Notes section of the order details page; and ref shows up as a referral code in the order’s Conversion summary. In practice: use note for something a human on your team should read, attributes for structured tags you want to filter or export by, and ref for a campaign label.

Pre-filled checkout fields

https://example.myshopify.com/cart/11111111111111:1?checkout[email]=sam%40example.com&checkout[shipping_address][first_name]=Sam&checkout[shipping_address][city]=Miami

Shopify documents nine supported checkout parameters: checkout[email], and under checkout[shipping_address] the fields first_name, last_name, address1, address2, city, province, country and zip. Nothing else is listed. Phone number, company name and billing address are not in the supported table, so we leave them out.

A caution that is judgment rather than documentation: a pre-filled link puts personal data in a URL, and URLs get stored — in click-tracking tools, link shorteners, browser history and forwarded messages. Pre-fill only in one-to-one links sent to the person whose details they are. Never pre-fill in anything public, printed or posted.

Sales channel attribution

https://example.myshopify.com/cart/11111111111111:1?access_token={storefront_access_token}
https://example.myshopify.com/cart/11111111111111:1?access_token={storefront_access_token}&source_name={attribution_handle}

This pair is for developers building sales channel apps. Adding a storefront access token attributes the order to the sales channel that owns the token, and Shopify says merchants can then see the attribution in sales-by-channel reporting and in the admin. The source_name parameter attributes the order to a specific order attribution definition; Shopify’s order attribution guide says it requires the access token, because that is how Shopify identifies the app that owns the attribution definition, and the value must match a handle owned by your app. A merchant hand-building links for an email has no reason to use either. Use ref, attributes and UTM parameters instead.

Cart page instead of checkout

https://example.myshopify.com/cart/11111111111111:1,22222222222222:1?storefront=true

By default a cart permalink goes to checkout. Appending storefront=true sends the customer to the online store cart instead, which the Help Center presents as the option for letting customers add to or change the cart first. Use it whenever the customer might reasonably want to remove an item, change a quantity or keep shopping. We default to it for personal-shopping sends and default to checkout for replenishment.

Shop Pay

https://example.myshopify.com/cart/11111111111111:1?payment=shop_pay

payment=shop_pay directs buyers to a Shop Pay checkout. The Help Center shows it combined with a code, as ?payment=shop_pay&discount=15off, and points to Shopify’s Shop Pay branding guidelines if you want to style the button that carries the link.

Locale

https://example.myshopify.com/fr/cart/11111111111111:1

The locale is not a query parameter. It is a path prefix that goes before /cart/, so the buyer lands in a localized checkout. This is the only localization control Shopify documents for cart permalinks.

Selling plans: documented as not working

The first limitation in Shopify’s developer tutorial reads: “Selling plans don’t work with cart permalinks.” A guide by Rob K. Johnson describes appending selling_plan= and an ID to a permalink to attach a subscription. That parameter is reported by a third party and contradicts Shopify’s documentation. We would not build a subscription campaign on it. For subscriptions, link to the product page or use the link format your subscription app provides.

Parameters reference table

Every row is a parameter or path element we could confirm on a Shopify page. “Help” means the Help Center cart permalinks page; “Dev” means the shopify.dev tutorial.

ParameterWhat it doesExampleDocumented on
/cart/{id}:{qty}Loads one variant at the given quantity/cart/11111111111111:1Help, Dev
,{id}:{qty}Adds further variants/cart/11111111111111:2,22222222222222:1Help, Dev
discountApplies an existing discount code?discount=WELCOME10Help, Dev
discount (several)Applies several codes, comma-separated; codes containing commas cannot be passed?discount=WELCOME10,FREESHIPDev
propertiesAdds up to 25 line item properties to the first product; Base64 URL-encoded JSON?properties=eyJFbmdyYXZpbmci...Dev (linked from Help)
noteAdds an order note, shown in the Notes section of the order?note=came-from-newsletterDev
attributes[key]Adds cart attributes, shown in the Notes section; repeatable?attributes[source]=packaging-qrDev
refReferral code shown in the order’s Conversion summary?ref=newsletter-octoberDev
checkout[email]Pre-fills the email field?checkout[email]=sam%40example.comDev (linked from Help)
checkout[shipping_address][field]Pre-fills first_name, last_name, address1, address2, city, province, country or zip?checkout[shipping_address][city]=MiamiDev
access_tokenAttributes the order to the sales channel that owns the storefront access token?access_token={token}Dev
source_nameAttributes the order to an attribution definition; requires access_token?access_token={token}&source_name={handle}Dev, order attribution guide
storefrontLands on the online store cart instead of checkout?storefront=trueHelp, Dev
paymentSends the buyer into a Shop Pay checkout?payment=shop_payHelp, Dev
Locale prefixLocalized checkout; goes in the path before /cart//fr/cart/11111111111111:1Dev (linked from Help)
channelPresent on links generated by the Buy Button channel; not described as a parameter you set yourself?channel=buy_buttonHelp
selling_planReported by third parties; Shopify states selling plans do not work with cart permalinks—Dev lists it as a limitation
utm_*Not listed on the permalink pages; read by Shopify’s session-based analytics?utm_source=newsletterSee the UTM section below

How to find a variant ID

The whole format depends on variant IDs, and they take a little finding. Shopify’s Find a variant ID help page documents three methods.

From the admin URL

For a product with variants: go to Products, open the product, click the variant in the Variants section, and read the browser’s address bar. The URL looks like https://admin.shopify.com/store/shopname/products/1234567/variants/36485954240671; the number after /variants/ is the variant ID. The number after /products/ is the product ID and will not work in a permalink.

From the .json view

For a product without variants there is no variant to click. Open the product in the admin, add .json to the end of the URL and press Enter. In the JSON that loads, find "product", then "variants", then "id". The help page notes that a product without variants shows "title": "Default Title" for its single variant. That ID is the one you want.

In bulk, from a report

For dozens or hundreds of IDs, go to Analytics, then Reports, click New exploration, and add Product title, Product variant title and Product variant ID as dimensions. You can then read the IDs off the report or export it.

This is the documented replacement for what most people expect to find in the product CSV. We checked Shopify’s product CSV reference: the column list covers title, URL handle, SKU, options, prices and inventory, and does not include a variant ID column. If your workflow starts from a product export, join it to the report export on SKU.

From a storefront product URL

One more shortcut. Shopify’s Ajax Cart API reference shows line item URLs in the form /products/health-potion?variant=39897499729985. When a product page URL on your storefront carries a variant= value after you select an option, that number is the variant ID. Whether your theme updates the URL on selection is a theme behaviour, so treat this as a convenience and the admin methods as the source of truth.

URL-encoding rules

Most broken cart permalinks are encoding mistakes. The format mixes characters that have structural meaning in a URL with free text written by people, and the two collide.

The separators

  • One ? starts the query string. Every parameter after the first is joined with &. A second ? breaks the link.
  • The colon and comma in the path are structural. Shopify’s examples show them as literal characters, so leave them unencoded.
  • No spaces, anywhere. Not after commas, not around =.

Free-text values

RFC 3986, the standard that defines URL syntax, lists the characters that never need encoding: letters, digits, hyphen, period, underscore and tilde. Anything else in a value you typed yourself should be percent-encoded. The ones that matter in practice:

CharacterEncodedWhy it matters
Space%20An unencoded space ends the link in most email and chat clients
&%26Otherwise read as the start of the next parameter
=%3DOtherwise read as a key-value separator
#%23Everything after it is treated as a fragment and never sent to Shopify
%%25Otherwise read as the start of an encoded character
+%2BCommonly decoded as a space in query strings
@%40Shopify’s own example shows a literal @ in checkout[email]; encoding it is the conservative choice
Accented and non-Latin charactersUTF-8, percent-encodedé becomes %C3%A9

For tracking values, the simplest rule is to avoid the problem: use lowercase letters, digits and hyphens for ref, attributes and UTM values. ref=newsletter-october needs no encoding at all.

Square brackets

The checkout[...] and attributes[...] parameters use square brackets, which RFC 3986 classes as reserved characters. Shopify’s examples show them literally. Some tools — email platforms, link shorteners, spreadsheet encoding functions — will convert them to %5B and %5D. Shopify’s documentation does not say whether the encoded form is accepted, so if your sending tool rewrites brackets, test the rewritten link before you send.

The properties parameter

Shopify requires Base64 URL-encoded JSON here. Base64 URL is not the same as ordinary Base64: RFC 4648 defines it as the variant that uses - and _ in place of + and /, so the result is safe inside a URL. The same RFC notes that the = padding character can be skipped when the length is known, and Shopify’s own example string has no padding. The sequence is:

  1. Write valid JSON with double quotes: {"Engraving":"For Sam"}.
  2. Encode it with a Base64 URL encoder, not a standard Base64 one.
  3. Strip any trailing = characters.
  4. Paste the result after properties=.

Discount codes

Shopify documents one rule: a code containing a comma cannot be passed through the discount parameter, because the comma is the separator between codes. Our advice goes further and is judgment, not documentation: name codes you intend to put in links with letters, digits and hyphens only. SPRING-15 survives every channel. Spring Sale 15%! will be mangled by something between your keyboard and the customer’s thumb.

Invisible breakage

Copying a link out of a word processor or a slide deck can swap straight quotes for curly ones, turn a hyphen into an en dash, or append a trailing period. Build links in a plain-text editor or a spreadsheet, and copy from there.

Building cart permalinks at scale in a spreadsheet

Once you need more than a handful of links, build them with a formula. The formulas below are written for Google Sheets, using ENCODEURL and TEXTJOIN. Excel has functions with the same names, but check that your version includes them.

One variant per row

Set up columns: A is the variant ID, B the quantity, C the discount code, D the ref value. In E2:

="https://example.myshopify.com/cart/"&A2&":"&B2&"?discount="&ENCODEURL(C2)&"&ref="&ENCODEURL(D2)

Fill down. Row 2 with 11111111111111, 2, REORDER10 and email-buy-again produces:

https://example.myshopify.com/cart/11111111111111:2?discount=REORDER10&ref=email-buy-again

Several variants per link

Put each variant ID and quantity in paired columns — A and B for the first item, C and D for the second, E and F for the third — and the discount code in G. In H2:

="https://example.myshopify.com/cart/"&TEXTJOIN(",",TRUE,IF(A2="","",A2&":"&B2),IF(C2="","",C2&":"&D2),IF(E2="","",E2&":"&F2))&IF(G2="","","?discount="&ENCODEURL(G2))

TEXTJOIN with TRUE skips empty pairs, so a row with two items and a row with three both produce clean links. The final IF leaves off the query string when there is no code.

Spreadsheet hygiene

  • Format the ID columns as plain text. Variant IDs are long numbers, and a spreadsheet that treats them as numbers may display them in scientific notation or round them. Text formatting prevents both.
  • Do not wrap the whole link in ENCODEURL. That encodes the slashes, colons and question mark and destroys the link. Encode values only.
  • Keep a column for the date built and the campaign. In six months you will want to know which links are still in circulation.
  • Test a sample, not one. Open the first row, the last row, and the row with the longest value in an incognito window.

Adding UTM parameters, and what survives into the order

Shopify’s cart permalink pages do not list UTM parameters. They appear elsewhere in Shopify’s documentation: the developer guide to carts and checkout for agents says you can append query parameters to a permalink for marketing attribution and shows utm_source appended to a checkout URL, and the Help Center’s Measuring marketing performance page says traffic that arrives with utm_campaign parameters in the URL is attributed to marketing. So UTM parameters are appended the same way as any other:

https://example.myshopify.com/cart/11111111111111:1?discount=REORDER10&ref=email-buy-again&utm_source=newsletter&utm_medium=email&utm_campaign=buy-again-october

The more useful question is which of these values you can still see after the order exists. They do not all travel the same way.

Value in the linkWhere Shopify says it appearsRelies on session tracking
discountOn the order; grouped in the Sales by discount codes reportNo — it is part of the order
noteNotes section of the order details pageNo — it is part of the order
attributes[...]Notes section of the order details pageNo — it is part of the order
propertiesOn the line itemNo — it is part of the order
refReferral code in the order’s Conversion summaryShown in a section Shopify says can be missing
utm_*UTM parameters in the Conversion summary’s visit details; marketing reportsYes
checkout[...]Pre-filled fields the customer can editNot a tracking value

The caveat on the last two tracking rows comes from Shopify’s Viewing order conversion summary page. It lists the cases where an order has no conversion summary at all: when apps or private browsers block cookie tracking, when the order started life as a draft order, and when the order did not come from the Online Store or Hydrogen sales channels. It also says the summary can take up to 48 hours to appear.

Our recommendation is to carry the campaign twice. Put it in UTM parameters so it flows into Shopify’s marketing reports, and put it in attributes or note so it is written onto the order. When the two disagree, the order-level value is the one that was in the link.

Seven use cases, with an example each

Every scenario below is an illustrative example. The stores, names and numbers are invented to show the mechanics.

1. Email: buy it again

Say a coffee roaster has a customer who ordered two bags of the same espresso blend five weeks ago. The replenishment email carries one button:

https://example.myshopify.com/cart/11111111111111:2?ref=buy-again&attributes[flow]=replenish-35d&utm_source=email&utm_medium=flow&utm_campaign=buy-again

Same variant, same quantity, straight to checkout. No discount: a customer who is about to run out does not need a reason. If your email platform can insert the last-ordered variant ID and quantity as merge fields, the link builds itself per recipient; if it cannot, segment by product and send one link per segment.

2. SMS: a short link for a short message

Say a skincare store texts a restock alert for one serum:

https://example.myshopify.com/cart/22222222222222:1?ref=sms-restock

Keep SMS links minimal. Every parameter lengthens the message, and long URLs in texts look like phishing. No pre-filled fields, one tracking value, and if you shorten the link, open the short version yourself first to confirm the shortener has not rewritten the colon or comma.

3. QR code on packaging or in store

Say a candle maker prints a QR code inside the lid that reorders the same candle:

https://example.myshopify.com/cart/33333333333333:1?storefront=true&attributes[source]=lid-qr

Two design choices. storefront=true lands on the cart, because someone scanning a lid may want two, or a different scent. And the link is as short as it can be, because every extra character makes the printed code denser and harder to scan. The real risk is permanence: print cannot be edited. If that variant is ever deleted, every lid in circulation points at nothing. For anything printed, encode a short URL on a domain you control that redirects to the permalink, so you can repoint it later.

4. Influencer link with a code

Say a creator called Dana gets 15% for her audience on a specific two-item set:

https://example.myshopify.com/cart/11111111111111:1,22222222222222:1?discount=DANA15&ref=dana-october&storefront=true

The code is visible in the URL and the link is forwardable, so assume it will travel beyond Dana’s audience. Shopify’s discount code settings let you cap the number of times a code can be used, set the dates it is valid and require a minimum order amount. Set those before the link goes out, not after the code shows up on a coupon site. If the audience should choose their own products, use the shareable discount link instead.

5. B2B reorder link

Say a café orders the same six products from a wholesale roaster every month. The rep saves one link:

https://example.myshopify.com/cart/11111111111111:24,22222222222222:12,33333333333333:12,44444444444444:6,55555555555555:6,66666666666666:2?note=Standing%20order%20-%20Cafe%20Luna&storefront=true

Sixty-two units, one click, and the buyer lands on the cart where they can adjust quantities before checking out. Be clear about what the link does not do. It carries no prices, so it cannot express a negotiated rate, and Shopify’s cart permalink documentation does not describe how permalinks interact with B2B catalogs or company accounts. When the price is part of the deal, use a draft order: Shopify’s draft order page says you can set a custom price on any line item, reserve inventory until a date you choose, and send an invoice that contains a link to a checkout.

6. Customer-service recovery

Say a customer writes in because their order arrived with one of three items damaged. The agent sends a link for the replacement with a goodwill code:

https://example.myshopify.com/cart/22222222222222:1?discount=SORRY-7F3K&note=Ticket%2048213%20replacement

The note ties the new order to the ticket for whoever reads it later. Use a unique, single-use code per case; a shared apology code becomes a permanent public discount the first time someone posts it.

7. Personal-shopping sends

Say a stylist has spent twenty minutes with a client choosing a jacket, two shirts and a belt. She sends:

https://example.myshopify.com/cart/11111111111111:1,22222222222222:1,33333333333333:1,44444444444444:1?storefront=true&attributes[stylist]=dana&note=Picked%20in-store%2014%20Oct

This is the use case where the bare link is weakest. The customer sees a cart with four line items and no explanation of why those four. The context — why the navy, why that size — lives in a separate message, if it lives anywhere. We wrote about closing that gap in our guide to sending personalized shoppable links on Shopify.

Limits and failure modes

This is the section most guides skip. Some of these limits are documented by Shopify. For others the documentation is silent, and we say so rather than guess.

Inventory is not reserved

Shopify’s Shopify Checkout help page says that when a customer completes a step of checkout their cart is checked against your inventory levels, that an error message is displayed if inventory has become unavailable, and that inventory is held only once the customer submits payment information. A cart permalink therefore reserves nothing. If you send a link for the last unit of something to forty people, one of them gets it. When you need to hold stock for a named customer, a draft order with reserved inventory is the documented tool.

Out-of-stock and deleted variants

Shopify’s cart permalink documentation does not describe what the customer sees when a variant in the link is sold out, unavailable or deleted. The variant ID is the only pointer the link has; there is no fallback to the product or to another variant. For any link with a long life — printed, pinned, or in an automated flow — check it on a schedule, and re-test whenever you restructure a product’s variants. Do not assume a variant you deleted and recreated has kept its old ID.

Selling plans and password-protected stores

Both are stated limitations in the developer tutorial: selling plans do not work with cart permalinks, and cart permalinks cannot get past a storefront password. The second one catches people testing a link on a store that has not launched. It also rules out using a permalink as a back door into a password-protected pre-launch sale.

Properties apply to the first product only

Up to 25 properties, attached to the first variant in the path. There is no documented way to attach different properties to the second or third item in the same link. If two items each need personalization, send two links or land on the product pages.

Markets, currency and language

The locale prefix is the only localization control Shopify documents for cart permalinks. The documentation lists no currency or country parameter, and does not describe how a permalink behaves for a buyer in a different market from the one you tested in. If you sell internationally, open the link from each market you serve and check the currency, the prices, and whether every variant in the link is available there.

Discount not applicable

The link passes the code; the discount’s own rules decide whether it applies. An expired code, a minimum the cart does not meet, a customer who is not eligible, or two codes that are not set to combine all lead to a customer at checkout paying more than your message promised. Shopify’s documentation does not describe the message shown in each case when the code arrives by permalink. State the offer and its end date in the message itself, so a customer who sees full price knows something went wrong and tells you.

Existing cart contents

Shopify’s documentation does not say whether a cart permalink replaces, clears or merges with items already in the customer’s online store cart. Test it on your store, with storefront=true and without. This matters most for customers who were mid-shop when your email arrived.

Link length

Shopify does not document a maximum length or a maximum number of variants. RFC 9110, the HTTP standard, recommends that senders and recipients support URLs of at least 8,000 octets, which is far longer than a reasonable cart. The practical limits arrive sooner and come from the channel: a text message, a QR code, or a chat app that truncates long links. Shopify’s example variant IDs are 14 digits long; with a quantity and a comma, each item costs about 17 characters, so a ten-item cart is roughly 170 characters of path before any parameters.

Customer login

Popupsmart’s guide states that customers who are not logged in see a login page before checkout when customer accounts are enabled. That is reported by a third party; we did not find it on Shopify’s cart permalink pages. If your store requires accounts, test the link while logged out.

The customer skips the product page

A checkout-bound permalink removes the product page from the journey. DevCommerce’s guide makes the point well: if the visitor does not already know the product, sending them straight to payment removes their chance to learn about it. Checkout-bound links are for people who have already decided. For everyone else, use storefront=true, or link to the product.

Hand-built link or an app?

Hand-built cart permalinks are free and they are fine. For a one-off link, a campaign with a single cart, or a spreadsheet of replenishment links, nothing in this article requires software beyond a text editor. If someone on your team is comfortable with the formulas above, keep doing it that way.

The native option is also better than its reputation. The Buy Button channel’s Create checkout link action produces a single-variant permalink from the product page with no ID lookup at all.

Hand-building stops working in one specific situation: non-technical staff assembling multi-item carts for individual customers, many times a day. A stylist on a shop floor is not going to open four variants in the admin, copy four IDs, join them with commas and encode a note. They will send screenshots instead.

That is the job we built CurateList for. A staff member picks products from the catalog, writes a note next to each one, and sends a branded page on the store’s own domain. The customer can react to each pick with “Love It” or “Not for Me” and add to cart without an account, and the list carries a one-click cart permalink so the whole selection goes to checkout together. The app generates the permalink; nobody types a variant ID. Per its App Store listing, the Free plan covers 10 lists and 5 customers a month, Starter is $7 a month and Pro is $15 a month. It launched in May 2026 and has no App Store reviews yet, so you are judging it on the free plan, not on social proof.

What it does not do: it is not a clienteling CRM. It has no customer profiles, no POS integration, no per-associate seats, and it does not send SMS or WhatsApp messages. If you need those, our buyer’s guide to clienteling apps for Shopify covers the tools that do, and our survey of personal shopper apps for Shopify compares the wider category by job.

Our rule of thumb, offered as judgment: if links are built by one person, at a desk, a few times a week, build them by hand. If they are built by several people, away from a desk, for individual customers, the cost of the tool is smaller than the cost of the links that never get sent.

Testing checklist

Run this before any link goes to more than one person.

  1. Open the link in an incognito or private window, so your own session and cart do not affect the result.
  2. Open it on a phone, from inside the app it will be sent through — the email client, the messaging app, the camera for a QR code.
  3. Confirm every variant and quantity is correct, including size and colour, not just the product.
  4. Confirm the discount appears and the total matches what your message promises.
  5. Confirm it lands where you intended: checkout, or the cart if you used storefront=true.
  6. Click it with items already in your cart and note what happens to them.
  7. Place a test order and open it in the admin. Check that the note, attributes and line item properties appear, and look at the Conversion summary once it has had time to populate.
  8. If you sell in several markets or languages, repeat from each one.
  9. Click the link as rewritten by your sending tool. Email platforms and shorteners wrap and re-encode links; the version the customer receives is the one that matters.
  10. For links with a long life, set a recurring reminder to re-test, and re-test after any change to the products or the discount.

Measuring performance

A cart permalink has three numbers worth tracking: how many people clicked, how many ordered, and what those orders were worth. Clicks come from whatever sent the link — your email platform, SMS tool or shortener. Orders and revenue come from Shopify, and there are four places to look.

  • The discount code. If each campaign has its own code, Shopify’s Sales by discount codes report groups sales by discount name. This is the most reliable join key, because the code is part of the order. It only works when the code is unique to the link.
  • Notes and attributes. These appear on the order details page. They are the fallback for links with no discount, and the way to tell two links apart when they share a code.
  • The Conversion summary. On each order from the Online Store, where tracking allows, this shows the referral code from ref and the UTM parameters from the visit.
  • Marketing reports. Shopify’s Measuring marketing performance page describes five attribution models — last non-direct click, which is the default, plus last click, first click, any click and linear. A permalink click is usually the last touch before purchase, so under last-click models it will take credit for orders that an earlier ad or email set up. Compare models before you conclude that your reorder links are your best channel.

Illustrative example

Say a store sends a buy-it-again email with a permalink to 400 past customers. The email platform reports 60 clicks. In Shopify, 9 orders carry attributes[flow]=replenish-35d, worth $540 in total. That is a 15% click rate, a 15% click-to-order rate, a $60 average order and $1.35 of revenue per email sent. Now suppose only 6 of those 9 orders show UTM parameters in their Conversion summary. The other 3 are not missing orders; they are orders where session tracking was unavailable. If you had measured by UTM alone you would have under-counted the campaign by a third. These numbers are invented; the gap between order-level and session-level tracking is the point.

What to compare it against

The honest comparison for a checkout-bound permalink is the same message with a product-page link. Split a send, keep everything else identical, and compare orders per recipient rather than click-to-order rate — a permalink can raise the conversion of clickers while lowering the number of people willing to click something that goes straight to payment. We have not published a measured result for that test and will not invent one; run it on your own list.

Common mistakes

  1. Using the product ID instead of the variant ID. The number after /products/ in the admin URL is the product. The permalink needs the number after /variants/, or the variant id from the .json view.
  2. Putting a second question mark in the link. One ?, then & between every further parameter. This is the most common break when someone appends UTM parameters to a link that already has a discount.
  3. Sending a checkout-bound link to a cold audience. People who have not seen the product should not land on a payment form. Use storefront=true or a product link.
  4. Treating the link as a reservation. Inventory is held only when payment information is submitted. Do not promise “we’ve set this aside for you” with a permalink; use a draft order with reserved inventory.
  5. Reusing one discount code across every link. You lose the ability to tell campaigns apart, and one leak exposes all of them. One code per campaign, with a usage cap and an end date.
  6. Pre-filling personal details in links that can be forwarded. An email address in a URL is stored wherever the URL is stored. Pre-fill only in one-to-one sends.
  7. Printing a raw permalink. Packaging, flyers and shelf cards outlive variants. Print a short redirect you control.
  8. Trusting a parameter because a blog listed it. Selling plans are the clearest example: documented by a third party, ruled out by Shopify. Check the developer tutorial before you build a campaign on a parameter.

FAQ

What is a cart permalink in Shopify?

A cart permalink is a URL that takes a customer to checkout with specific product variants and quantities already loaded, in the format store-domain/cart/variant_id:quantity. Shopify’s Help Center says the same link is reusable and creates a new checkout for each customer, and that optional query parameters can add discount codes, notes, line item properties and pre-filled contact details.

How do I create a checkout link in Shopify?

There are two ways. With the Buy Button channel installed, open a product in the admin, click More actions, choose Create checkout link, select a variant and copy the link. Or build it by hand: take your store domain, add /cart/, then add the variant ID, a colon and the quantity, with commas between multiple variants and any parameters after a question mark.

How do I add a discount code to a Shopify cart link?

Append ?discount= followed by the code, or &discount= if the link already has a question mark. Shopify’s developer documentation also supports several codes separated by commas, provided your discount combination settings allow those codes to be used together, and notes that a code containing a comma cannot be passed this way.

Where do I find the variant ID for a cart permalink?

Shopify documents three methods: click the variant in the product’s Variants section and read the number after /variants/ in the admin URL; add .json to the end of a product’s admin URL and find the id under variants; or create a new exploration under Analytics, Reports with Product variant ID as a dimension. The product CSV described in Shopify’s help documentation does not include a variant ID column.

Can a cart permalink go to the cart page instead of checkout?

Yes. Add storefront=true as a query parameter and the customer lands on the online store cart, where they can change quantities, remove items or keep shopping. Without it, the link goes to checkout.

Do Shopify cart permalinks work with subscriptions?

Not according to Shopify. The developer tutorial lists selling plans as a stated limitation of cart permalinks. Some third-party guides describe a selling_plan parameter, but it is not in Shopify’s documentation, so for subscription products link to the product page or use the link format your subscription app provides.

Does a cart permalink reserve inventory?

No. Shopify’s checkout documentation says inventory is held only when the customer submits their payment information, and that the cart is checked against inventory levels as the customer completes each step of checkout. If you need to hold stock for a specific customer, create a draft order and reserve the inventory there.

Do UTM parameters work on Shopify cart permalinks?

You can append them like any other query parameter, and Shopify’s marketing documentation says traffic arriving with utm_campaign in the URL is attributed to marketing. They depend on session tracking, which Shopify says can be blocked by apps and private browsers, so also put the campaign name in the note, attributes or a unique discount code, which are recorded on the order.


— Palm Beach Themes is a Miami-based Shopify app studio. We use the apps we sell, so every claim in this post comes from our own merchant testing.

If your team sends curated picks to individual customers and nobody wants to hand-build the link, that is the job we built for. See CurateList →