Tool guide
Twenty-seven tools, in three groups. Every one is scoped to the single store its connection belongs to, and which of them your assistant can see depends on that connection's access level.
This page is for understanding what each tool is for. For a compact list, see the tools reference.
- Reading — 18 tools, available at every level
- Finding Shopify resources — part of that 18, and worth its own section
- Writing — 7 tools, needs write access
- Deleting — 2 tools, needs delete access
Reading
get_setup_health
Purpose: Report whether the free gift widget can actually appear on this store.
When to use: First, whenever anything is described as "not showing" — a gift, a widget, an offer. It reaches a conclusion rather than handing back raw data.
Parameters: none
Returns: The live theme and whether it supports app blocks, whether the app embed is switched on,
campaign counts by status, the currently active campaigns, and issues — a list of concrete problems
with codes such as APP_EMBED_DISABLED, THEME_NOT_OS2, NO_CAMPAIGN and NO_ACTIVE_CAMPAIGN.
Read issues before anything else. If it is empty, the widget is able to render and the problem
lies elsewhere — usually in the campaign's own conditions, which is get_campaign_details.
Each section fails independently: if Shopify is unreachable, campaign counts still come back and the
failure is recorded in errors rather than taking the whole answer down.
get_campaigns
Purpose: List this store's free gift campaigns.
When to use: To answer "what offers am I running", or to find a campaign id before asking for its details.
Parameters:
| Name | Type | Required | Notes |
|---|---|---|---|
status | active · scheduled · expired | No | Omit to list everything |
Returns: total, and a summary of each campaign — id, name, status, type, target pages,
schedule, discount code.
These three statuses are the only ones that exist. There is no draft state, and deleted campaigns are never returned, so everything listed is something you still have. Results are capped at 100.
get_campaign_details
Purpose: The full configuration of one campaign.
When to use: After get_campaigns, once you know which campaign is in question. This is where
trigger conditions, gift products, discount settings and schedule live — the things that explain why
an offer is or is not applying.
Parameters:
| Name | Type | Required | Notes |
|---|---|---|---|
campaignId | string | Yes | From get_campaigns |
Returns: found, and the campaign's complete configuration.
An id that does not exist on this store comes back as found: false with an explanation, not an
error. An id belonging to a different store is treated the same way — there is no way to read
another store's campaign through this key.
get_analytics
Purpose: Free gift performance over a recent window.
When to use: For anything about revenue, orders, or whether the offers are working.
Parameters:
| Name | Type | Required | Notes |
|---|---|---|---|
days | integer 1–365 | No | Window length, ending yesterday. Default 30 |
includeToday | boolean | No | Extend to the store's current day |
ianaTimezone | string | No | Override the timezone. Leave it out |
Returns: The period actually used, the store's currency, and five metrics — orders, revenue,
conversionRate, aovByFG and aovStore. Each carries value, previous and changePercent, so
every figure arrives with its own comparison.
Comparing aovByFG against aovStore is the fastest way to answer whether gifts lift order
value. One is the average order value of orders that involved a gift; the other is the whole
store's. If the first is not higher, the offers are not doing what they were set up to do.
Figures are always reported in the store's own timezone, echoed back in the result. A store set to New York rolls over its day at a different moment than you do, so "yesterday" is the store's yesterday, not yours.
Windows that end yesterday are cached. includeToday is not — today is incomplete, the result is
marked as partial, and it should be presented as a period in progress rather than a finished one.
check_gift_product
Purpose: Explain whether specific products can actually be given as a gift.
When to use: When a gift is not being added to the cart. The cause is almost always one of three things: out of stock, not published to the online store, or the product is a draft.
Parameters:
| Name | Type | Required | Notes |
|---|---|---|---|
handles | string | Yes | One handle, or several separated by commas. Max 50 |
Returns: Per product — status, inventory, whether it is published, its variants, and
canBeGifted with an issues list. Per variant — stockStatus and giftable.
Trust giftable, stockStatus and issues for the verdict. Do not infer availability from
inventoryQuantity or inventoryPolicy: a variant with stockStatus: "not_tracked" has inventory
tracking switched off and is always available, which is exactly why its quantity and policy come back
empty.
A handle is the part of the product's URL after /products/ — not the product title.
get_widget_types
Purpose: List the widget types this store has.
When to use: Before get_widget_settings, to get a valid type name.
Parameters: none
Returns: total and, for each type, its internal name, its display title, whether it is a
premium widget and whether it is currently locked on this plan.
get_widget_settings
Purpose: Read the visual settings of one widget type — colours, text, layout.
When to use: For questions about how a widget looks rather than what triggers it.
Parameters:
| Name | Type | Required | Notes |
|---|---|---|---|
type | string | Yes | For example progress-bar, from get_widget_types |
Returns: found, and the saved settings for that type. A type this store has never configured
returns found: false and a pointer back to get_widget_types.
get_translations
Purpose: Report the storefront wording shoppers actually see.
When to use: For "what text do my customers see", or "what has been translated".
Parameters:
| Name | Type | Required | Notes |
|---|---|---|---|
locale | string | No | Restrict to one language, e.g. vi. Omit for all |
Returns: activeLanguages, a total string count, and two lists — widgets and campaigns —
split that way because widget text and campaign text are edited on different screens. Each entry
carries both layers of wording:
text— what was typed on the Design screen. This is what shoppers see, and what any language without its own translation falls back to.translations— the per-language overrides added on the Translations screen.
Only customised strings are listed. A string that does not appear is using the app's built-in wording — which is not the same as having no wording at all. "This store has not customised any text" means the defaults are in use, not that the widget is blank.
Defaults are per-store: a shop installed in French starts with French wording, and that French is treated as untouched rather than as a customisation.
get_app_settings
Purpose: Read the global app configuration — the switches that apply across every campaign.
When to use: For store-wide behaviour. For one campaign's own rules, use
get_campaign_details instead.
Parameters: none
Returns: found and the saved configuration.
get_plan_status
Purpose: Report this store's plan and how much of its limits are used.
When to use: For "what plan am I on", or "have I hit a limit".
Parameters: none
Returns: The plan, whether a trial is running, campaign allowance against campaigns live,
revenue used against the cap and when that cap resets, and any issues such as a limit already
exceeded.
This tool reports your store's own situation only. It does not list plans, quote prices, or suggest what an upgrade would cost. Anything price-shaped belongs in the app's billing page, which goes through Shopify Billing.
Finding Shopify resources
Eight tools, all read scope, all the same shape: the merchant names something in words, the tool searches this store for it, and the assistant asks which one they meant if more than one matches.
| Tool | Finds | Parameters |
|---|---|---|
find_gift_products | Products that could be given as a gift | query |
find_trigger_products | Products that could trigger an offer | query |
find_collections | Shopify collections | query |
find_customer_segments | Shopify customer segments | query |
find_customer_locations | Markets and countries | query |
find_shipping_rates | Shipping rates, by zone | query |
find_markets | Every Shopify Market | none |
find_pos_locations | Locations usable as POS channels | query |
They exist so nothing is guessed. A campaign is built from Shopify ids, and an id an assistant invented points at nothing — or worse, at the wrong product. These tools are the only sanctioned way to turn a name into an id, and a search returns at most ten candidates so the choice stays something a person can actually make.
find_gift_products and find_trigger_products also report whether each candidate can do the job,
in blockers — out of stock, unpublished, draft, or subscription-only.
Judge stock from stockStatus, never from totalInventory. A product with
stockStatus: "not_tracked" has inventory tracking switched off and is always available, which is
why its totalInventory comes back empty. stockStatus: "unknown" means the product has more
variants than were read — a reason to ask, not to assert.
Writing
These need read and write access. A read-only connection is not offered them at all.
The shape every write shares
Nothing is created, edited or deleted in one call. The first call prepares: it validates the whole change, checks your plan, re-reads the Shopify resources involved, and returns a full preview plus a short-lived confirmation token. It writes nothing. The second call carries that token unchanged, and is the only one that writes.
This is what makes a change reviewable. The preview is the thing your assistant shows you, and the token binds it: change any commercial field and the token stops working, so an approved version cannot quietly become a different one.
get_campaign_creation_blueprint
Purpose: Report what this store may configure for one campaign type — required intent, supported options, localized defaults, limits and any policy blockers.
When to use: Before proposing a campaign, so the proposal fits this store rather than the product in general. It reserves nothing and creates nothing.
Parameters: type
prepare_campaign → add_campaign
Purpose: Build a new campaign.
prepare_campaign takes the whole intended campaign, validates it against the blueprint, resolves
the Shopify resources, applies safe defaults, and returns the complete preview with a token.
add_campaign takes that campaign unchanged plus the token, and creates it.
When to use: Any "set up a campaign that…" request. Show the merchant the entire preview and get an explicit yes before committing — creation may start or schedule a live Shopify discount.
Repeating the same confirmed call is idempotent: it returns the campaign that was already made rather than making a second one.
prepare_campaign_edit → edit_campaign
Purpose: Change an existing campaign.
prepare_campaign_edit re-reads the campaign's current resources so an edit is judged against what
is live now, not what was live when the chat started. edit_campaign applies the change.
edit_campaign accepts around a hundred optional fields — wording, schedule, thresholds, gifts,
triggers, customer eligibility, delivery, discount economics, usage limits, structured product
settings and translations. Only the fields your campaign type actually renders are accepted; any
other is refused by name rather than silently dropped.
Resource lists are never accepted as objects the assistant built itself. To change which products
trigger an offer, it searches with find_trigger_products, confirms the match with you, and passes
only ids. That is what stops a stale or invented product reaching a live discount.
set_campaign_status
Purpose: Turn a campaign on or off.
When to use: Pausing and resuming. This is the safe alternative to deletion — it keeps the campaign and everything in it.
Parameters: campaignId, status
edit_widget
Purpose: Change a widget's allowlisted settings and wording.
When to use: "Make the progress bar green", "reword the popup". Text, colours, layouts, preset icons, display behaviour and numeric styling are editable; anything outside the allowlist is refused.
Parameters: type, fields, translationUpdates
Deleting
These need read, write, and delete access — the level above write, granted separately.
prepare_delete_campaign → delete_campaign
Purpose: Remove a campaign for good.
prepare_delete_campaign writes nothing. It returns what deleting would actually remove: the
campaign, its Shopify discounts, what shoppers stop seeing, and a snapshot of the configuration so
it survives in the conversation afterwards. delete_campaign performs it.
Parameters: campaignId; then campaignId and confirmationToken
This cannot be undone. The token is bound to the campaign's configuration at preview time, so if
anything about the campaign changes in between the deletion is refused and the assistant has to show
you the current state first. Historical analytics survive; the campaign does not. If the goal is to
stop an offer rather than erase it, use set_campaign_status.
Shopify is cleaned up before the app's own record, and the record is only removed once the discount is confirmed gone — the opposite order would leave a live discount still applying at checkout with nothing in the admin to explain it.
Related
- Tools reference — the compact list, and the matching REST endpoints
- Recipes — these tools in sequence, on real questions