The problem
For Shopify merchants with large catalogs, product tagging is a nightmare. Manually tagging thousands of products is a time sink that leads to inconsistency; humans tend to use spammy, generic tags like "hot", "new", or "best-seller" that actually hurt SEO. There's no strategy behind the tags, no way to know which ones drive traffic, and no quality control before they go live.
Existing solutions either blindly overwrite tags with AI output ( risking data loss) or provide no intelligence at all. Merchants need something in between: an AI that understands SEO, combined with human oversight to ensure nothing breaks.
Story 1
Product discovery & filtering
Find the right products to optimize across a 20k+ catalog
The dashboard provides four search and filter dimensions that work together: search by product name, filter by existing Shopify tags (to find products that already use a specific tag), filter by collection (fetched live via Shopify GraphQL), and sort by newest/oldest update or product name A-Z. For a catalog of 20,000+ items, this makes it practical to find and batch-process the products that need attention.
Each row in the product table shows the product image, name, description, current tags, SEO score (if scored), the top optimization suggestion, and a "View Report" link for the full analysis. This gives merchants a health check view of their entire catalog at a glance — products with low scores or missing data stand out immediately.

Story 2
AI tag generation with human-in-the-loop
Safety first — AI suggests, humans decide
Select up to 10 products and click "Generate AI Tags." The OpenAI API analyzes each product's title and description to generate context-aware tags, understanding material, usage, target audience, and SEO relevance. But here's the key difference from other tools: nothing is saved automatically.
AI-generated tags appear in a staging state (shown in orange) alongside the existing tags (shown in gray). Merchants can review each tag, delete ones they disagree with, edit spelling or wording, and manually add their own tags via the input field. Only when they click "Confirm Tags" does the Shopify productUpdate mutation fire. There's also a "Replace Existing Tags with AI Tags" option for merchants who want a clean slate, and a "Cancel" button that discards all changes.
This non-destructive staging workflow is the core architectural decision of the entire app. I designed it because the cost of a bad tag update on a live store is high, broken filters, incorrect search results, lost customer trust. Zero data accidents is a feature, not a coincidence.

Non-destructive staging
AI tags stored in local frontend state first. Shopify API only called on explicit "Confirm" zero risk of accidental overwrites.
Full user control
Delete, edit, or add tags manually before committing. Each tag has an "x" button; an input field allows custom additions.
Batch processing
Generate and commit tags for up to 10 products simultaneously. Practical for large catalogs that need systematic optimization.
Story 3
Proprietary SEO scoring engine
Not just a number — actionable feedback across 6 dimensions
Select products and click "Score Selected Tags" to run the analysis. The scoring algorithm evaluates existing tags across six dimensions: tag quantity (5-10 is optimal), duplicate detection, weak word filtering (flags terms like "hot" or "new" that hurt SEO), function/material/scene keyword coverage, title keyword matching, and overall diversity.
What makes this more than a generic checker is the industry-specific keyword databases. I built 13 category-specific dictionaries, fashion, electronics, industrial, beauty, sports, food, and more, each containing curated lists of functional, material, and scene-based keywords. The algorithm matches tags against the relevant industry dictionary, so a "waterproof" tag scores well for sports equipment but wouldn't be flagged as missing for food products.
Scores and the top suggestion appear inline in the product list. Clicking "View Report" opens a detailed breakdown page with the full score and up to three specific optimization recommendations, for example, "Contains weak words (e.g., 'hot'). Try using more specific terms" or "Try including keywords from the product title."


Scoring dimensions (100 points)
Technical deep dive
Three-state tag management
The frontend manages three distinct tag states simultaneously: "Original Tags" (from Shopify), "AI Draft Tags" (staged, shown in orange), and "Final Tags" (committed). This state machine handles edge cases like re-generating tags for an already-staged product, adding manual tags alongside AI-generated ones, and reverting to original tags on cancel.
// State flow: Original → AI Draft (staging) → Final (committed)
// Shopify productUpdate mutation ONLY fires on explicit confirm
const mutation = `
mutation productUpdate($input: ProductInput!) {
productUpdate(input: $input) {
product { id, tags }
userErrors { field, message }
}
}
`;
// Called only when user clicks "Confirm Tags"Industry-specific keyword databases
Built 13 curated keyword dictionaries (fashion, electronics, industrial, beauty, baby, sports, pet, food, craft, digital, home/kitchen, adult, general), each containing three categories: functional keywords, material keywords, and scene/usage keywords. The scoring algorithm loads the relevant dictionary based on product type and matches against it.
// 13 industry keyword maps
const KEYWORD_MAP = {
fashion: { function, material, scene },
electronics: { function, material, scene },
industrial: { function, material, scene },
// ... 10 more categories
};
// Scoring matches tags against relevant industry dictionary
const keywords = KEYWORD_MAP[productType] || generalKeywords;Exhaustive tag aggregation via cursor pagination
The tag search filter needs to know every unique tag across the entire product catalog. I built a paginated GraphQL crawler that fetches all products 100 at a time using cursor-based pagination, aggregates every tag into a Set (for O(1) dedup), and returns the complete unique tag list. For a 20k+ catalog, this runs on the server via Remix loader to avoid blocking the UI.
// Cursor-paginated tag aggregation across entire catalog
const allTags = new Set();
while (hasNextPage) {
const data = await admin.graphql(query, {
variables: { first: 100, after: cursor }
});
for (const edge of data.products.edges) {
edge.node.tags.forEach(tag => allTags.add(tag));
cursor = edge.cursor;
}
hasNextPage = data.products.pageInfo.hasNextPage;
}Remix SSR for secure API handling
All OpenAI API calls and Shopify admin authentication happen server-side via Remix loader/action patterns. API keys never touch the client. The Shopify App Bridge handles session authentication, and Prisma ORM provides local data persistence for settings and tag history. TypeScript interfaces enforce strict data validation between the Shopify GraphQL Admin API and the frontend, preventing runtime errors in the tagging workflow.
What I learned
Building TagWise taught me that AI features need more UX guardrails, not fewer. The temptation was to make the flow as frictionless as possible, "click button, get tags, done." But talking to merchants revealed that trust is the bottleneck: they don't want AI silently changing their live store data. The staging workflow adds one extra step, but it's the step that makes merchants actually use the tool instead of being afraid of it.
The scoring engine was also a lesson in domain specificity. A generic "tag quality" algorithm is nearly useless, what makes a good tag for a snowboard is completely different from what makes a good tag for a lab instrument. Building 13 keyword databases was tedious, but it's what makes the scoring genuinely useful rather than just a vanity metric.
