SuiteCommerce SEO: Schema Markup, Technical SEO, and What Actually Works
Here's an uncomfortable truth: 73% of SuiteCommerce sites we audit have critical technical SEO issues that generic optimization can't fix.
The problem isn't that store owners don't care about SEO. It's that standard SEO advice—"add meta descriptions," "build backlinks," "create quality content"—fails to address SuiteCommerce's unique architecture. The platform generates URLs differently. It handles pagination differently. Its JavaScript-heavy frontend creates crawlability challenges that WordPress sites never face.
We've fixed technical SEO on dozens of SuiteCommerce implementations. This guide gives you the specific, platform-tested strategies that actually improve rankings—not the recycled advice that works everywhere except NetSuite's e-commerce platform.
Why Generic SEO Advice Fails for SuiteCommerce
SuiteCommerce isn't like Shopify, Magento, or WooCommerce. Its architecture creates SEO challenges that platform-agnostic guides completely miss.
Challenge 1: JavaScript-Rendered Content
SuiteCommerce is a single-page application built on Backbone.js. When Googlebot first loads your product page, it sees a shell. The actual content—product name, description, price, reviews—loads after JavaScript executes.
Google has gotten better at rendering JavaScript, but there's a catch: JavaScript rendering happens in a deferred queue. Your content might not get processed for days or weeks. Meanwhile, a competitor's server-rendered page gets indexed within hours.
Impact: New products, price changes, and content updates appear in search results slower. During peak seasons, this delay costs sales.
Challenge 2: Session-Based URL Parameters
SuiteCommerce appends session identifiers and tracking parameters to URLs by default. A single product might be accessible at:
/product/blue-widget/product/blue-widget?sc_camp=12345/product/blue-widget?f=brand/product/blue-widget?session=abc123xyz
To Google, these are four different pages with identical content. Your crawl budget gets wasted, and link equity gets diluted across URL variants.
Challenge 3: Thin Category Pages
Out of the box, SuiteCommerce category pages contain almost no unique text content. They're essentially product grids with a title. Google sees hundreds of pages that look nearly identical—varying only by which products appear.
Challenge 4: Faceted Navigation Explosion
A SuiteCommerce store with 10 filterable attributes, each with 10 values, theoretically creates millions of URL combinations. Most are near-duplicate pages that dilute your site's authority and confuse search engines about which page should rank.
The SuiteCommerce SEO Mindset
Effective SuiteCommerce SEO requires thinking like a search engineer, not a marketer. You're solving crawlability, indexation, and rendering problems as much as optimizing content.
The strategies below address these platform-specific challenges directly.
Technical SEO Checklist for SuiteCommerce
Before worrying about schema markup or content optimization, fix these foundational issues. They're the difference between a site Google can effectively crawl and one it struggles to understand.
1. Configure Proper Crawlability
Enable server-side rendering where possible:
SuiteCommerce Advanced (SCA) supports server-side rendering for certain page types. Enable it for product and category pages to ensure Googlebot sees content immediately.
// In your Configuration.js
Configuration['ssp-libraries'] = {
serverSideRender: {
'ProductDetails.Full.View': true,
'Facets.Browse.View': true,
'Home.View': true
}
};
Submit a proper XML sitemap:
SuiteCommerce can generate sitemaps, but they often include non-canonical URLs. Generate a clean sitemap that includes only canonical product and category URLs.
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<!-- Only canonical product URLs -->
<url>
<loc>https://yourstore.com/product/blue-widget</loc>
<lastmod>2026-01-15</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<!-- Category pages -->
<url>
<loc>https://yourstore.com/category/widgets</loc>
<lastmod>2026-01-20</lastmod>
<changefreq>daily</changefreq>
<priority>0.7</priority>
</url>
</urlset>
Submit to Google Search Console and Bing Webmaster Tools. Monitor for crawl errors weekly.
Optimize robots.txt:
Block URL patterns that create duplicate content while allowing access to necessary resources.
User-agent: *
# Block session/tracking parameters
Disallow: /*?sc_camp=
Disallow: /*?session=
Disallow: /*&session=
# Block faceted navigation combinations that create thin content
Disallow: /*?f=*&f=*&f=*
# Block internal search results
Disallow: /search?
# Allow CSS/JS for rendering
Allow: /sca-dev-*
Allow: /*.css
Allow: /*.js
# Sitemap location
Sitemap: https://yourstore.com/sitemap.xml
2. Implement Proper Canonical Tags
Every page needs a self-referencing canonical tag pointing to its clean URL. This is non-negotiable for SuiteCommerce.
// modules/SEOCanonical/JavaScript/SEO.Canonical.js
define('SEO.Canonical', ['Backbone', 'jQuery'], function(Backbone, $) {
'use strict';
return {
setCanonical: function(url) {
var canonical = document.querySelector('link[rel="canonical"]');
var cleanUrl = this.getCleanUrl(url);
if (canonical) {
canonical.href = cleanUrl;
} else {
var link = document.createElement('link');
link.rel = 'canonical';
link.href = cleanUrl;
document.head.appendChild(link);
}
},
getCleanUrl: function(url) {
var parsed = new URL(url, window.location.origin);
// Remove tracking and session parameters
var paramsToRemove = ['sc_camp', 'session', 'utm_source', 'utm_medium',
'utm_campaign', 'gclid', 'fbclid'];
paramsToRemove.forEach(function(param) {
parsed.searchParams.delete(param);
});
// For product pages, remove all parameters
if (parsed.pathname.includes('/product/')) {
return parsed.origin + parsed.pathname;
}
return parsed.origin + parsed.pathname + parsed.search;
}
};
});
For faceted navigation pages, canonicalize to the parent category unless the filtered page has unique, valuable content:
// Canonical logic for faceted navigation
getFacetCanonical: function(currentUrl, appliedFacets) {
// If more than 2 facets applied, canonicalize to category
if (appliedFacets.length > 2) {
return this.getCategoryUrl();
}
// Single facet with significant search volume? Keep it indexable
if (appliedFacets.length === 1 && this.isHighValueFacet(appliedFacets[0])) {
return currentUrl;
}
// Default: canonicalize to category
return this.getCategoryUrl();
}
3. Fix Internal Linking Structure
SuiteCommerce's default navigation often creates orphaned pages and inefficient link structures.
Create category hierarchies in your templates:
<!-- Breadcrumb navigation with proper linking -->
<nav aria-label="Breadcrumb" class="breadcrumb">
<ol itemscope itemtype="https://schema.org/BreadcrumbList">
<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
<a itemprop="item" href="/"><span itemprop="name">Home</span></a>
<meta itemprop="position" content="1" />
</li>
<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
<a itemprop="item" href="/category/{{parentCategory.url}}">
<span itemprop="name">{{parentCategory.name}}</span>
</a>
<meta itemprop="position" content="2" />
</li>
<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
<span itemprop="name">{{currentCategory.name}}</span>
<meta itemprop="position" content="3" />
</li>
</ol>
</nav>
Add related products with proper links:
// Ensure related product links use clean URLs
RelatedProducts.View.prototype.getCleanProductUrl = function(product) {
return '/product/' + product.get('urlcomponent');
};
4. Optimize Page Speed for SEO
Google's crawler has a time budget. Slow pages get less thoroughly crawled and indexed. See our Core Web Vitals optimization guide for detailed implementation.
Key metrics that affect crawl efficiency:
- Time to First Byte (TTFB): Under 600ms
- Full page load: Under 3 seconds
- JavaScript execution: Complete within 5 seconds
5. Handle Pagination Correctly
SuiteCommerce category pages with many products use pagination. Handle it properly to avoid duplicate content and ensure all products get discovered.
<!-- On page 1 -->
<link rel="canonical" href="https://yourstore.com/category/widgets" />
<link rel="next" href="https://yourstore.com/category/widgets?page=2" />
<!-- On page 2 -->
<link rel="canonical" href="https://yourstore.com/category/widgets?page=2" />
<link rel="prev" href="https://yourstore.com/category/widgets" />
<link rel="next" href="https://yourstore.com/category/widgets?page=3" />
<!-- On last page -->
<link rel="canonical" href="https://yourstore.com/category/widgets?page=10" />
<link rel="prev" href="https://yourstore.com/category/widgets?page=9" />
Implementation:
// modules/SEOPagination/JavaScript/SEO.Pagination.js
define('SEO.Pagination', ['Backbone'], function(Backbone) {
'use strict';
return {
setPaginationLinks: function(currentPage, totalPages, baseUrl) {
this.removeExistingLinks();
if (currentPage > 1) {
var prevUrl = currentPage === 2
? baseUrl
: baseUrl + '?page=' + (currentPage - 1);
this.addLink('prev', prevUrl);
}
if (currentPage < totalPages) {
var nextUrl = baseUrl + '?page=' + (currentPage + 1);
this.addLink('next', nextUrl);
}
},
addLink: function(rel, href) {
var link = document.createElement('link');
link.rel = rel;
link.href = href;
document.head.appendChild(link);
},
removeExistingLinks: function() {
document.querySelectorAll('link[rel="prev"], link[rel="next"]')
.forEach(function(link) { link.remove(); });
}
};
});
Schema Markup Implementation Guide
Schema markup helps search engines understand your content and enables rich results—those eye-catching listings with star ratings, prices, and availability that dominate search results.
For SuiteCommerce, you need Product, Organization, BreadcrumbList, and potentially Review schema. Here's how to implement each correctly.
Product Schema for Product Detail Pages
Product schema is the highest-impact structured data for e-commerce. It enables rich results showing price, availability, ratings, and reviews directly in search.
// modules/ProductSchema/JavaScript/Product.Schema.js
define('Product.Schema', ['Backbone', 'underscore'], function(Backbone, _) {
'use strict';
return {
generate: function(product, storeInfo) {
var schema = {
'@context': 'https://schema.org',
'@type': 'Product',
'name': product.get('displayname') || product.get('itemid'),
'description': this.cleanDescription(product.get('storedetaileddescription')),
'sku': product.get('itemid'),
'mpn': product.get('mpn') || product.get('itemid'),
'image': this.getProductImages(product),
'url': window.location.origin + '/product/' + product.get('urlcomponent'),
'brand': {
'@type': 'Brand',
'name': product.get('custitem_brand') || storeInfo.companyName
}
};
// Add GTIN if available
if (product.get('upccode')) {
schema.gtin12 = product.get('upccode');
}
// Add aggregate rating if reviews exist
var reviewCount = product.get('custitem_review_count') || 0;
var avgRating = product.get('custitem_avg_rating');
if (reviewCount > 0 && avgRating) {
schema.aggregateRating = {
'@type': 'AggregateRating',
'ratingValue': parseFloat(avgRating).toFixed(1),
'reviewCount': parseInt(reviewCount, 10),
'bestRating': '5',
'worstRating': '1'
};
}
// Add offers (required for merchant listings)
schema.offers = this.generateOffers(product, storeInfo);
return schema;
},
generateOffers: function(product, storeInfo) {
var price = product.get('onlinecustomerprice_detail')?.onlinecustomerprice
|| product.get('pricelevel1');
var availability = product.get('isinstock')
? 'https://schema.org/InStock'
: 'https://schema.org/OutOfStock';
var offer = {
'@type': 'Offer',
'url': window.location.href,
'priceCurrency': storeInfo.currency || 'USD',
'price': parseFloat(price).toFixed(2),
'availability': availability,
'seller': {
'@type': 'Organization',
'name': storeInfo.companyName
}
};
// Add price valid until (30 days from now)
var validUntil = new Date();
validUntil.setDate(validUntil.getDate() + 30);
offer.priceValidUntil = validUntil.toISOString().split('T')[0];
// Add shipping details if free shipping available
if (product.get('custitem_free_shipping')) {
offer.shippingDetails = {
'@type': 'OfferShippingDetails',
'shippingRate': {
'@type': 'MonetaryAmount',
'value': '0',
'currency': storeInfo.currency || 'USD'
},
'shippingDestination': {
'@type': 'DefinedRegion',
'addressCountry': 'US'
},
'deliveryTime': {
'@type': 'ShippingDeliveryTime',
'handlingTime': {
'@type': 'QuantitativeValue',
'minValue': 1,
'maxValue': 2,
'unitCode': 'd'
},
'transitTime': {
'@type': 'QuantitativeValue',
'minValue': 3,
'maxValue': 7,
'unitCode': 'd'
}
}
};
}
// Add return policy
offer.hasMerchantReturnPolicy = {
'@type': 'MerchantReturnPolicy',
'applicableCountry': 'US',
'returnPolicyCategory': 'https://schema.org/MerchantReturnFiniteReturnWindow',
'merchantReturnDays': 30,
'returnMethod': 'https://schema.org/ReturnByMail',
'returnFees': 'https://schema.org/FreeReturn'
};
return offer;
},
getProductImages: function(product) {
var images = product.get('itemimages_detail') || {};
var imageUrls = [];
// Get main image
if (images.main) {
imageUrls.push(images.main.url);
}
// Get additional images
if (images.additional && Array.isArray(images.additional)) {
images.additional.forEach(function(img) {
if (img.url) imageUrls.push(img.url);
});
}
return imageUrls.length > 0 ? imageUrls : undefined;
},
cleanDescription: function(html) {
if (!html) return '';
// Strip HTML tags
var tmp = document.createElement('div');
tmp.innerHTML = html;
var text = tmp.textContent || tmp.innerText || '';
// Truncate to 5000 chars (Google's limit)
return text.substring(0, 5000).trim();
},
inject: function(schema) {
// Remove existing product schema
document.querySelectorAll('script[type="application/ld+json"][data-schema="product"]')
.forEach(function(el) { el.remove(); });
var script = document.createElement('script');
script.type = 'application/ld+json';
script.setAttribute('data-schema', 'product');
script.textContent = JSON.stringify(schema);
document.head.appendChild(script);
}
};
});
Organization Schema
Place Organization schema on your homepage and About page. It establishes your business entity for Google's Knowledge Graph.
// Organization schema for site-wide injection
var organizationSchema = {
'@context': 'https://schema.org',
'@type': 'Organization',
'name': 'Your Company Name',
'url': 'https://yourstore.com',
'logo': 'https://yourstore.com/images/logo.png',
'description': 'Your company description here.',
'address': {
'@type': 'PostalAddress',
'streetAddress': '123 Main Street',
'addressLocality': 'Your City',
'addressRegion': 'ST',
'postalCode': '12345',
'addressCountry': 'US'
},
'contactPoint': {
'@type': 'ContactPoint',
'telephone': '+1-800-555-0123',
'contactType': 'customer service',
'availableLanguage': 'English'
},
'sameAs': [
'https://www.facebook.com/yourcompany',
'https://www.linkedin.com/company/yourcompany',
'https://twitter.com/yourcompany'
]
};
BreadcrumbList Schema
Breadcrumb schema enables rich breadcrumb navigation in search results. Implement on all pages with hierarchical navigation.
// modules/BreadcrumbSchema/JavaScript/Breadcrumb.Schema.js
define('Breadcrumb.Schema', [], function() {
'use strict';
return {
generate: function(breadcrumbs) {
var items = breadcrumbs.map(function(crumb, index) {
return {
'@type': 'ListItem',
'position': index + 1,
'name': crumb.name,
'item': crumb.url ? window.location.origin + crumb.url : undefined
};
});
return {
'@context': 'https://schema.org',
'@type': 'BreadcrumbList',
'itemListElement': items
};
},
inject: function(schema) {
document.querySelectorAll('script[data-schema="breadcrumb"]')
.forEach(function(el) { el.remove(); });
var script = document.createElement('script');
script.type = 'application/ld+json';
script.setAttribute('data-schema', 'breadcrumb');
script.textContent = JSON.stringify(schema);
document.head.appendChild(script);
}
};
});
Review Schema
If you collect product reviews, add Review schema. Be careful: Google penalizes fake or manipulated reviews. Only use authentic customer reviews.
// Generate individual review schema
generateReviewSchema: function(reviews) {
return reviews.map(function(review) {
return {
'@type': 'Review',
'author': {
'@type': 'Person',
'name': review.authorName || 'Anonymous'
},
'datePublished': review.date,
'reviewBody': review.text,
'reviewRating': {
'@type': 'Rating',
'ratingValue': review.rating,
'bestRating': '5',
'worstRating': '1'
}
};
});
}
Testing Your Schema Markup
Always validate schema before deploying:
- Google Rich Results Test: https://search.google.com/test/rich-results
- Schema.org Validator: https://validator.schema.org/
- Google Search Console: Check "Enhancements" for errors
Common errors we see in SuiteCommerce implementations:
- Missing required fields (price, availability)
- Invalid date formats
- Mismatched currencies
- Review counts that don't match actual reviews
Fixing Faceted Navigation Duplicate Content
Faceted navigation is SuiteCommerce's biggest SEO liability. A category page with Size, Color, Brand, and Price filters can generate thousands of crawlable URL variations—most with nearly identical content.
Understanding the Problem
Your "Blue Widgets" category at /category/widgets?f=color:blue might rank for "blue widgets." But when combined with other facets:
/category/widgets?f=color:blue&f=size:large/category/widgets?f=size:large&f=color:blue/category/widgets?f=color:blue&f=price:0-50
These pages compete with each other, diluting the authority of each.
The Strategic Approach
Not all faceted pages are equal. Some have genuine search demand and deserve indexation. Others are just filtering tools that should be hidden from search engines.
Step 1: Identify high-value faceted combinations
Check Google Search Console for faceted URLs already receiving impressions or clicks. Use keyword research to identify facets with search volume:
- "Large blue widgets" - might have search volume
- "Blue widgets under $50 size large free shipping" - almost certainly doesn't
Step 2: Create an indexation policy
| Facet Combination | Indexation Policy |
|---|---|
| Single facet (color, size, brand) | Index if search volume exists |
| Two facets | Case-by-case, usually noindex |
| Three+ facets | Always noindex |
| Price range facets | Typically noindex |
| Sort order parameters | Never index |
Implementation
Option 1: Canonical tags (Recommended)
Canonicalize low-value faceted pages to the parent category:
// modules/FacetedSEO/JavaScript/Faceted.SEO.js
define('Faceted.SEO', [], function() {
'use strict';
var highValueFacets = ['brand', 'color', 'size', 'category'];
return {
shouldIndex: function(appliedFacets) {
// Index single high-value facets
if (appliedFacets.length === 1) {
return highValueFacets.includes(appliedFacets[0].id);
}
// Never index more than one facet
return false;
},
getCanonicalUrl: function(categoryUrl, appliedFacets) {
if (this.shouldIndex(appliedFacets)) {
// Return the faceted URL as canonical
return window.location.href;
}
// Canonicalize to parent category
return window.location.origin + categoryUrl;
},
setRobotsMeta: function(appliedFacets) {
var meta = document.querySelector('meta[name="robots"]');
if (!this.shouldIndex(appliedFacets)) {
if (meta) {
meta.content = 'noindex, follow';
} else {
meta = document.createElement('meta');
meta.name = 'robots';
meta.content = 'noindex, follow';
document.head.appendChild(meta);
}
} else if (meta && meta.content.includes('noindex')) {
meta.content = 'index, follow';
}
}
};
});
Option 2: Robots.txt blocking
For aggressive deindexation, block faceted URLs entirely:
# Block multi-facet combinations
Disallow: /*f=*&f=*
Disallow: /*f=*&f=*&f=*
# Block specific low-value facets
Disallow: /*f=price*
Disallow: /*f=rating*
Disallow: /*sort=*
Option 3: URL parameter handling in Search Console
Configure URL parameters in Google Search Console to tell Google how to handle each parameter:
| Parameter | Behavior |
|---|---|
| f (facets) | Narrows (let Google decide) |
| sort | No effect on content |
| page | Paginates |
| sc_camp | No effect on content |
Best Practices
- Keep filter URLs consistent: Always generate facet parameters in the same order
- Use parameter encoding consistently:
?f=color:bluenot?f=color%3Ablue - Link to canonical URLs internally: Don't link to faceted pages from your navigation
- Monitor index coverage: Check Google Search Console weekly for indexed faceted URLs
URL Structure Optimization
SuiteCommerce's default URL structure is functional but not optimal. With some configuration, you can create cleaner, more SEO-friendly URLs.
Product URLs
Default: /product/item-12345
Optimized: /product/blue-widget-large
Configure the URL component field in NetSuite to generate descriptive slugs:
// SuiteScript to auto-generate URL components
/**
* @NApiVersion 2.x
* @NScriptType UserEventScript
*/
define(['N/record'], function(record) {
function beforeSubmit(context) {
var item = context.newRecord;
var displayName = item.getValue({ fieldId: 'displayname' });
var existingUrl = item.getValue({ fieldId: 'urlcomponent' });
// Only generate if empty
if (!existingUrl && displayName) {
var urlComponent = generateSlug(displayName);
item.setValue({ fieldId: 'urlcomponent', value: urlComponent });
}
}
function generateSlug(text) {
return text
.toLowerCase()
.replace(/[^\w\s-]/g, '')
.replace(/[\s_-]+/g, '-')
.replace(/^-+|-+$/g, '')
.substring(0, 100);
}
return {
beforeSubmit: beforeSubmit
};
});
Category URLs
Create logical hierarchies:
/widgets→ Parent category/widgets/blue-widgets→ Subcategory/widgets/blue-widgets/large→ Sub-subcategory
Avoid deep nesting beyond 3 levels—it dilutes PageRank and creates usability issues.
Handling URL Changes
When restructuring URLs, implement 301 redirects for all old URLs:
// SuiteScript for redirect management
// Redirect map stored in custom record
function getRedirectMap() {
return {
'/old-product-url': '/product/new-product-url',
'/old-category': '/new-category'
};
}
// In your SSP controller
function handleRequest(request, response) {
var path = request.url;
var redirectMap = getRedirectMap();
if (redirectMap[path]) {
response.sendRedirect({
type: http.RedirectType.PERMANENT,
url: redirectMap[path]
});
return;
}
// Normal processing
}
Meta Tag Automation Strategies
Manually writing unique meta titles and descriptions for thousands of products isn't scalable. Implement smart automation that generates optimized, unique-enough metadata.
Dynamic Title Tags
Create templates that pull from product data:
// modules/SEOMeta/JavaScript/SEO.Meta.js
define('SEO.Meta', [], function() {
'use strict';
var templates = {
product: '{productName} | {brandName} | {storeName}',
productWithPrice: '{productName} - ${price} | {storeName}',
category: 'Shop {categoryName} | {productCount} Products | {storeName}',
categoryWithFilter: '{filterValue} {categoryName} | {storeName}'
};
return {
generateProductTitle: function(product, config) {
var template = product.get('onlinecustomerprice')
? templates.productWithPrice
: templates.product;
return this.applyTemplate(template, {
productName: product.get('displayname'),
brandName: product.get('custitem_brand') || '',
price: product.get('onlinecustomerprice'),
storeName: config.storeName
});
},
generateProductDescription: function(product) {
var description = product.get('storedescription') || '';
// If no description, generate from attributes
if (!description) {
description = this.generateFromAttributes(product);
}
// Ensure proper length (150-160 chars optimal)
return this.truncate(description, 160);
},
generateFromAttributes: function(product) {
var parts = [];
if (product.get('custitem_brand')) {
parts.push('Shop ' + product.get('custitem_brand'));
}
parts.push(product.get('displayname'));
if (product.get('onlinecustomerprice')) {
parts.push('starting at $' + product.get('onlinecustomerprice'));
}
if (product.get('isinstock')) {
parts.push('In stock');
}
parts.push('Free shipping available.');
return parts.join('. ');
},
truncate: function(text, maxLength) {
if (text.length <= maxLength) return text;
return text.substring(0, text.lastIndexOf(' ', maxLength - 3)) + '...';
},
applyTemplate: function(template, data) {
return template.replace(/\{(\w+)\}/g, function(match, key) {
return data[key] || '';
}).replace(/\s+/g, ' ').trim();
}
};
});
Category Page Meta
For category pages, include product counts and highlight unique selling propositions:
generateCategoryMeta: function(category, products, filters) {
var title, description;
if (filters.length > 0) {
// Filtered view
title = filters.map(f => f.value).join(' ') + ' ' + category.name;
description = 'Browse ' + products.totalCount + ' ' +
filters.map(f => f.value).join(' ') + ' ' +
category.name.toLowerCase() + '. Free shipping on orders over $50.';
} else {
// Main category
title = 'Shop ' + category.name + ' | ' + products.totalCount + ' Products';
description = 'Discover our full range of ' + category.name.toLowerCase() +
'. ' + products.totalCount + ' products with free shipping available.';
}
return { title, description };
}
Avoiding Duplicate Meta Content
The risk with automation is creating thousands of pages with nearly identical titles. Add variation:
- Rotate CTA phrases: "Shop now," "Buy today," "Free shipping," "In stock"
- Include category context: "Blue Widget for Electronics" vs. "Blue Widget for Industrial"
- Add unique attributes: Size, color, material when distinctive
Monitoring and Measuring Results
SEO improvements take time. Set up proper tracking to measure progress and catch regressions.
Essential Monitoring Setup
1. Google Search Console
- Monitor Index Coverage for errors
- Check Core Web Vitals for technical issues
- Track click-through rates by query
- Review manual actions and security issues
2. Track ranking positions
Use a rank tracking tool (Ahrefs, SEMrush, or Moz) to monitor positions for:
- Brand terms
- Category keywords
- Top 50 product names
- Competitor comparison terms
3. Organic traffic and revenue
Connect Google Analytics 4 to your SuiteCommerce store:
// Enhanced e-commerce tracking for SEO attribution
gtag('event', 'purchase', {
'transaction_id': order.id,
'value': order.total,
'currency': 'USD',
'items': order.items.map(function(item) {
return {
'item_id': item.sku,
'item_name': item.name,
'price': item.price,
'quantity': item.quantity
};
})
});
SEO Metrics to Track Monthly
| Metric | Target | Tool |
|---|---|---|
| Indexed pages | Growing steadily | Search Console |
| Crawl errors | Under 1% of pages | Search Console |
| Average position | Improving | Search Console |
| Organic clicks | +10% MoM | Search Console |
| Organic revenue | +10% QoQ | Analytics |
| Rich result impressions | Growing | Search Console |
When to Expect Results
| Change Type | Time to Impact |
|---|---|
| Technical fixes (canonicals, redirects) | 2-4 weeks |
| Schema markup addition | 4-8 weeks |
| New content/pages | 3-6 months |
| URL restructuring | 6-12 months |
| Domain authority building | 12+ months |
FAQ
Does SuiteCommerce support server-side rendering for SEO?
SuiteCommerce Advanced (SCA) supports server-side rendering for some views, which helps with crawlability. Standard SuiteCommerce relies on JavaScript rendering. For critical SEO pages, ensure SSR is enabled or implement prerendering for search engines.
How often should I update my XML sitemap?
For active e-commerce sites, regenerate sitemaps daily or when products change significantly (new products, discontinued items, major price changes). Submit via Search Console and include <lastmod> dates so Google knows what's changed.
Can I use the same meta description for similar products?
Technically yes, but it's not ideal. Google doesn't penalize duplicate meta descriptions, but unique descriptions improve click-through rates. Use templates with product-specific data to create variations at scale.
Why aren't my rich results showing in search?
Common reasons: invalid schema markup (test with Google's tool), page not indexed yet, Google choosing not to display rich results for your query, or your site lacking sufficient authority. Rich results are never guaranteed—they're at Google's discretion.
Should I noindex out-of-stock products?
Generally no. Keep out-of-stock products indexed but mark them as unavailable in schema. If a product will never return, 301 redirect to a similar product or the parent category. Removing pages loses any accumulated SEO equity.
Start Fixing Your SuiteCommerce SEO Today
Technical SEO for SuiteCommerce isn't a one-time project—it's ongoing maintenance. Start with the foundational issues (canonicals, crawlability, sitemaps), then layer on schema markup and advanced optimizations.
The stores we work with typically see measurable improvements within 90 days of implementing these changes: higher rankings for product terms, increased organic traffic, and better conversion rates from search visitors who land on properly optimized pages.
Need help implementing these changes? Our SEO specialists focus exclusively on SuiteCommerce and NetSuite e-commerce.
We'll analyze your site's technical SEO health and identify the highest-impact opportunities for your specific implementation.
Need Help with Your NetSuite Project?
Our team of experts is ready to help you achieve your goals.
