{post?.title}
{post?.amazonProduct && (
layout="horizontal"
imageSize="large"
/>
)}
Sanity Studio plugin to fetch and embed Amazon products by ASIN (PA-API v5), with settings tool and document actions.
npm install @multidots/sanity-plugin-amazon-product-syncA comprehensive Sanity Studio plugin for fetching and managing Amazon products using the Amazon Product Advertising API (PA-API v5). This plugin provides seamless integration between Sanity Studio and Amazon's product data with real-time fetching capabilities.
- Amazon Settings Management: Configure PA-API credentials with a dedicated settings singleton
- Real-time Form Validation: Instant feedback and button state updates using useFormValue
- Product Document Management: Create multiple Amazon product documents with auto-fetching
- Fetch from Amazon Button: Dedicated button component for product data retrieval
- Multi-region Support: US, UK, DE, FR, IT, ES, CA, AU, JP, IN marketplaces
- Streamlined Product Data: Essential fields including title, brand, pricing, images, and more
- TypeScript Support: Full type safety throughout the plugin
- Modern Sanity v4: Built for the latest Sanity Studio architecture
- Secure Configuration: Environment variable-based API endpoint configuration
Amazon Product Sync plugin overview in Sanity Studio
API Settings: https://share.cleanshot.com/sYc88tRMBvHPvsjvt9YT
Product Fields Display Settings: https://share.cleanshot.com/Nrtl8RpdhgJrSr7Lj0j6
Test Connection and Debug Actions: https://share.cleanshot.com/Nrtl8RpdhgJrSr7Lj0j6
``bash`
npm install @multidots/sanity-plugin-amazon-product-sync
`typescript
// sanity.config.ts
import { defineConfig } from 'sanity'
import { structureTool } from 'sanity/structure'
import { visionTool } from '@sanity/vision'
import { amazonProductsPlugin } from '@multidots/sanity-plugin-amazon-product-sync'
import { structure } from './structure'
export default defineConfig({
name: 'default',
title: 'Your Studio',
projectId: 'your-project-id',
dataset: 'production',
plugins: [
structureTool({ structure }),
visionTool(),
amazonProductsPlugin(),
],
schema: {
types: [
// Your existing schemas
],
},
})
`
Create structure.ts in your project root:
`typescript
// structure.ts
import type { StructureResolver } from 'sanity/structure'
export const structure: StructureResolver = (S) =>
S.list()
.title('Content')
.items([
...S.documentTypeListItems().filter(
(item) => item.getId() &&
!['amazon.settings'].includes(item.getId()!)
),
S.divider(),
S.listItem()
.id('amazonSettings')
.title('Amazon Settings')
.child(
S.document()
.schemaType('amazon.settings')
.documentId('amazon-settings')
),
])
`
`typescript`
// sanity.config.ts (add these document rules)
export default defineConfig({
// ... other config
document: {
// Hide singleton types from the global "New document" menu
newDocumentOptions: (prev: any, { creationContext }: any) => {
if (creationContext.type === 'global') {
return prev.filter(
(templateItem: any) =>
!['amazon.settings'].includes(templateItem.templateId)
)
}
return prev
},
// Prevent duplicate/delete on singleton documents
actions: (prev: any, { schemaType }: any) => {
if (['amazon.settings'].includes(schemaType)) {
return prev.filter(({ action }: any) => action !== 'duplicate' && action !== 'delete')
}
return prev
},
},
// ... rest of config
})
The plugin requires server-side API routes to handle Amazon PA-API calls due to CORS restrictions and security requirements.
CRITICAL: You must set up these environment variables in your Sanity Studio root .env.local file:
`bash`.env.local (in Sanity Studio root)
SANITY_STUDIO_AMAZON_API_URL=http://localhost:3001
SANITY_STUDIO_AMAZON_TEST_CONNECTION_PATH=/api/amazon/test-connection
SANITY_STUDIO_AMAZON_FETCH_PRODUCT_PATH=/api/amazon/fetch-product
Important Notes:
- These environment variables are MANDATORY - the plugin will throw errors if they're missing
- The API server URL should point to your Next.js/Express server that handles Amazon API calls
- The paths should match your server-side API route endpoints
- Environment variables must be prefixed with SANITY_STUDIO_ to be accessible in Sanity Studio
- NEW: The plugin now validates environment variables at startup and provides clear error messages
The plugin now includes a centralized configuration system (src/lib/config.ts) that:
- Validates environment variables at startup
- Provides clear error messages for missing or invalid configurations
- Ensures secure endpoint configuration without hardcoded URLs
- Supports flexible API server setups for different environments
You need to implement these endpoints in your frontend:
- POST /api/amazon/test-connection - Test PA-API credentialsPOST /api/amazon/fetch-product
- - Fetch product data by ASIN
#### 1. Install Dependencies
`bash`
npm install @sanity/client
#### 2. Environment Variables
Create .env.local:
`envSanity Configuration
NEXT_PUBLIC_SANITY_PROJECT_ID=your-project-id
NEXT_PUBLIC_SANITY_DATASET=production
SANITY_API_TOKEN=your-sanity-api-token
#### 3. Create Sanity Client
`typescript
// lib/sanity.ts
import { createClient } from '@sanity/client'export const client = createClient({
projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID!,
dataset: process.env.NEXT_PUBLIC_SANITY_DATASET || 'production',
apiVersion: '2025-01-01',
useCdn: false,
token: process.env.SANITY_API_TOKEN,
})
export async function getAmazonSettings() {
const query =
*[_type == "amazon.settings"][0]{
return await client.fetch(query)
}
`📎 Referencing Amazon Products in Your Schemas
You can easily reference Amazon products in your own document schemas using a simple field definition. This allows you to associate Amazon products with blog posts, reviews, comparisons, or any other content type.
$3
`typescript
// Copy this field into any schema where you want to reference Amazon products
defineField({
name: 'amazonProduct',
title: 'Choose Product',
type: 'reference',
to: [{ type: 'amazon.product' }],
options: {
filter: ({ document }) => ({
filter: '_type == "amazon.product"',
params: {}
})
},
description: 'Select an Amazon product',
})
`$3
Single Product (Required):
`typescript
defineField({
name: 'amazonProduct',
title: 'Choose Product',
type: 'reference',
to: [{ type: 'amazon.product' }],
validation: Rule => Rule.required(),
})
`Single Product (Optional):
`typescript
defineField({
name: 'amazonProduct',
title: 'Choose Product',
type: 'reference',
to: [{ type: 'amazon.product' }],
})
`Multiple Products (Array):
`typescript
defineField({
name: 'amazonProducts',
title: 'Choose Products',
type: 'array',
of: [
{
type: 'reference',
to: [{ type: 'amazon.product' }],
}
],
validation: Rule => Rule.min(1).max(10),
})
`$3
Blog Post with Amazon Product:
`typescript
export const blogPostSchema = defineType({
name: 'post',
title: 'Blog Post',
type: 'document',
fields: [
defineField({
name: 'title',
title: 'Title',
type: 'string',
validation: Rule => Rule.required(),
}),
// Amazon Product Reference
defineField({
name: 'amazonProduct',
title: 'Choose Product',
type: 'reference',
to: [{ type: 'amazon.product' }],
description: 'Select an Amazon product to feature in this blog post',
}),
// ... other fields
],
})
`Product Review Schema:
`typescript
export const productReviewSchema = defineType({
name: 'review',
title: 'Product Review',
type: 'document',
fields: [
defineField({
name: 'title',
title: 'Review Title',
type: 'string',
validation: Rule => Rule.required(),
}),
// Amazon Product Reference (Required)
defineField({
name: 'amazonProduct',
title: 'Choose Product',
type: 'reference',
to: [{ type: 'amazon.product' }],
validation: Rule => Rule.required(),
description: 'Select the Amazon product being reviewed',
}),
defineField({
name: 'rating',
title: 'Rating',
type: 'number',
options: { range: { min: 1, max: 5, step: 0.5 } },
}),
// ... other fields
],
})
`Product Comparison Schema:
`typescript
export const comparisonSchema = defineType({
name: 'comparison',
title: 'Product Comparison',
type: 'document',
fields: [
defineField({
name: 'title',
title: 'Comparison Title',
type: 'string',
validation: Rule => Rule.required(),
}),
// Multiple Amazon Products
defineField({
name: 'amazonProducts',
title: 'Choose Products',
type: 'array',
of: [
{
type: 'reference',
to: [{ type: 'amazon.product' }],
}
],
validation: Rule => Rule.required().min(2).max(5),
description: 'Select 2-5 Amazon products to compare',
}),
// ... other fields
],
})
`$3
Once you have Amazon product references in your schemas, you can query them using GROQ. Here are comprehensive examples:
#### Basic Single Product Reference
`typescript
// Get blog post with Amazon product reference
const query = *[_type == "post" && defined(amazonProduct)][0]{const post = await sanityClient.fetch(query)
console.log(post.amazonProduct.title) // Amazon product title
console.log(post.amazonProduct.price) // Amazon product price
`#### Direct Product Queries
Get product by ASIN:
`typescript
const query = *[_type == "amazon.product" && asin == $asin][0]{const product = await sanityClient.fetch(query, { asin: "B09XFQL45V" })
`Get product by Reference ID:
`typescript
const query = *[_type == "amazon.product" && _id == $referenceId][0]{const product = await sanityClient.fetch(query, { referenceId: "3f995870-12ea-4d02-b242-ce78abfbf56e" })
`Unified query (either ASIN or Reference ID):
`typescript
const query = *[_type == "amazon.product" && (// Use with ASIN
const productByAsin = await sanityClient.fetch(query, { asin: "B09XFQL45V", referenceId: null })
// Use with Reference ID
const productByRef = await sanityClient.fetch(query, { asin: null, referenceId: "3f995870-12ea-4d02-b242-ce78abfbf56e" })
`#### Multiple Products Array
`typescript
// Get comparison with multiple Amazon products
const query = *[_type == "comparison"][0]{const comparison = await sanityClient.fetch(query)
comparison.amazonProducts.forEach(product => {
console.log(
${product.title}: ${product.price})
})
`#### Filtered Queries
`typescript
// Find posts featuring specific Amazon product
const postsByProduct = *[_type == "post" && amazonProduct->asin == $asin]{const posts = await sanityClient.fetch(postsByProduct, { asin: 'B0F15TM77B' })
// Find posts with products from specific brand
const postsByBrand =
[_type == "post" && amazonProduct->brand match $brand + ""]{const applePosts = await sanityClient.fetch(postsByBrand, { brand: 'Apple' })
`#### Product Reviews with Ratings
`typescript
// Get product reviews with ratings
const reviewsQuery = *[_type == "review" && defined(amazonProduct)] | order(rating desc){const reviews = await sanityClient.fetch(reviewsQuery)
// Get average rating for specific product
const ratingQuery =
{const productStats = await sanityClient.fetch(ratingQuery, { asin: 'B0F15TM77B' })
`#### Advanced Analysis Queries
`typescript
// Get comparison with price analysis
const analysisQuery = *[_type == "comparison"][0]{const analysis = await sanityClient.fetch(analysisQuery)
console.log(
Price range: ${analysis.lowestPrice} - ${analysis.highestPrice})
`#### TypeScript Interfaces
`typescript
interface PostWithProduct {
_id: string
title: string
slug: string
amazonProduct: {
asin: string
title: string
brand: string
price: string
currency: string
url: string
images: Array<{ url: string; width: number; height: number }>
features: string[]
}
}// Use with type safety
const post: PostWithProduct = await sanityClient.fetch(query)
`For more GROQ query examples, check the
examples/groqQueries.ts file in the plugin.🎨 React Component for Frontend Display
The plugin includes a flexible React component for displaying Amazon products in your frontend applications.
$3
`tsx
import AmazonProductDisplay from './AmazonProductDisplay'
import { createClient } from '@sanity/client'const client = createClient({
projectId: 'your-project-id',
dataset: 'production',
apiVersion: '2025-01-01',
useCdn: true,
})
// Option 1: Display product from reference field
function BlogPost({ post }) {
return (
{post.title}
{post.amazonProduct && (
product={post.amazonProduct}
layout="card"
imageSize="medium"
/>
)}
)
}// Option 2: Display product by ASIN lookup
function ProductPage({ asin }) {
return (
asin={asin}
client={client}
layout="horizontal"
imageSize="large"
onProductClick={(product) => {
console.log('Product clicked:', product.title)
}}
/>
)
}
`$3
`tsx
interface AmazonProductDisplayProps {
// Data source (choose one)
product?: AmazonProduct // Direct product data
asin?: string // ASIN for lookup
referenceId?: string // Reference ID for lookup
client?: SanityClient // Required when using asin or referenceId
// Display options
showFeatures?: boolean // Show feature list (default: true)
showImages?: boolean // Show product image (default: true)
showPrice?: boolean // Show pricing (default: true)
showBrand?: boolean // Show brand name (default: true)
showCTA?: boolean // Show "View on Amazon" button (default: true)
// Styling options
layout?: 'horizontal' | 'vertical' | 'card' // Layout style (default: 'card')
imageSize?: 'small' | 'medium' | 'large' // Image size (default: 'medium')
className?: string // Custom CSS classes
ctaText?: string // Custom CTA button text (default: 'View on Amazon')
// Development options
debug?: boolean // Enable debug mode (default: false)
// Interaction
onProductClick?: (product: AmazonProduct) => void // Click handler
}
`$3
$3
The component supports 3 different ways to display products:
1. By ASIN Lookup:
`tsx
import { AmazonProductByASIN } from '@/components/AmazonProductDisplay'
import { sanityClient } from '@/lib/sanity-client' asin="B09XFQL45V"
client={sanityClient}
layout="card"
debug={true}
/>
`2. By Reference ID Lookup:
`tsx
import { AmazonProductByReferenceId } from '@/components/AmazonProductDisplay'
import { sanityClient } from '@/lib/sanity-client' referenceId="3f995870-12ea-4d02-b242-ce78abfbf56e"
client={sanityClient}
layout="card"
debug={true}
/>
`3. Unified Component (accepts any parameter):
`tsx
import AmazonProductDisplay from '@/components/AmazonProductDisplay'
import { sanityClient } from '@/lib/sanity-client'// Option A: ASIN lookup
// Option B: Reference ID lookup
// Option C: Direct product data
`$3
All lookup methods use one optimized GROQ query:
`groq
*[_type == "amazon.product" && (
($asin != null && asin == $asin) ||
($referenceId != null && _id == $referenceId)
)][0]{
_id, asin, title, brand, price, currency, url, images, features, lastSyncedAt
}
`4. Blog Post with Featured Product:
`tsx
function BlogPostWithProduct({ slug }) {
const [post, setPost] = useState(null)
useEffect(() => {
const query = *[_type == "post" && slug.current == $slug][0]{
client.fetch(query, { slug }).then(setPost)
}, [slug]) return (
{post?.title}
{post?.amazonProduct && (
product={post.amazonProduct}
layout="horizontal"
imageSize="large"
/>
)}
)
}
`Product Comparison Grid:
`tsx
function ProductComparison({ comparisonId }) {
const [comparison, setComparison] = useState(null)
useEffect(() => {
const query = *[_type == "comparison" && _id == $comparisonId][0]{
client.fetch(query, { comparisonId }).then(setComparison)
}, [comparisonId]) return (
{comparison?.title}
{comparison?.amazonProducts.map((product) => (
key={product.asin}
product={product}
layout="card"
showFeatures={false}
/>
))}
)
}
`Direct ASIN Lookup:
`tsx
function ProductWidget({ asin }) {
return (
Recommended Product
asin={asin}
client={client}
layout="horizontal"
imageSize="small"
showFeatures={false}
/>
)
}
`Product Review with Rating:
`tsx
function ProductReview({ reviewId }) {
const [review, setReview] = useState(null)
useEffect(() => {
const query = *[_type == "review" && _id == $reviewId][0]{
client.fetch(query, { reviewId }).then(setReview)
}, [reviewId]) return (
product={review?.amazonProduct}
layout="card"
ctaText="Buy Now"
/>
{review?.title}
Rating: {review?.rating}/5
{/ Review content /}
)
}
`$3
The component includes default Tailwind CSS classes and can be customized with:
1. CSS Import:
`tsx
import './AmazonProductDisplay.css'
`2. Custom Classes:
`tsx
className="my-custom-product-card shadow-lg"
// ... other props
/>
`3. Layout Variants:
-
card - Card layout with border and shadow
- horizontal - Side-by-side image and content
- vertical - Stacked image above content🚀 Quick Start: Frontend Integration
$3
For immediate setup, copy the complete working example:
`bash
1. Copy the complete Next.js example files
cp examples/complete-nextjs-example/page.tsx src/app/page.tsx
cp examples/components/AmazonProductDisplay.tsx src/components/
cp examples/frontend-integration/sanity-client-setup.ts src/lib/sanity-client.ts2. Install required dependencies
npm install @sanity/client @sanity/image-url3. Configure environment variables
cp examples/complete-nextjs-example/env-template.txt .env.local
Edit .env.local with your actual Sanity project details
4. Start development server
npm run dev
`$3
1. Visit
http://localhost:3000 (or your configured port)
2. You should see:
- ✅ "Product by ASIN Lookup" section
- ✅ "Product by Reference ID Lookup" section
- ✅ Debug panels showing component state
- ✅ Manual fetch buttons for testing$3
Complete Working Examples:
-
examples/complete-nextjs-example/ - 🚀 Full Next.js integration
- page.tsx - Complete page demonstrating ASIN & Reference ID lookups
- package.json - All required dependencies
- env-template.txt - Environment variables template
- SETUP_GUIDE.md - 📖 Detailed step-by-step setup guideIndividual Components:
-
examples/components/AmazonProductDisplay.tsx - Main component with dual parameter support
- examples/components/AmazonProductDisplay.css - Optional styling
- examples/frontend-integration/sanity-client-setup.ts - Production-ready Sanity clientSchema Integration:
-
examples/productReferenceField.ts - Reusable reference field snippets
- examples/exampleSchema.ts - Blog post & comparison schema examples
- examples/groqQueries.ts - Comprehensive GROQ query examplesAPI Integration (Optional):
-
examples/frontend-integration/amazon-client.ts - Amazon PA-API client
- examples/frontend-integration/nextjs-api-route.ts - API route examples
- examples/frontend-integration/fetch-product-api-route.ts - Product fetch APITroubleshooting:
-
examples/environment-setup.md - Environment setup & common issues
- Built-in debug mode in components🎯 Usage
$3
1. Open your Sanity Studio
2. Go to "Amazon Settings" from the sidebar
3. Fill in your Amazon PA-API credentials:
- Region: Select your marketplace (US, UK, DE, etc.)
- Access Key: Your PA-API access key
- Secret Key: Your PA-API secret key
- Partner Tag: Your Amazon Associate tag
- Test ASIN: An ASIN for testing (e.g.,
B0F15TM77B)
- Cache Hours: Duration to cache results (1-168 hours)4. Click "Test API Connection" to verify your setup
$3
1. Go to "Amazon Products" from the sidebar
2. Click "Add new" to create a product document
3. Enter an ASIN number in the ASIN field
4. Navigate to the "Actions" tab
5. Click "Fetch from Amazon" button
6. The document will be auto-populated with:
- Product title (with auto-generated slug)
- Brand name
- Pricing information
- Primary product image
- Product description
- Product type and status
- Amazon permalink
- Last sync timestamp
7. Review and edit the data as needed
8. Click "Publish" when ready
NEW: Product titles now automatically generate URL-friendly slugs!
https://share.cleanshot.com/n2tnCdSDwsW11cwYH7dq
Creating a new Amazon product document
$3
You can also manually enter product information without fetching from Amazon. All fields are editable.
📋 Schema Reference
$3
API Settings:
-
region - Amazon marketplace region
- accessKey - PA-API access key
- secretKey - PA-API secret key
- partnerTag - Amazon Associate tag
- asinNumber - Test ASIN for API validation
- cacheHours - Cache duration (1-168 hours)Display Settings:
-
showTitle - Show/hide product title
- showImage - Show/hide product image
- showFeatures - Show/hide feature list
- showPrice - Show/hide pricing
- showCtaLink - Show/hide CTA linkActions:
- "Test API Connection" - Verify credentials with real-time form validation
- "Debug Document" - View document state and form values
NEW: Real-time form validation using
useFormValue - buttons enable/disable instantly as you type!
https://share.cleanshot.com/P2LbmkdNCJcwJFf14CHC
Amazon Settings actions panel with Test API Connection button
$3
Product Information:
-
asin - Amazon Standard Identification Number
- title - Product title
- slug - Auto-generated URL-friendly slug from title
- brand - Brand/manufacturer name
- permalink - Direct Amazon product URL
- shortDescription - Product description (HTML stripped)
- type - Product type: 'simple', 'variable', 'grouped', 'external'
- featured - Featured product status
- sku - Stock keeping unitPricing:
-
regularPrice - Regular price
- salePrice - Sale price (if on sale)
- price - Current selling priceMedia & Ratings:
-
primaryImage - Primary product image URL
- averageRating - Average customer rating (0-5)
- ratingCount - Number of customer ratings
- stockStatus - Stock status: 'instock', 'outofstock', 'onbackorder'Metadata:
-
lastSyncedAt - Timestamp of last Amazon syncActions:
- "Fetch from Amazon" - Auto-populate from Amazon API
🆕 Recent Improvements (Latest Update)
$3
- Real-time Form Validation: Settings now use
useFormValue for instant feedback and button state updates
- Streamlined Schema: Simplified product schema with essential fields only
- Component Consolidation: Removed redundant components for cleaner architecture
- Secure Configuration: Environment variable-based API endpoint configuration
- Auto-slug Generation: Automatic slug generation from product titles$3
1. AmazonSettingsActions.tsx:
- Replaced complex state management with real-time form values
- Uses
useFormValue hooks for immediate validation
- Buttons enable/disable in real-time as you type2. Schema Simplification:
- Removed complex fields like
description (Portable Text)
- Added essential fields like slug, type, featured, stockStatus
- Streamlined pricing fields for better usability3. Component Cleanup:
- Removed
AmazonAsinInput.tsx (redundant functionality)
- Removed AmazonProductFetch.tsx (unused component)
- Kept AmazonFetchButton.tsx as the primary fetch component4. Configuration System:
- Added
src/lib/config.ts for centralized environment variable handling
- Replaced hardcoded URLs with configurable endpoints
- Added validation for required environment variables🏗️ Component Architecture
$3
The plugin now uses a streamlined component architecture:
1. AmazonSettingsActions.tsx - Settings actions with real-time validation
2. AmazonFetchButton.tsx - Primary fetch component for product documents
3. Configuration System - Centralized environment variable handling
$3
The following components were removed for cleaner architecture:
- ❌ AmazonAsinInput.tsx - Redundant functionality
- ❌ AmazonProductFetch.tsx - Unused component
$3
- AmazonSettingsActions: Handles API testing and debugging with real-time form values
- AmazonFetchButton: Fetches product data and updates documents
- Config System: Manages environment variables and API endpoints
🛠️ Development
$3
`bash
cd plugins/@multidots/sanity-plugin-amazon-product-sync
npm install
npm run build
`$3
`bash
cd your-frontend-app
npm install
npm run dev
`$3
`bash
cd your-sanity-project
npm run dev
`🔧 Troubleshooting
$3
#### Frontend Component Issues
1. "No product available" despite correct ASIN
- Problem: Component shows debug info but never fetches data
- Solution: Enable debug mode and check browser console
`tsx
asin="B09XFQL45V"
client={sanityClient}
debug={true} // Shows debug panel with manual fetch button
/>
`
- Click the "🔄 Manual Fetch" button to test the Sanity client directly2. Environment variables not working
- Problem:
process.env.NEXT_PUBLIC_SANITY_PROJECT_ID is undefined
- Solution: Ensure .env.local exists with correct variables
`bash
# .env.local
NEXT_PUBLIC_SANITY_PROJECT_ID=your-project-id
NEXT_PUBLIC_SANITY_DATASET=production
SANITY_API_TOKEN=your-token
`
- Use NEXT_PUBLIC_ prefix for client-side variables3. CORS errors when fetching from Sanity
- Problem: Browser blocks requests to Sanity API
- Solution: Use correct client configuration
`typescript
export const sanityClient = createClient({
projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID!,
dataset: 'production',
apiVersion: '2025-01-01',
useCdn: true, // Important for client-side
// NO token needed for public documents
})
`4. useEffect not triggering automatically
- Problem: Component doesn't fetch data on mount
- Solution: Add debug logging to see which conditions fail
`typescript
useEffect(() => {
console.log('useEffect conditions:', {
hasInitialProduct: !!initialProduct,
hasAsin: !!asin,
hasClient: !!client
})
}, [asin, client, initialProduct])
`#### API Issues
5. "Amazon API credentials not configured"
- Verify your Sanity API token has read access to
amazon.settings
- Check that amazon.settings document exists in Sanity Studio
- Ensure token is available server-side only6. "InvalidSignature" error
- Check your PA-API access key and secret key
- Verify your system clock is accurate
- Ensure you're using the correct region
7. Product documents not accessible
- Test with direct GROQ query:
`bash
curl -X POST "https://YOUR_PROJECT_ID.api.sanity.io/v2025-01-01/data/query/production" \
-H "Content-Type: application/json" \
-d '{"query": "*[_type == \"amazon.product\"][0]{asin, title}"}'
`
- Ensure documents are published (not drafts)
- Check document permissions in Sanity Studio$3
The component includes built-in debugging tools:
`tsx
// Enable debug mode to see detailed information
asin="B09XFQL45V"
client={sanityClient}
debug={process.env.NODE_ENV === 'development'}
/>
`Debug features:
- Console logging of all fetch attempts
- Visual debug panel showing component state
- Manual fetch button to test Sanity client
- Full product data logging
$3
1. Test Sanity Connection First
`typescript
import { testSanityConnection } from './lib/sanity-client-setup'
testSanityConnection('B09XFQL45V').then(result => {
console.log('Sanity test:', result)
})
`2. Create Test Products
See
examples/environment-setup.md for the script3. Use Debug Mode
`tsx
``4. Check Browser Console
- Look for 🎬, 🔍, 📦, ✅, ❌ emoji logs
- Manual fetch button provides direct testing
- Amazon Product Advertising API Documentation
- AWS Signature Version 4
- Sanity Client Documentation
- Next.js API Routes
MIT
For issues and questions:
1. Check the troubleshooting section above
2. Verify your configuration matches the examples
3. Check browser console and API server logs
4. Ensure your Amazon PA-API account is active
---
Note: This plugin requires an active Amazon Product Advertising API account and valid credentials. The PA-API has rate limits and approval requirements.