Let’s explore how to leverage Composable Commerce Shopping Lists, particularly Custom Fields, to build advanced functionality like public sharing (for wishlists or gift registries), manage list lifecycles, and implement related features.
While Composable Commerce provides flexible base Shopping List functionality, features like publicly sharing a list or building a full gift registry require custom implementation. We'll focus on the core mechanisms using Custom Fields.
Foundation: Understanding Custom Fields and Types
Before extending Shopping Lists, it's essential to understand Custom Fields and Types in Composable Commerce.
- Custom Fields: Allow you to add your project-specific data to standard Composable Commerce resources.
- Types: Define the structure (schema) of your Custom Fields. A Type specifies the field names, data types (String, Boolean, or Set), labels, and the resources it applies to.
- Resource Association (
resourceTypeIds): When creating a Type, theresourceTypeIdsproperty determines which Composable Commerce resources can use the custom fields defined in that Type. To add custom fields directly to a Shopping List, the Type must include"shopping-list"in itsresourceTypeIds. Similarly,"line-item"or"text-line-item"can be used for fields on items within the list.
resourceTypeIds, and the definitions of the fields you want to add (like the isPublic field discussed next). This is typically done via the Composable Commerce API or SDKs.Implementing public sharing for Shopping Lists
To allow users to share their Shopping Lists via a public URL (like a wishlist or gift registry), you need two main components: a public identifier and an access control mechanism.
Access control: The isPublic Custom Field
- Mechanism: Define a Boolean Custom Field (for example, named
isPublic) on theshopping-listresource type using a Custom Type (as described in Section 1). - Purpose: This field acts as a flag. Only lists where this flag is explicitly set to
trueshould be considered publicly accessible via the shareable URL. - Default State: If the
isPublicfield is absent orfalse, the list remains private (accessible only to the owner). This secure default prevents accidental exposure.
Custom Field definition draft example (Type definition):
isPublic field.// Type Draft Snippet for shopping-list-settings Type
{
"key": "shopping-list-settings", // Choose a meaningful key
"name": { "en": "Shopping List Settings" },
"description": { "en": "Custom settings including visibility." },
"resourceTypeIds": ["shopping-list"], // Applies to Shopping Lists
"fieldDefinitions": [
{
"name": "isPublic", // The custom field name
"label": { "en": "Is Publicly Shareable" },
"type": { "name": "Boolean" }, // Data type is Boolean
"required": false, // Not required; absence means private
"inputHint": "SingleLine"
}
// Add other settings fields here later if needed
]
}
Setting the isPublic field value
isPublic field value (to true or false). This is done using the setCustomField update action via the API, providing the list ID, its current version, the field name (isPublic), and the desired boolean value.Backend logic: Fetching and displaying the public list
GET /shared-list/{slug}).- Approach A: Fetch by Identifier, then Verify
isPublic- Query: Fetch the Shopping List using only its
slugorkey. - Verify (in your code): Check if the list was found and if its
custom.fields.isPublicistrue. Handle404 Not Foundand403 Forbidden(or404for private lists) appropriately. - Pros: Clear distinction between non-existent and private lists.
- Cons: Requires backend logic post-API call.
- Query: Fetch the Shopping List using only its
- Approach B: Query by Identifier AND
isPublicStatus- Query: Fetch using both identifier and
isPublic = truein the API query predicate. - Verify: If the API returns a list, display it. If not, return
404 Not Found. - Pros: Simpler API interaction; platform does filtering.
- Cons: Backend cannot distinguish why no list was returned (wrong slug versus private list).
- Query: Fetch using both identifier and
- Query Optimization: When combining filters in API query predicates, place highly selective identifiers (
slug,key,id) before less selective ones (custom(fields(isPublic = true))) for better performance.
Frontend implementation
- Create a dedicated route, such as
/shared-list/:slug, in your frontend application. - This page calls your backend endpoint (which uses one of the logic approaches above) to fetch and display the list data.
Expanding sharing: Specific users
Beyond simple public sharing, you can share lists with specific individuals.
- Mechanism: Use a Custom Field of type
SetofString(for example, namedsharedWith) on the Shopping List Type. Store user identifiers (for example, customer IDs, emails) in this set. - Implementation Steps:
- Define the
sharedWithfield in your Custom Type. - Use the
setCustomFieldAPI action to add or remove user identifiers from this set on a specific list. - Your application logic must check if the currently logged-in user's identifier is present in the
sharedWithcustom field before granting access.
- Define the
- Considerations: Ensure robust security, clear UI for managing shares, consistent identifier choice, and handle optimistic concurrency (using the list
version) during updates.
Advanced Custom Field Applications
Custom Fields unlock many possibilities beyond basic sharing, including:
- List Metadata: Store extra info directly on the list:
listType("Wishlist", "Grocery"),occasion("Birthday", "Wedding"),eventDate,eventLocation,shippingAddress(for registries). - Partial Purchase Tracking: In shared lists (like registries), track who bought what to prevent duplicates. Add a Custom Field (such as
purchasedByas aSetofString) to the Line Item Type (resourceTypeIds: ["line-item"]). Your application would update this field when an item is purchased from the shared list. - Localization: Use
LocalizedStringtypes for custom fields needing language-specific values. - Text Line Item Notes: Add metadata (for example,
priority) to text-based items using a Type associated withtext-line-item.
setLineItemCustomField or setTextLineItemCustomField.)List lifecycle management
deleteDaysAfterLastModification field.- Mechanism: Set this field on the Shopping List via the
setDeleteDaysAfterLastModificationAPI update action. Provide the number of days of inactivity before deletion. Setting it tonullor omitting it disables auto-deletion.