<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sandra Sakura</title>
    <description>The latest articles on DEV Community by Sandra Sakura (@csandra_ericson).</description>
    <link>https://dev.to/csandra_ericson</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F442900%2Fb5cba284-5ba4-4ebf-ad43-5efa4c528dfd.jpg</url>
      <title>DEV Community: Sandra Sakura</title>
      <link>https://dev.to/csandra_ericson</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/csandra_ericson"/>
    <language>en</language>
    <item>
      <title>Cleaning Up a 1,500-Product Halal Grocery Catalog: A WooCommerce SEO Case Study</title>
      <dc:creator>Sandra Sakura</dc:creator>
      <pubDate>Sun, 13 Sep 2026 12:19:39 +0000</pubDate>
      <link>https://dev.to/csandra_ericson/cleaning-up-a-1500-product-halal-grocery-catalog-a-woocommerce-seo-case-study-38ee</link>
      <guid>https://dev.to/csandra_ericson/cleaning-up-a-1500-product-halal-grocery-catalog-a-woocommerce-seo-case-study-38ee</guid>
      <description>&lt;h2&gt;Cleaning Up a 1,500-Product WooCommerce Catalog: What I Learned the Hard Way&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; I spent months working on the catalog for a halal grocery store in Shinjuku, Tokyo (&lt;a href="https://jbhalalfood.com" rel="noopener noreferrer"&gt;JB Halal Food&lt;/a&gt;) that serves the Bangladeshi, South Asian, and Southeast Asian communities living in Japan. 1,500+ WooCommerce products, hundreds blank or half-written, no product variations set up anywhere, inconsistent claims on the packaging, and imports that quietly failed without anyone noticing. Here's what that actually looked like day to day.&lt;/p&gt;

&lt;h3&gt;The starting point&lt;/h3&gt;

&lt;p&gt;The store imports and sells halal groceries — everything from Bangladeshi fish and Pran-brand snacks to Indonesian sambal and instant noodles — to a diaspora customer base scattered across Japan. It runs on &lt;a href="https://dev.to/t/wordpress"&gt;WordPress&lt;/a&gt; + &lt;a href="https://dev.to/t/woocommerce"&gt;WooCommerce&lt;/a&gt; with the Umart theme and Rank Math for on-page optimization, plus Klaviyo for email.&lt;/p&gt;

&lt;p&gt;The catalog itself told a messier story:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;~1,547 total products&lt;/li&gt;
  &lt;li&gt;400 completely blank&lt;/li&gt;
  &lt;li&gt;115 with poor/thin descriptions&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;Zero&lt;/strong&gt; existing variable products — every different weight or size of the same item was a separate, unrelated simple-product listing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last point mattered more than it sounds. A store selling the same rice brand in 1kg, 5kg, and 10kg bags had three disconnected product pages, no shared reviews, and no way for a customer to switch sizes without leaving the page.&lt;/p&gt;

&lt;h3&gt;Problem 1: "Halal" isn't a checkbox, it's a content policy&lt;/h3&gt;

&lt;p&gt;You can't just slap a halal badge on everything and call it done — some suppliers publish dual-market products (domestic vs. export-certified versions of the same packaging), and getting that wrong is a trust problem, not just an SEO one. I ended up writing an actual policy:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Only claim halal when there's real evidence (certification language visible on the label/photo)&lt;/li&gt;
  &lt;li&gt;Whole categories like dry spice blends and rice are treated as low-risk by default&lt;/li&gt;
  &lt;li&gt;Products from majority-Muslim countries of origin get a more liberal pass&lt;/li&gt;
  &lt;li&gt;Anything with a known dual-market conflict (a well-known instant noodle brand, for example) gets flagged and the claim withheld until confirmed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This turned "write a product description" into "write a product description that won't misrepresent what's actually in the package."&lt;/p&gt;

&lt;h3&gt;Problem 2: Multilingual SEO for a catalog nobody else is optimizing&lt;/h3&gt;

&lt;p&gt;Most of this inventory has &lt;em&gt;never&lt;/em&gt; been properly indexed anywhere in English or Japanese — it's diaspora-specific and long-tail by nature. The fix wasn't "translate the title," it was matching the language in the title to the product's actual origin:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Bangladeshi brand → Bengali term in the title&lt;/li&gt;
  &lt;li&gt;Indonesian brand → Bahasa Indonesia term&lt;/li&gt;
  &lt;li&gt;Generic/no-brand item → English + Japanese only, never defaulting to Bengali just because most of the catalog skews Bangladeshi&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Getting this wrong (defaulting everything to Bengali) was a mistake I made and had to correct — a generic no-brand spice doesn't need a Bangladeshi label just because the store's core customer base is Bangladeshi.&lt;/p&gt;

&lt;h3&gt;Problem 3: The import that silently never happened&lt;/h3&gt;

&lt;p&gt;At one point I discovered a batch of 20+ product descriptions — fully written, reviewed, ready — that had simply never made it live. The CSV existed. The work was done. But re-checking a later store export showed the same products still blank. Somewhere between "file delivered" and "product live," an import step had failed silently.&lt;/p&gt;

&lt;p&gt;The fix was procedural, not technical: never assume a written batch is live. Cross-check every batch against the &lt;em&gt;next&lt;/em&gt; fresh store export before marking it done. I caught multiple recurrences of this same gap over the course of the project.&lt;/p&gt;

&lt;h3&gt;Problem 4: What's actually a duplicate&lt;/h3&gt;

&lt;p&gt;With a catalog this size, "duplicate" isn't binary. I ended up with three real categories:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
&lt;strong&gt;True duplicates&lt;/strong&gt; — same product, same weight, accidentally listed twice (delete/merge)&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;Size/weight variants&lt;/strong&gt; — same product, different sizes, that &lt;em&gt;should&lt;/em&gt; be WooCommerce product variations, not separate listings&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;False positives&lt;/strong&gt; — different products that just have similar names (a 100g and 500g mustard seed listing from two different unrelated brands, for instance) — these are not duplicates at all, and treating them as such would have removed real inventory&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Getting the third category wrong early on meant real products were being incorrectly flagged and held back from going live.&lt;/p&gt;

&lt;h3&gt;Problem 5: Setting up variations from zero&lt;/h3&gt;

&lt;p&gt;Since the store had never used &lt;a href="https://dev.to/t/ecommerce"&gt;WooCommerce variable products&lt;/a&gt;, I had to build the pattern from scratch on a real example (a tea brand sold in three sizes across four different old listing IDs, one of which was already a duplicate). That meant:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;picking one listing to become the "parent" variable product (keeping its URL for SEO continuity)&lt;/li&gt;
  &lt;li&gt;converting the others into variation rows&lt;/li&gt;
  &lt;li&gt;setting the old duplicate listing IDs to a non-published status&lt;/li&gt;
  &lt;li&gt;flagging that 301 redirects were needed from the old URLs to the new parent URL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That single conversion became the template for every subsequent multi-size product line.&lt;/p&gt;

&lt;h3&gt;What this actually looked like week to week&lt;/h3&gt;

&lt;p&gt;Not glamorous. Mostly:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Batches of 15–30 product descriptions at a time, grouped by category or origin&lt;/li&gt;
  &lt;li&gt;Every batch cross-checked against the live sitemap before adding &lt;a href="https://dev.to/t/webdev"&gt;internal links&lt;/a&gt; (never guessing a URL)&lt;/li&gt;
  &lt;li&gt;A running "unresolved duplicates" list that got triaged in bulk at the end rather than one at a time&lt;/li&gt;
  &lt;li&gt;A biweekly report covering hosting, SEO, Google Ads/Merchant Center, email, and video — because content work alone doesn't mean much if the site had a multi-day outage that quarter (it did — about 4–5 days of downtime that had to be factored into any traffic or sales analysis)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;The takeaway&lt;/h3&gt;

&lt;p&gt;None of the individual problems here are exotic — bad imports, unclear duplicates, missing variations, inconsistent claims. What made this project hard was scale plus the lack of any existing convention to fall back on: no prior variable products, no reliable &lt;a href="https://dev.to/t/seo"&gt;SEO plugin&lt;/a&gt; scores to audit against (Rank Math's fields were confirmed unreliable on this install and had to be ignored), and a catalog serving eight-plus language communities at once.&lt;/p&gt;

&lt;p&gt;The unglamorous fix, every time, was the same: don't guess, verify against the live site, and build the missing convention once so the next 100 products don't repeat the same decision from scratch.&lt;/p&gt;





&lt;p&gt;&lt;em&gt;Have you dealt with a WooCommerce catalog that grew faster than its data model? Curious how others have handled variable-product retrofits on a live store — drop your approach below.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>seo</category>
      <category>webdev</category>
      <category>wordpress</category>
    </item>
    <item>
      <title>5 Laravel Artisan commands I use every single day</title>
      <dc:creator>Sandra Sakura</dc:creator>
      <pubDate>Sun, 13 Sep 2026 11:55:27 +0000</pubDate>
      <link>https://dev.to/csandra_ericson/5-laravel-artisan-commands-i-use-every-single-day-4783</link>
      <guid>https://dev.to/csandra_ericson/5-laravel-artisan-commands-i-use-every-single-day-4783</guid>
      <description>&lt;h2&gt;5 Laravel Artisan commands I use every single day&lt;/h2&gt;

&lt;p&gt;If you're a Laravel dev, these five are probably burned into your terminal history too:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;&lt;code&gt;php artisan make:model Post -mfsc&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
    Model + migration + factory + seeder + controller, one command. No more typing five separate &lt;code&gt;make:&lt;/code&gt; commands like it's 2015.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;&lt;code&gt;php artisan tinker&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
    Need to test a query or poke at a relationship real quick? Tinker over spinning up a whole route, every time.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;&lt;code&gt;php artisan route:list --path=api&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
    Debugging a 404 or checking if middleware actually applied? This shows you instantly, no guessing.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;&lt;code&gt;php artisan queue:work --tries=3&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
    Can't run jobs without this. That &lt;code&gt;--tries&lt;/code&gt; flag has saved me from silently-failed jobs more than once.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;&lt;code&gt;php artisan optimize:clear&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
    Something "just not updating"? Config, cache, routes, views? This is step zero before real debugging even starts.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Drop your most-used Artisan command below — curious what I'm missing 👇&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>laravel</category>
      <category>php</category>
    </item>
  </channel>
</rss>
