Fourthwall
Make custom apparel, merch, and streetwear with Fourthwall, using ChatGPT. Turn a logo or image into real products: t-shirts, hoodies, hats, mugs, stickers, plushies, or whatever swag / apparel you can dream up. Type your ideas and get live previews for different colors and design placements. Once you're happy, you can place an order. No minimums required. You can also sell your products online or run a campaign with Fourthwall: manage promotions, track orders, and see what's selling without leaving the chat. Fourthwall handles the hard parts: manufacturing, fulfillment, shipping, customer support, and sales tax. No upfront costs, no inventory, no monthly fees.
- Integration type
- Plugin
- Verification status
- Not applicable
- Platform
- ChatGPT
- Primary Subcategory
- Custom Print & Personalized Keepsakes
- Secondary Subcategories
- None listed
- Brand
- Fourthwall
- Access
- Account required
- First tracked
- 2026-07-02
- Tool count
- 136
- Geography
- US
The Primary Subcategory used for this profile’s headline score.
Other Subcategories where the Integration is visible.
ChatGPT Plugin Discoverability Score
ChatGPT organic discovery is not live yet
Fourthwall is tracked in the ChatGPT Plugin registry. Public organic-discovery measurement is not live for ChatGPT yet, so there is no score to publish today.
Get notified when your score goes live
Enter your work email and we’ll notify you when ChatGPT Plugin organic discovery scoring launches.
No spam. Unsubscribe any time.
Competing in ChatGPT Custom Print & Personalized Keepsakes
View CategoryHow the Discoverability Score works
Organic discovery scoring for Fourthwall on ChatGPT is not live yet. The score will use measured agent conversations when it launches.
Organic discovery scoring is pending. Your Plugin score will appear on this scale when measurement goes live.
FoundDiagnostic
Whether Claude found your Plugin in connector search. It must be Found before it can reach the picker, but the score counts picker appearances—not search results.
PickedMain score
How often your Plugin appeared in the picker, or Claude invoked it directly, across contested conversations. This percentage is the Discoverability Score; the headline number is rounded.
PositionedDiagnostic
What position your Plugin appeared in when it was shown in the picker. This shows prominence, but it does not affect the score.
136 tools agents can invoke
Reactivate a promotion (set status to LIVE). Only works for ENDED promotions. Cannot activate ARCHIVED or ALL_USED promotions. Use when a shop owner wants to re-enable a previously deactivated discount code.
ecommerce_activate-promotion
Adds a new print region to an existing customization's design state with an initial image. Use this when the user wants to place artwork on a region that the catalog product supports (`availableRegions` from inspect-design) but the current customization doesn't yet contain. edit-design cannot add new regions — it only mutates regions already present in the state. BEFORE calling: - inspect-design to confirm the regionId is in `availableRegions` and not already in the state's `sizes[*].regions[*].regionId` list (i.e. not already added). - The image must already be saved (use ecommerce_save-media-library-image first); pass its CDN href plus natural width/height in pixels. AFTER calling: use rerender-design-previews with customizationId to regenerate preview images. Returns the updated inspect summary plus the same availableRegions list inspect-design exposes. Errors: - DESIGN_PIPELINE_INVALID_REGIONS — regionId is not on the catalog product. Surface validRegions to the user. - DESIGN_PIPELINE_BAD_REQUEST with "already part of this design" — the region is already in the state; use edit-design instead.
ecommerce_add-design-region
Adds colors to the draft's color selection. Does NOT affect the live product. Each color must appear in the product's availableColors (case-sensitive). Read availableColors from get-draft-attributes before calling. Passing an unknown color throws CUSTOMIZATION_INVALID_COLORS with the valid set — surface the valid options to the user and stop; do not retry with guessed spellings (e.g. "heather grey" vs "Heather Gray"). Use rerender-design-previews after to see updated previews. Use apply-draft-to-product when the creator confirms changes.
ecommerce_add-draft-colors
Adds sizes to the draft's size selection. Does NOT affect the live product. Each size must appear in the product's availableSizes (case-sensitive). Read availableSizes from get-draft-attributes before calling. Passing an unknown size throws CUSTOMIZATION_INVALID_SIZES with the valid set — surface the valid options to the user and stop; do not retry with guessed sizes (e.g. requesting "3XL" when the product caps at "2XL"). Use rerender-design-previews after to see updated previews. Use apply-draft-to-product when the creator confirms changes.
ecommerce_add-draft-sizes
Internal helper for the media-library widget. Run a vision analysis on an image that already has a URL (a selected media-library image) and return its description plus the analyzed URL. Not a user-facing action — the widget calls it when the user confirms a selected image. Safe to re-call: results are cached by image identity. Parameters: - imageUrl: The image to analyze — a media-library CDN URL or a GCS object URL in Omni's bucket.
Syncs the current draft state to the live product. Call this ONLY when the creator explicitly confirms the changes. This atomically: 1. Reads the draft's current attributes and design state 2. Rebuilds the product's variants from the draft 3. Recalculates pricing Use rerender-design-previews after to see final product previews.
ecommerce_apply-draft-to-product
Stage 1 of brand extraction: analyze a brand sheet and stash a checkpoint. Runs the vision analyzer on the image. Does NOT extract a logo or run any image generation — that happens in `brand_extract_assets`. Returns a `checkpoint_uri` that the follow-up call uses to pull only the artworks/logo it actually needs. Parameters: - image_path: Source brand sheet (PNG/JPEG) or brand deck (PDF). For PDF input a cheap text-only selector picks the most informative pages (at most 6), rasterizes them, and sends them to the vision model in one call — useful for multi-page merch decks or brand guidelines. When pages were dropped, `checkpoint_md` carries a NOTE saying so. Accepts a local filesystem path, an `http(s)://` URL (fetched anonymously), or a `gs://bucket/key` URI (fetched via the gateway's Workload Identity SA). The `https://storage.googleapis.com/<bucket>/<key>` form (and its `storage.cloud.google.com` / virtual-hosted variants) is also accepted and routed through the SA. Returns a dict with: - checkpoint_uri: opaque URI (gs:// in prod, file:// in local dev) that pins this analysis run; pass back as the first argument to `brand_extract_assets`. - brand_name: confirm with the user before spending image-gen calls. - checkpoint_md: a markdown summary of the brand (mood, palette, typography, logo description, products, and the artwork "menu" with ids and descriptions). Use this to decide which `want_artwork_ids` to request next. - artwork_candidates: structured list of `{id, kind, name, description}` for the same menu — the `id` values are what `brand_extract_assets` accepts in `want_artwork_ids`. - logo_description: verbal description of the primary logo, helpful for confirming "yes this is the right brand" before extraction. Typical flow: r1 = brand_analyze(image_path="...") # confirm r1["brand_name"] with the user, pick artwork ids from # r1["artwork_candidates"], then: r2 = brand_extract_assets( checkpoint_uri=r1["checkpoint_uri"], want_logo=True, want_artwork_ids=["main_logo", "side_heart"], ) For long brand decks where the synchronous round-trip risks an MCP proxy timeout, use `brand_analyze_start` + `brand_analyze_status` instead — they expose the same pipeline behind a job_id poll loop.
Async variant of `brand_analyze`. Enqueues the analysis and returns immediately, or returns the inline result if the job finishes inside the ~50s budget. Parameters: - image_path: same shape as `brand_analyze` (local path, http(s) URL, gs:// URI, or storage.googleapis.com URL). Returns either: - `{"status": "done", "result": {...}}` — the analysis finished inside the inline wait window; treat `result` exactly like `brand_analyze` would have returned. - `{"job_id": "ba_...", "status": "pending" | "running", "progress": {...}}` — the job is still in flight. Poll `brand_analyze_status(job_id)` every 5–10 seconds. Typical brand-deck jobs take 120–180s; very short single-image inputs may return inline. On failure surfaces `{"job_id": "ba_...", "status": "failed", "error": "..."}` rather than raising, so the model can decide whether to retry.
Poll the status of a `brand_analyze_start` job. Parameters: - job_id: the id returned by `brand_analyze_start`. Returns: - `{"job_id", "status": "pending" | "running" | "done" | "failed", ...}` - `progress` (optional): `{stage, pct}` while running. - `result` present when status=="done" — same shape as `brand_analyze`. - `error` present when status=="failed". Returns within ~1s. Raises if `job_id` is unknown or has aged out of the 24h TTL.
Stage 2 of brand extraction: produce just the assets you actually need. Reads the checkpoint produced by `brand_analyze`, then runs the logo stage and/or a focused per-artwork extraction for only the requested ids. Outputs are uploaded back into the same checkpoint, so calling this again with a different `want_artwork_ids` set extracts more without re-running analysis. Parameters: - checkpoint_uri: the URI returned by `brand_analyze`. - want_logo: extract the pixel-faithful 2048x2048 transparent logo PNG. Default True — flip to False on follow-up calls when you only want additional artworks. - want_artwork_ids: list of artwork ids (from `brand_analyze`'s `artwork_candidates`) to extract as transparent PNGs. Each id costs one medium-quality parallel gpt-image-2 call. Pass an empty list (or omit) to skip artwork extraction. Unknown ids raise — the message lists what's available so you can correct. At least one of `want_logo=True` or a non-empty `want_artwork_ids` must be set; otherwise the call has nothing to do and raises. Returns a dict with: - checkpoint_uri: echoed back so the model can chain another call. - brand_name - logo_compact: gs:// URI of a downsized, <512 KB transparent logo PNG. Pass it as `data` to `storefront_update-draft-theme-logo` (and to any downstream tool that wants the brand logo — there is no high-res variant; this is the canonical logo asset). None if want_logo=False or the checkpoint bucket is unset. - favicon: gs:// URI of a square <512 KB favicon PNG derived from the same logo. Pass it as `data` to `storefront_update-draft-theme-favicon`. None if want_logo=False or the checkpoint bucket is unset. - artworks: list of {id, kind, name, upload, media} for every successfully extracted id. `upload` is the gs:// URI; `media` is the media-library entry — pass `media[].media_url` to ecommerce tools like `ecommerce_generate-product-design-previews` so they can resolve the asset without a separate upload step. - failed_artworks: list of {id, kind, name, error_kind, message} for ids the model service refused. `error_kind` is one of `moderation_blocked`, `rate_limited`, `bad_request`, `api_error`, `other` — `moderation_blocked` means OpenAI's safety system rejected that specific artwork prompt; the caller should drop or rephrase that id and retry without it. - cost: usage summary for the artwork stage — `{input_text_tokens, input_image_tokens, output_image_tokens, total_tokens, estimated_usd, calls}`. Estimate uses published gpt-image rates; the OpenAI invoice is authoritative. For long extractions where the synchronous round-trip risks an MCP proxy timeout, use `brand_extract_assets_start` + `brand_extract_assets_status` — same pipeline behind a job_id poll.
Async variant of `brand_extract_assets`. Enqueues the extraction and returns immediately, or returns the inline result if the job finishes inside the ~50s budget. Parameters: same as `brand_extract_assets`. Returns either: - `{"status": "done", "result": {...}}` — the extraction finished inline; treat `result` exactly like `brand_extract_assets` would have returned. - `{"job_id": "bx_...", "status": "pending" | "running", "progress": {...}}` — the job is still in flight. Poll `brand_extract_assets_status(job_id)` every 5–10 seconds. Typical extractions take 60–180s depending on how many artwork ids you requested. On failure surfaces `{"job_id": "bx_...", "status": "failed", "error": "..."}`.
Poll the status of a `brand_extract_assets_start` job. Parameters: - job_id: the id returned by `brand_extract_assets_start`. Returns: - `{"job_id", "status": "pending" | "running" | "done" | "failed", ...}` - `progress` (optional): `{stage, pct}` while running. - `result` present when status=="done" — same shape as `brand_extract_assets`. - `error` present when status=="failed". Returns within ~1s. Raises if `job_id` is unknown or has aged out of the 24h TTL.
Bulk-update prices across an offer's variants. Call get-offers-by-ids first to see current variants and prices. Pick ONE mode: - UNIFORM — omit groupBy. Set `price` (and optional `compareAtPrice`) on every active variant. - BY ATTRIBUTE — set groupBy to SIZE/COLOR/CUSTOM and pass `priceUpdates` as an array of {attributeValue, price, compareAtPrice?} entries. Variants whose attribute value is not in the array are left unchanged. Example priceUpdates: [{"attributeValue":"S","price":10.00},{"attributeValue":"L","price":20.00,"compareAtPrice":30.00}] Rules: - `price` and `priceUpdates` are mutually exclusive — pass exactly one. - All prices are set in USD dollars, NOT cents (9.99 = $9.99). Shops price in USD; checkout handles currency conversion automatically. - `priceUpdates` is a plain JSON array, NOT a stringified JSON string.
ecommerce_bulk-update-offer-variant-prices
Cancel giveaway links. IRREVERSIBLE. Always confirm with the user first. Provide EITHER giftId (cancel one link) OR packageId (cancel all available links in package). Only AVAILABLE links are cancelled. Already redeemed links are unaffected.
ecommerce_cancel-giveaway-links
Cancel a full or partial order. IRREVERSIBLE. ALWAYS confirm with the user before calling. Before calling, use `get-order-cancellation-by-ids` to check eligibility: - For a full cancellation: `fullyCancellable` must be true. - For a partial cancellation: `partiallyCancellable` must be true; pass an `itemsToCancel` subset of `cancellableItems` (variantId + quantity). Omit `itemsToCancel` (or pass empty) to cancel the whole order. Payment handling — done automatically, no separate confirmation step: - If the shop's balance covers the refund, the refund is issued immediately (status = CANCELLED). - If the balance is insufficient, the shortfall is charged to the shop's card and the cancellation is queued (status = CHARGE_INITIATED). A background job finalizes the cancellation once the charge settles. If the charge fails, the cancellation is abandoned and the order stays open. The response fields `fromBalance`, `chargeAmount`, and `status` make this explicit. Always surface these to the user — especially `chargeAmount` when > 0. Permission: requires ORDER_WRITE role on the shop. Typical rejection reasons (returned as errors from the endpoint): - STATUS: order already cancelled, failed, etc. - IN_PRODUCTION_OR_DELIVERING: items in fulfillment - OLDER_THAN_ALLOWED_CANCELLATION_TIMEFRAME - CONTAINS_DIGITAL_ITEMS / GIFT_CARD_ALREADY_USED - REFUND_IN_PROGRESS: an existing refund is pending; wait or resolve first - ExpectedChargeAmountChanged: a rare race where the required charge changed between our estimate and submission; just retry.
ecommerce_cancel-order
Update the shipping address on an order. Only allowed before items enter production or shipping. The use case verifies: - Order status permits address changes (not in production/shipped/delivered/cancelled) - All items have `canUpdateAddress == true` for this issuer - Third-party fulfillment systems accept the update If the address is identical to the current one, the call is a no-op and returns the order unchanged. Emits `OrderAddressChangedEvent` on change. Permission: requires ORDER_WRITE role on the shop. Required fields: firstName, lastName, address1, city, country. Optional fields: address2, state, zip, phone. Returns the updated order summary (same shape as get-order-details-by-ids).
ecommerce_change-order-shipping-address
Internal helper for the show-upload widget. Confirm that an image finished uploading and return a vision analysis of it. Not a user-facing action — the widget calls it after PUTting the file. Safe to re-call: an already-confirmed upload returns the cached analysis. Returns two URLs for the same image, used for different purposes: - url: the stable internal GCS URL — use this for any further processing (handing the image to the model, chaining into other tools). Never expires, but the browser can't fetch it. - publicUrl: a time-limited signed read URL — use this only to show the image to the user (e.g. the widget's preview). Don't pass it on for further processing; it expires after ~60 minutes. Parameters: - uploadId: The id returned by request-upload-url.
Create a new bundle offer — a group of existing offers sold together at a combined price. The bundle starts in HIDDEN state. Use update-bundle to change status to PUBLIC when ready.
ecommerce_create-bundle
Create a new collection for the shop. Collections group products (offers) together for display on the storefront. Required fields: - name: Collection display name (max 200 chars) - description: Collection description (HTML allowed) - available: Whether the collection is available - offerIds: List of Offer IDs to include in the collection Optional fields: - availableFrom/availableTo: Schedule when the collection becomes visible (ISO 8601 datetime) The collection is created in HIDDEN state. Use update-collection-state to make it PUBLIC. Returns the created collection with: - Identity: id (CollectionId), shopId (ShopId), name, slug, description - Visibility: available (boolean), state (PUBLIC/HIDDEN/ARCHIVED) - Time-based availability: availableFrom (nullable ISO 8601), availableTo (nullable ISO 8601) - Products: offerIds (list of OfferIds) - Sorting: sortingStrategy (MANUAL/BEST_SELLING/NEWEST/OLDEST/NAME_ASC/NAME_DESC)
ecommerce_create-collection
Create a combined listing — merges color variants from multiple offers (same product library) into one storefront product. Unlike bundles, combined listings share the same product library. All offers must have compatible colors (no duplicates). The listing starts in HIDDEN state. Use update-combined-listing to change status to PUBLIC when ready. Use validate-combined-listing first to check if offers are compatible.
ecommerce_create-combined-listing
Create gift cards (store credit) with an amount, optionally with custom codes. Skip the `codes` parameter unless the user explicitly asks for specific codes — random 12-character friendly codes (e.g., "L3WQNU1MV4W9") will be generated automatically. Use `numberOfCards` to control how many cards to create with auto-generated codes (defaults to 1, max 50). When `codes` IS provided: single code = single card, multiple codes = bulk group (1-50). All cards share the same amount and expiration. Codes are auto-uppercased, 8-36 chars, alphanumeric. Returns created card details (single) or group ID (bulk). Use get-gift-cards to browse. All amounts are set in USD dollars (NOT cents) — gift cards are priced in the shop's USD, and checkout handles currency conversion for non-USD customers. Examples: • Auto-generated single: amount=50 • Auto-generated bulk: numberOfCards=10, amount=25 • Single with custom code: codes=["GIFT50"], amount=50 • Bulk with custom codes: codes=["VIP1","VIP2","VIP3"], amount=25, expiresAt="2026-12-31T23:59:59Z"
ecommerce_create-gift-cards
Create a package of giveaway links (free product URLs) for a product. Each link is a unique URL someone can use to claim a free product. Links are grouped into a package. REQUIRED: • offerId: product ID (UUID). Use get-offers to find IDs. • numberOfGifts: how many links to generate (1-50) Returns: packageId + list of created gift IDs. Use get-giveaway-links to see URLs.
ecommerce_create-giveaway-links
Create a membership discount code (percentage off membership subscription). ⚠ NOT SUPPORTED — do NOT promise these to the user: expiration / end date / start date / scheduled activation. There is no time-based field. `durationCharges` is the number of BILLING CYCLES the discount applies for (not a calendar date). To stop a code, use deactivate-promotion. DELIVERY MODE — provide exactly one: • code: single promo code (e.g. "MEMBER20") — most common • codes: list of bulk codes for multi-code promotions REQUIRED: • percentage (1-100): discount percentage • subscriptionType: ALL_MEMBERS | MONTHLY_ONLY | ANNUAL_ONLY OPTIONAL: • tierIds: restrict to specific membership tier IDs (null = all tiers). • durationCharges: how many billing cycles the discount lasts (1-1000). Null = lifetime (discount applies to every cycle, never auto-stops). • newMembersOnly: only new members can use this code (default false) • limitToSingleUse: limit code to one total redemption (default false) Examples: • 20% off all members for life: code="MEMBER20", percentage=20, subscriptionType="ALL_MEMBERS" • 50% off first 3 cycles, annual only: code="ANNUAL50", percentage=50, subscriptionType="ANNUAL_ONLY", durationCharges=3 • Bulk codes for new monthly members: codes=["NEW1","NEW2"], percentage=30, subscriptionType="MONTHLY_ONLY", newMembersOnly=true
ecommerce_create-membership-promotion
Creates offers from previously generated design previews — processes multiple designs concurrently. Each design is processed independently — failures for one do not affect others. IMPORTANT: You must call generate-product-design-previews first to get customizationIds. Waits up to 1 minute per design for completion, then returns results. Each result contains: - customizationId: the input customization ID - pipelineId, status, type, offerId?, images[], priceSuggestions?, error? — present on success - bulkError?: string — present on failure Use this tool to: - Create offers after the user approves the preview images Offer names default to the product name when omitted. Offer descriptions default to empty when omitted. Offers are created in HIDDEN state — use update-offer-status to publish. WORKFLOW after creation: tell the user the default price that was applied (read it from priceSuggestions in the result) and that it can be changed any time, then offer to order a physical sample (create-sample-checkout — charged at manufacturing cost only).
ecommerce_create-offers-from-designs
One-shot: creates offers directly from product designs in a single call. Skips the preview→approve step — use this when the user pre-approved (e.g. "create offers for all of these") or already saw mockups and just wants offers made. Products are processed concurrently — no polling needed, results returned directly. Each product is processed independently — failures for one product do not affect others. For the preview-first flow (review mockups, then create offers from approved ones), use generate-product-design-previews followed by create-offers-from-designs. regionUrls MUST be URLs from the shop's media library (use get-media-library-images, or upload via request-media-upload-link → PUT file → save-media-library-image). BEFORE calling this tool, use get-catalog-product-details to check: 1. supportsBackendRendering must be true for the product 2. Only use regions from printAreas where supportsBackendRendering=true 3. If a print area has placements, pass the desired placementId for that region Each result contains: - productId: the input product ID - pipelineId, status, type, customizationId, offerId, images[], priceSuggestions?, error? — present on success - bulkError?: string — present on failure WORKFLOW after creation: tell the user the default price that was applied (read it from priceSuggestions in the result) and that it can be changed any time, then offer to order a physical sample (create-sample-checkout — charged at manufacturing cost only).
ecommerce_create-offers-from-products
Creates a checkout session to order product samples at cost. Use get-offers or get-offers-by-ids to find variant IDs for the items to order. Returns: - checkoutPath: Relative path to the checkout page (e.g., "/checkout/ch_abc123") Sample credits are applied automatically at checkout when available; if the balance is zero or insufficient, the buyer pays the remaining amount on the checkout page. You do NOT need to check the balance beforehand — never gate this call on get-sample-credit-balance. Examples: - Order 2 units of a variant: items="8d79c46d-9a56-4266-885b-4b02a21aacd2:2" - Order multiple variants: items="aaa-uuid:1,bbb-uuid:3"
ecommerce_create-sample-checkout
Create a shop discount promotion. ⚠ Use ONLY the parameter names declared on this tool — do not invent or paraphrase. For an entire-order discount, OMIT `productIds` (there is no `appliesTo` parameter). ⚠ NOT SUPPORTED — do NOT promise these to the user, even if help articles imply otherwise: • Expiration / end date / start date / scheduled activation — there is no time-based field. To stop a promotion, use deactivate-promotion. To cap total usage, set `maxUses`. • Stacking rules, per-product discount tiers, BOGO without using FREE_PRODUCTS. All monetary amounts are set in USD dollars (NOT cents) — shops price in USD; checkout handles per-customer currency conversion automatically. RECIPES (each line shows the required fields per discountType): • 10% off all orders: { discountType: "PERCENTAGE", code: "SAVE10", percentage: 10 } • $10 off + free shipping: { discountType: "FIXED_AMOUNT", code: "TAKE10", amount: 10, freeShipping: true } • Free shipping: { discountType: "FREE_SHIPPING", code: "SHIPFREE" } • Free product: { discountType: "FREE_PRODUCTS", code: "FREEGIFT", freeVariantId: "<variant-uuid>" } • Bulk codes: replace `code` with `codes: ["VIP1","VIP2"]`. Auto-apply: replace `code` with `autoApplyTitle: "Summer Sale"`. COMMON OPTIONS (all types): • productIds: restrict to specific offer IDs. OMIT for entire-order (default). • freeShipping: bundle free shipping (PERCENTAGE, FIXED_AMOUNT, FREE_PRODUCTS) • minimumOrderAmount: USD dollars (e.g. 50 = $50) • allowedCountries: ISO 3166-1 alpha-2 codes (e.g. ["US","CA"]). Omit = all. • maxUses (1-1000, omit = unlimited), onePerCustomer (default false) • shippingOption (PERCENTAGE only): EXCLUDED | FREE | FREE_LOWEST_ONLY • lowestShippingOnly (FREE_SHIPPING only); freeProductQuantity (FREE_PRODUCTS only, default 1)
ecommerce_create-shop-promotion
Deactivate a promotion (set status to ENDED). Customers can no longer use this code. To reactivate later, use activate-promotion. To permanently remove, use delete-promotion.
ecommerce_deactivate-promotion
Create a copy of an existing offer (product). The duplicated offer will have a new ID and a modified slug (with a suffix). The duplicate starts in HIDDEN state so it won't be visible on the storefront until published.
ecommerce_duplicate-offer
Edits an existing customization's design state and returns the updated layout. BEFORE calling: use inspect-design to understand the current layout (imageIds, indices, region dimensions) and to read availableRegions — the legal values for `target.regionId`. Passing a regionId not in availableRegions returns DESIGN_PIPELINE_INVALID_REGIONS with the valid set; surface that to the user and stop — do not retry with another guessed regionId. AFTER calling: use rerender-design-previews with customizationId to regenerate preview images. Operations: - scale-absolute: set size as fraction of region (regionFraction: 0.0-1.0) - scale-relative: multiply current size (factor: e.g. 1.5 = 150%) - move-absolute: snap to named position (anchor: top-left/top-center/top-right/center-left/center/center-right/bottom-left/bottom-center/bottom-right) - move-relative: offset by fraction of region (dx: -1.0 to 1.0, dy: -1.0 to 1.0) - rotate: set rotation (degrees) - replace-image: swap image URL (href, naturalWidth, naturalHeight) - remove: delete image from region - add-image: add new image (href, width, height, optional regionFraction, anchor) - reorder: change z-order (position: numeric z-index) Target filtering: sizes (e.g. ["S","M"]), regionId (e.g. "front"), imageId (dataId from inspect), imageIndex (0-based). Omit target fields to apply to all. Returns updated inspect summary with all image positions.
ecommerce_edit-design
Edits tracking information on existing self-fulfilled (creator-fulfilled) order fulfillments. Supports batch updates (up to 10). WHEN TO USE: A creator has shipped one or more existing self-fulfilled orders and you need to update the carrier and tracking number on the existing fulfillment. This tool cannot create new fulfillments — it only edits existing ones. INPUT FORMAT: Each entry is a pipe-delimited string with exactly 3 parts: fulfillmentId|trackingCompany|trackingNumber All 3 parts are required: - fulfillmentId: starts with "ful_" prefix (get it from "get-fulfillment-details") - trackingCompany: carrier name — one of: USPS, UPS, FedEx, DHL, Canada Post, Royal Mail, or other carrier - trackingNumber: the tracking number provided by the carrier EXAMPLES: - ["ful_abc123|USPS|9400111899223100001234"] - ["ful_abc123|USPS|9400111899223100001234", "ful_def456|FedEx|794644790138"] WHAT HAPPENS: The fulfillment transitions to PACKAGED status. A shipment tracker with a customer-visible tracking page URL is created in the background (not in this response). RETURNS: List of updated fulfillments with id, orderId, status, items, and shippingLabels. RELATED: Use "get-fulfillment-details" first to look up fulfillment IDs for an order.
ecommerce_edit-self-fulfilled-tracking
Creates design preview pipelines for multiple products and generates mockup images. Use this when the user wants to review mockups BEFORE offers are created — then call create-offers-from-designs on approved customizationIds. If the user has already pre-approved (e.g. "create offers for all of these"), prefer create-offers-from-products instead — it goes straight to offer creation in one call and avoids re-rendering the previews. Products are processed concurrently — no polling needed, results returned directly. Each product is processed independently — failures for one product do not affect others. regionUrls MUST be URLs from the shop's media library (use get-media-library-images, or upload via request-media-upload-link → PUT file → save-media-library-image). BEFORE calling this tool, use get-catalog-product-details to check: 1. supportsBackendRendering must be true for the product 2. Only use regions from printAreas where supportsBackendRendering=true 3. If a print area has placements, pass the desired placementId for that region IMPORTANT: Each product has its own design settings (regions, placements) because different products have different print areas (e.g., 'front_large' vs 'front'). Use get-catalog-product-details for each product to determine the correct region names and placements. Each result contains: - productId: the input product ID - pipelineId, status, type, customizationId, images[], priceSuggestions?, error? — present on success - bulkError?: string — present on failure WORKFLOW: Show images to the user — do NOT quote priceSuggestions at this stage; pricing is applied at offer creation, not on previews. If approved, call create-offers-from-designs with customizationIds. To re-render an existing customization after edit-design, use rerender-design-previews instead.
ecommerce_generate-product-design-previews
Get the Affiliate Earnings analytics report for the shop within a date range: confirmed affiliate referral bonus earnings. This report shows affiliate earnings over time with the following columns per row: - date: The time period - earnings: Total confirmed affiliate referral bonus earnings for this period (USD) - payout_count: Number of individual affiliate payout events in this period IMPORTANT - Aggregation precision selection: Each row represents one time unit. Choose the finest granularity that produces at most 31 rows: - HOUR: use only for ranges up to 31 hours (up to ~1 day) - DAY: use only for ranges up to 31 days (up to ~1 month) - WEEK: use only for ranges up to 31 weeks (up to ~7 months) - MONTH: use only for ranges up to 31 months (up to ~2.5 years) - QUARTER: use only for ranges up to 31 quarters (up to ~7 years) - YEAR: use for ranges longer than 31 quarters For example: "last 2 years" → MONTH (24 rows), "last week" → DAY (7 rows), "last 6 months" → WEEK (~26 rows), "today" → HOUR (24 rows), "last 5 years" → QUARTER (20 rows). Examples: - Monthly affiliate earnings for 2024: from="2024-01-01T00:00:00Z", to="2024-12-31T23:59:59Z", aggregationPrecision="MONTH" - Weekly affiliate earnings: from="2024-10-01T00:00:00Z", to="2024-12-31T23:59:59Z", aggregationPrecision="WEEK"
ecommerce_get-affiliate-earnings-report
Retrieves all connected integrations for the shop. This is a high-level overview — for TikTok or YouTube details, use get-tiktok-configuration or get-youtube-integrations. Returns a list of integrations, each with: - app: Integration identifier (TWITCH_GIFTING, TWITCH_DISCOUNTS_FOR_SUBS, YOUTUBE_PRODUCT_SHELF, TIKTOK_SHOP, INSTAGRAM_SHOP, INSTAGRAM_CHECKOUT, TWITTER_SHOP, STREAMELEMENTS, STREAMLABS, TIKTOK_FEED, INSTAGRAM_FEED, SHIPSTATION, LAYLO, KLAVIYO, MAILCHIMP, KIT, BEEHIIV, FWDISCORD, PLEDGE, BOOKFUNNEL) - status: CONNECTED, NOT_CONNECTED, NOT_CONFIGURED, IN_PROGRESS, COMING_SOON, EXTERNAL, BROKEN - categories: list of SOCIAL_COMMERCE, ALERTS, SOCIAL_FEED, EMAIL_MARKETING, SHIPPING, OTHER - recommendations: list of sales recommendations (e.g. "SALES (priority: 1)"), empty if none - channelName: Twitch channel name (nullable, only for Twitch integrations) - missingScopes: OAuth scopes that need to be granted (nullable, only for Twitch/StreamElements) Status values: - CONNECTED: Fully set up and active - NOT_CONNECTED: Not configured at all - NOT_CONFIGURED: Partial setup (e.g., OAuth connected but configuration incomplete) - IN_PROGRESS: Setup is being processed - COMING_SOON: Feature not yet available - EXTERNAL: Configured outside Fourthwall (e.g., TikTok Feed, Instagram Feed) - BROKEN: Needs attention (e.g., missing scopes, expired auth) Use this tool to: - See all available and connected integrations for a shop - Check which sales channels are set up (TikTok Shop, YouTube Merch Shelf) - Verify email marketing tool connections (Klaviyo, Mailchimp, Kit, Beehiiv, Laylo) - Identify integrations that need attention (BROKEN status) - Get sales recommendations based on connected integrations
ecommerce_get-all-integrations
Retrieves all subscription plans available for the shop. To check the shop's current plan and usage, use get-current-subscription instead. Returns a list of plans, each with: - Identity: id, name, custom (boolean — true if specially configured for this shop), pro (boolean) - Pricing: priceAmount (BigDecimal), priceCurrency (String, e.g. "USD"), recurringPeriod (MONTHLY/YEARLY, nullable — null means one-time) - Limits: - offersLimit (Int): maximum number of products (-1 = unlimited) - membersLimit (Int): maximum team members (-1 = unlimited) - domainsLimit (Int): maximum custom domains (-1 = unlimited) - productDesignerArtworkStorageLimitBytes (Long): artwork storage for product designer - digitalProductsStorageLimitBytes (Long): storage for digital product files - Features: - digitalProductsFeePercent (Double): transaction fee percentage for digital products - creditForSamplesAmount (BigDecimal): monthly credit for ordering product samples - creditForSamplesCurrency (String): currency of sample credit - upgradable (boolean): whether the plan can be upgraded to a higher tier - tag (nullable): PRO, PRO_UNLIMITED, DEFAULT, DEFAULT_LEGACY, DEFAULT_UNLIMITED, CUSTOM
ecommerce_get-available-plans
Get the Average Order Value analytics report for the shop within a date range: average transaction metrics over time. This report shows average order metrics over time with the following columns per row: - date: The time period - total_orders: Total number of orders - unique_customers: Number of customers who placed orders - avg_tx_value: Average amount paid by customer per order - avg_gross_revenue: Average profit value per order - avg_product_revenue: Average product sales price per order - avg_product_cost: Average declared cost of self-produced products per order - avg_shipping_revenue: Average shipping cost per order - avg_donation_revenue: Average donation value per order - avg_discount_amount: Average discount value per order - avg_taxes_amount: Average taxes amount per order - avg_fourthwall_product_costs: Average cost of manufacturing of Fourthwall products per order - avg_payment_processing_fees: Average payment processing fees per order Precision: choose finest granularity producing <=31 rows (HOUR for ~1d, DAY for ~1mo, WEEK for ~7mo, MONTH for ~2.5y, QUARTER for ~7y, YEAR beyond).
ecommerce_get-average-order-value-report
Get comprehensive product details for one or more catalog products by slug. Fetches all products concurrently. Returns enriched data including material, weight, fabric weight, print area pricing, size guide, colors, sizes, reviews, and more. This is the go-to tool for answering detailed product FAQ questions. IMPORTANT: Only use slugs returned by `get-catalog-products` or `search`. Do NOT construct or guess slugs from product names — they will not match real catalog entries. Returns a list of products (one per slug, in the same order), each containing: - Identity: id, brand, brandModel, name, slug, fulfillmentType - Category: categoryPath (list of category names) - Pricing: priceFrom, priceTo (BigDecimal) - Production: productionMethod, otherProductionMethods (alternative methods for same product), minimumOrdersNumber - Print areas: printAreas — list of available print areas, each containing: - type: region identifier (e.g. "front", "back", "neck_label") - name: display name (e.g. "Front", "Back", "Neck Label") - required: boolean — when true this area MUST carry artwork or the product cannot be manufactured (the manufacturer rejects the sync). Always design every required area, even when the product name highlights a different (optional) one — e.g. a "Custom Background" sticker sheet has a required "Stickers" area plus an optional "Background". - salePrice: formatted price string (e.g. "$8.50") - supportsBackendRendering: boolean — whether this specific region can be used with generate-product-design-previews (regions like neck labels or embroidery regions will be false) - placements: list of placements within the region, each an object with id and name (e.g. [{"id": "leftChest", "name": "Left chest"}, {"id": "centerChest", "name": "Center chest"}]). Empty list when no placements. Pass the desired placement id to generate-product-design-previews. - Backend rendering: supportsBackendRendering (boolean) — whether this product supports design preview generation via generate-product-design-previews. When true, check each print area's supportsBackendRendering to determine which regions can be designed. - Colors: list of available color names - Sizes: list of available sizes - Size guide: sizeGuide — formatted string like "Chest: S=34-36, M=38-40 (inches)" - Fabric: fabricWeightGsm (GSM), material (primary), distinctMaterials (all unique materials across variants, e.g. heather vs solid differ) - Weight: weightRange — formatted string like "5.00-6.20 oz" - Origin: countryOfProduction - Description: description, moreDetails, sizeAndFitNotes - Returns: guaranteeAndReturns — guarantee and returns policy text - Legal: legalWarningSubstance — legal/safety warnings (e.g. Prop 65) - Reviews: reviewSummary — formatted string like "4.63/5 (119 reviews) - Creators love the softness..." - Stock issues: colorsWithStockIssues — only colors that have problems, each with the discontinuedSizes and outOfStockSizes for that color. Colors absent from this list are fully available across every size in `sizes`. - Shipping: shipsFrom — regions where the product is fulfilled from (e.g. ["US", "EU", "CA"]) - Badges: badges (e.g. ["OUR_PICK", "BESTSELLER"]) - favourite: boolean
ecommerce_get-catalog-product-details
Browse source products from the product catalog with filtering and pagination. These are products available for customization — NOT the shop's own offers. To view products already added to the shop, use get-offers instead. Returns: - Pagination: pageNumber, pageSize, totalElements, totalPages - Per product: - Identity: id, brand, brandModel, name, slug - Category: categoryPath (list of category names) - Pricing: priceFrom (BigDecimal), priceTo (BigDecimal) - Production: productionMethod, minimumOrdersNumber (nullable Int) - Reviews: reviewsSummary with count and rating (nullable) - Metadata: customizationType (REQUESTABLE/INSTANT/DESIGNER_V3_READY/PRINTFUL_DESIGNER_READY), favourite (boolean), badges (OUR_PICK/BESTSELLER/NEW/SIGNATURE) - Print details (only when includePrintDetails=true): printDetails — { supportsBackendRendering (boolean), printAreas: [{ type, name, required, salePrice, supportsBackendRendering, placements: [{ id, name }] }] }. required=true means the area MUST carry artwork or the product cannot be manufactured. IMPORTANT: To find a specific catalog product by name, brand, or keyword, you MUST use the `search` tool. NEVER paginate through results to find a specific entity.
ecommerce_get-catalog-products
Get details of one or more catalog products by their slugs. Fetches all products concurrently. This returns catalog source products — NOT shop offers. Use get-offers-by-ids for shop product details. IMPORTANT: Only use slugs returned by `get-catalog-products` or `search`. Do NOT construct or guess slugs from product names — they will not match real catalog entries. Returns a list of products, each containing: - Identity: id, brand, brandModel, name, slug - Category: categoryPath (list of category names from breadcrumbs) - Pricing: priceFrom (BigDecimal), priceTo (BigDecimal) - Production: productionMethod (SUBLIMATION/DTG/EMBROIDERY/SCREEN_PRINTING/PRINTED/STICKER/DTFX/UV/ALL_OVER_PRINT/KNITTING/DRINKWARE/GARMENT_PRINTED/ACRYLIC_CUTOUT/DIE_CUT_MAGNET/HOLO_STICKER/OTHER), minimumOrdersNumber (nullable Int) - Metadata: customizationType (REQUESTABLE/INSTANT/DESIGNER_V3_READY/PRINTFUL_DESIGNER_READY), favourite (boolean), badges (OUR_PICK/BESTSELLER/NEW/SIGNATURE) - Note: reviewsSummary is not available for single product lookups
ecommerce_get-catalog-products-by-slugs
Retrieves all non-archived collections for the shop. NOTE: The system-level "All Products" collection (used internally to display all products on the Products page) is excluded from results. Only user-created collections are returned. Returns a list of collections, each with: - Identity: id (CollectionId), shopId (ShopId), name, slug, description - Visibility: available (boolean), state (PUBLIC/HIDDEN/ARCHIVED) - Time-based availability: availableFrom (nullable ISO 8601), availableTo (nullable ISO 8601) - Products: offerIds (list of OfferIds — use get-offers-by-ids to look up each product) - Sorting: sortingStrategy (MANUAL/BEST_SELLING/NEWEST/OLDEST/NAME_ASC/NAME_DESC) IMPORTANT: To find a specific collection by name or keyword, you MUST use the `search` tool. NEVER iterate through results to find a specific entity.
ecommerce_get-collections
Get details of one or more collections by their IDs. Fetches all collections concurrently. Use get-collections to discover collection IDs if you don't have any. Returns a list of collections, each containing: - Identity: id (CollectionId), shopId (ShopId), name, slug, description - Visibility: available (boolean), state (PUBLIC/HIDDEN/ARCHIVED) - Time-based availability: availableFrom (nullable ISO 8601), availableTo (nullable ISO 8601) - Products: offerIds (list of OfferIds — use get-offers-by-ids to look up each product) - Sorting: sortingStrategy (MANUAL/BEST_SELLING/NEWEST/OLDEST/NAME_ASC/NAME_DESC)
ecommerce_get-collections-by-ids
Get the Contributions Per Type analytics report for the shop within a date range: transaction count breakdown by contribution type. This report shows contribution counts over time with the following columns per row: - date: The time period - shop_orders: Number of shop orders - sample_orders: Number of sample orders - orders_twitch_gifts_purchases: Number of Twitch gifts purchases - orders_twitch_gifts_redeems: Number of Twitch gifts redeems - donations: Number of donations - giveaway_links: Number of giveaway links - memberships_subscriptions: Subscriptions = New subscriptions + Renewals + Upgrades - memberships_message_tips: Number of message tips - memberships_locked_messages: Number of locked messages - memberships_paid_posts: Number of paid posts - memberships_subscription_gifts: Number of subscription gifts - memberships_twitch_gifts: Number of Twitch gifts - total: Total contributions across all types Precision: choose finest granularity producing <=31 rows (HOUR for ~1d, DAY for ~1mo, WEEK for ~7mo, MONTH for ~2.5y, QUARTER for ~7y, YEAR beyond). Filter groups (pass comma-separated keys to include only specific metrics): - shop_metrics: shop_orders, sample_orders, orders_twitch_gifts_purchases, orders_twitch_gifts_redeems, donations, giveaway_links - memberships_metrics: memberships_subscriptions, memberships_message_tips, memberships_locked_messages, memberships_paid_posts, memberships_subscription_gifts, memberships_twitch_gifts
ecommerce_get-contributions-per-type-report
Get the Conversion Rates analytics report for the shop within a date range: checkout funnel conversion metrics. This report shows conversion funnel data over time with the following columns per row: - date: The time period - total_sessions: Total number of user sessions adjusted to be at least as large as the number of carts created (baseline for conversion percentages, always 100%) - cart_created_count: Number of shopping carts created by users, including carts from gift and giveaway checkouts - cart_created_percentage: Percentage of sessions that resulted in cart creation - checkout_created_count: Number of initiated checkouts - checkout_created_percentage: Percentage of sessions that resulted in checkout initiation - checkout_paid_count: Number of completed payments - checkout_paid_percentage: Percentage of sessions that resulted in completed payment Precision: HOUR for ranges <=1 day, DAY for longer.
ecommerce_get-conversion-rates-report
Retrieves the current shop's profile, configuration, and contact details. For user-level access permissions, use get-shop-permissions instead. Returns: - Identity: id (String, e.g. "sh_6c8684ef-..."), name, creatorName, description, logoUrl (nullable URL string) - Domains: primaryDomain (e.g. "myshop.fourthwall.com"), internalDomain (e.g. "myshop.fourthwall.com"), customDomains (list), baseUrl (full URL) - Status: status (LIVE/COMING_SOON/PASSWORD_PROTECTED/INACTIVE) - Contact info: - shopEmail, contactEmail, customerSupportEmail (nullable), transactionalEmail - location: name (nullable), address1 (nullable), address2 (nullable), city (nullable), state (nullable), zip (nullable), country (ISO code) - Settings: - currency (primary, e.g. USD), enabledCurrencies (list, e.g. [USD, EUR, GBP, CAD, AUD]) - membershipsEnabled (Boolean), membershipsUpsellingMinOrderValue (nullable BigDecimal), membershipsUpsellingMinOrderCurrency (nullable, e.g. "USD") - allowedPaymentProviders: list of Stripe, StripeDeferred, PayPal, Klarna, Afterpay, CKO - thankYouCardEnabled (Boolean), externalStoreUrl (nullable URL string) - socialLinks: map of platform key to URL/handle (only non-null entries). Possible keys: youtube, instagram, facebook, twitter, x, tiktok, snapchat, discord, twitch, spotify, reddit, kick, kofi, patreon, threads, pinterest, soundcloud, bluesky, linkedin - verificationRestrictions: list of feature names that require verification (empty list if none) - Timestamps: timezone (e.g. "America/New_York"), createdAt (ISO 8601), lastLiveAt (nullable ISO 8601)
ecommerce_get-current-shop
Retrieves the current subscription for the shop with usage information. For full plan details (pricing, all limits, features), use get-available-plans. Returns: - Subscription: id, status, activeFrom (nullable ISO 8601), activeTo (nullable ISO 8601), scheduledCancelledAtTheEndOfPeriod (boolean) - Plan summary: plan.id, plan.name, plan.pro (boolean), plan.custom (boolean) - Usage vs limits (each with limit and usage as Long): - offers: product/offer count - members: team member count - domains: custom domain count - digitalProductsStorageBytes: digital file storage in bytes - pendingSubscription (nullable): subscriptionId, planId, planName — present when a plan change is scheduled status values: - PENDING: awaiting payment/activation - ACTIVE: subscription is active and in good standing - PAST_DUE: payment is overdue - CANCELED: subscription has been cancelled Understanding limits: - When usage >= limit, the resource is at capacity - limit = -1 means unlimited for that resource - Storage is in bytes (divide by 1073741824 for GB)
ecommerce_get-current-subscription
Get the Customers Over Time analytics report for the shop within a date range: customer acquisition and retention metrics. This report shows customer counts over time with the following columns per row: - date: The time period - customers_first_time: Number of customers making their first purchase in this period - customers_returning: Number of customers who have made purchases before this period - customers_total: Total unique customers (first-time + returning) Precision: choose finest granularity producing <=31 rows (HOUR for ~1d, DAY for ~1mo, WEEK for ~7mo, MONTH for ~2.5y, QUARTER for ~7y, YEAR beyond).
ecommerce_get-customers-over-time-report
Gets pricing preview for a customization sketch without creating an offer. Returns manufacturing costs per size with cost component breakdown (blank, print regions, etc.). Use this to show the user what the offer would cost before creating it.
ecommerce_get-customization-pricing
Retrieves the current status of a design pipeline. Returns: - pipelineId, status (PENDING, DONE, or ERROR), type - customizationId?: set when a customization exists - offerId?: present when type=OFFER and status=DONE - images[]: { url, width, height, style, color, size?, region? } - priceSuggestions?: { currency, singlePrice, perSize[]: { size, price, cost } } - error?: { step, message } Use this tool to: - Check if a design pipeline has completed - Get generated preview images or the offer ID after completion - Diagnose failures via error.step and error.message
ecommerce_get-design-pipeline-status
Retrieves the DNS configuration and records for the shop's custom domain. This is a read-only check — it does NOT re-validate records against live DNS. To trigger a fresh validation, use validate-dns-entries instead. Returns null if no custom domain is configured, otherwise returns: - Domain: domainId, domain (e.g. "myshop.com") - Status: status (CONNECTED, NOT_CONNECTED, PARTIALLY_CONNECTED, SYNCING_YOUR_DOMAIN, REMOVAL_IN_PROGRESS) - Flags: areAllEntriesComplete (boolean), isSslSynced (boolean), retryAllowed (boolean) - Provider: dnsProvider (nullable String, e.g. "Cloudflare", "GoDaddy"), dnsProviderMode (MANUAL/AUTOMATIC, nullable) - Nameservers: nameservers (list of hostname strings) - Per record in records: - recordType (CNAME, TXT, MX, A) - host (nullable, e.g. "www", "@") - value (nullable, the expected DNS value) - status (VALID, INVALID, UNKNOWN) - validationError (nullable String — e.g. "RECORD_NOT_FOUND", "INCORRECT_TYPE_OR_VALUE (found: ...)", "DUPLICATED_BASE_DOMAIN (...)") - alias (identifies the record purpose, e.g. SHOP_IP_ADDRESS, SHOP_WWW_REDIRECT, SENDGRID_MAIL_CNAME, DMARC, SPF_RULE) - priority (nullable Int, for MX records) status values: - CONNECTED: All DNS records verified and SSL active - PARTIALLY_CONNECTED: Website records verified but other records (email, etc.) still pending - NOT_CONNECTED: Website DNS records not yet verified - SYNCING_YOUR_DOMAIN: Website records verified, waiting for SSL certificate provisioning - REMOVAL_IN_PROGRESS: Domain is being disconnected Use this tool to: - Check if a custom domain is set up for the shop - See the current domain connection status and SSL state - List DNS records that need to be configured at the domain registrar - Identify which specific records are failing (check record status + validationError) - Identify the DNS provider being used
ecommerce_get-dns-entries
Returns the current and available colors and sizes for a draft customization. - selectedColors / selectedSizes: what the draft currently has selected. - availableColors / availableSizes: every legal value for this product blank — the only values that add-draft-colors / add-draft-sizes will accept. Call this before add-draft-colors or add-draft-sizes to learn what's legal. Color and size names are case-sensitive — pass them exactly as they appear in availableColors / availableSizes.
ecommerce_get-draft-attributes
How do I improve a ChatGPT Plugin's discoverability?
The levers are the listing surface agents actually read: names, descriptions, keywords, tool metadata, and registry health. Which lever matters depends on where discovery breaks, which is what continuous measurement shows.
What are Fourthwall alternatives on ChatGPT?
As of 2026-08-14, Fourthwall competes with Bonfire, Photo9, Pixum, Print Beam, PrintA, Printify, PrintTiler, Send Postcard, Skylit Studio Custom Gifts, Stars In Hands Gift Studio in ChatGPT Custom Print & Personalized Keepsakes, ranked by public Discoverability Score.
Where is this profile measured?
This profile uses the geography attached to the latest public registry snapshot: US. Locale tags are intentionally omitted.