SuiteCommerce SEO: Schema Markup, Technical SEO, and What Actually Works
SEOSchema MarkupTechnical SEOJSON-LDStructured DataSuiteCommerceNetSuite

SuiteCommerce SEO: Schema Markup, Technical SEO, and What Actually Works

January 30, 2026•1 min read
Back to Blog

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'
    ]
};

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:

  1. Google Rich Results Test: https://search.google.com/test/rich-results
  2. Schema.org Validator: https://validator.schema.org/
  3. 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 CombinationIndexation Policy
Single facet (color, size, brand)Index if search volume exists
Two facetsCase-by-case, usually noindex
Three+ facetsAlways noindex
Price range facetsTypically noindex
Sort order parametersNever 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:

ParameterBehavior
f (facets)Narrows (let Google decide)
sortNo effect on content
pagePaginates
sc_campNo effect on content

Best Practices

  1. Keep filter URLs consistent: Always generate facet parameters in the same order
  2. Use parameter encoding consistently: ?f=color:blue not ?f=color%3Ablue
  3. Link to canonical URLs internally: Don't link to faceted pages from your navigation
  4. 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:

  1. Rotate CTA phrases: "Shop now," "Buy today," "Free shipping," "In stock"
  2. Include category context: "Blue Widget for Electronics" vs. "Blue Widget for Industrial"
  3. 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

MetricTargetTool
Indexed pagesGrowing steadilySearch Console
Crawl errorsUnder 1% of pagesSearch Console
Average positionImprovingSearch Console
Organic clicks+10% MoMSearch Console
Organic revenue+10% QoQAnalytics
Rich result impressionsGrowingSearch Console

When to Expect Results

Change TypeTime to Impact
Technical fixes (canonicals, redirects)2-4 weeks
Schema markup addition4-8 weeks
New content/pages3-6 months
URL restructuring6-12 months
Domain authority building12+ 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.

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.

Get a Free SEO Audit →

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.