Category assignment

What we are trying to do is utilize Gemini to do a one click process of entering product information into Wix. Click and it takes a pic which is used to search for a description of the product, load it into the Wix data entry page, and pause for us to verify. We can get the product description and proposed price (we are a reuse store), but it won’t load the picture (which is stored at Cloudinary) and it won’t check the category box. It’s still faster than it was but not where we want it. The following questions wre generated by “Maestro” (I change the name to Bob) in the Symphony AI app.

1. Category/Collection assignmentcollections.addProductsToCollection(collectionId, [productId]) always throws: TypeError: Cannot read properties of undefined (reading 'length')

The collection IS found correctly (confirmed by querying with queryCollections). I’ve tried:

  • addProductsToCollection(collectionId, [productId])
  • addProductsToCollection(collectionId, { productIds: [productId] })
  • addProductsToCollection({ collectionId, productIds: [productId] })
  • Passing collections: [{ _id: collectionId }] directly into createProduct
  • wixData.insert('Stores/CollectionProducts', ...)

None work.

2. Image from external URL Passing media: { mainMedia: { image: { url: externalUrl } } } either in createProduct or updateProduct returns Bad Request.

The external URL is a valid public Cloudinary HTTPS URL that loads fine in a browser.

What is the correct way to do both of these in a backend .jsw file using wix-stores.v2?

You’re hitting two separate API issues:

Issue 1: Category Assignment

The error "Cannot read properties of undefined (reading 'length')" happens because addProductsToCollection expects two separate parameters, not an object. The correct syntax is:

import { products } from '@wix/stores';

await products.addProductsToCollection(collectionId, [productId]);

You were passing { productIds: [productId] } as a single object, but the method signature is addProductsToCollection(collectionId, productIds) where productIds is a flat array.

Issue 2: External Images

External image URLs cannot go in createProduct or updateProduct — the media parameter there is read-only. For external URLs like Cloudinary, you must use addProductMedia after creating the product:

// Create the product first
const { product } = await products.createProduct({
  name: "Your Product Name",
  description: "Your description",
  priceData: { price: 29.99 }
  // Do NOT include media here
});

// Then add the external image URL
await products.addProductMedia(product._id, [
  { url: "https://res.cloudinary.com/your-account/image/upload/your-image.jpg" }
]);

Complete Working Flow

Here’s your one-click product entry combining both fixes:

import { products } from '@wix/stores';

export async function addProductFromGemini(productData) {
  const { name, description, price, imageUrl, collectionId } = productData;
  
  // Step 1: Create the product
  const { product } = await products.createProduct({
    name,
    description,
    priceData: { price }
  });
  
  // Step 2: Add external image
  if (imageUrl) {
    await products.addProductMedia(product._id, [{ url: imageUrl }]);
  }
  
  // Step 3: Assign to collection/category
  if (collectionId) {
    await products.addProductsToCollection(collectionId, [product._id]);
  }
  
  return product;
}

Both methods are from the Catalog V1 API (@wix/stores). The V2 collections module doesn’t have the same addProductsToCollection method, which is why your V2 attempts failed.

Thank you! We actually figured that out eventually. It’s all working now. Phil