Getting Started

Complete Guide to Updating Stock & Prices with Super Speedy Imports

Published · Last updated

This guide covers the most common use case: updating product stock levels and prices from a CSV file. Super Speedy Imports has an import mode built for exactly this job, which updates the fields you map on the products you already have and touches nothing else.


CSV Requirements

Your CSV needs just two things:

  1. A unique identifier to match existing products (usually SKU)
  2. The fields you want to update (stock, price, etc.)

Minimal CSV Example

SKU,Stock,Price
PROD-001,150,29.99
PROD-002,0,19.99
PROD-003,75,49.99

With Sale Prices

SKU,Stock,Regular Price,Sale Price
PROD-001,150,29.99,24.99
PROD-002,0,19.99,
PROD-003,75,49.99,39.99

A blank sale price cell means no sale, and clears any sale price the product had. Do not write 0 for “no sale”: 0 is a valid sale price and puts the product on sale for nothing.


Setting Up the Import

Step 1: Upload Your CSV

  1. Go to Super Speedy > Imports in your WordPress admin
  2. Expand Upload Files and click Browse
  3. Upload your CSV file and the New Import section will open
  4. Name your import and choose a Post Type (e.g., Products)

If you already have a CSV file uploaded, expand New Import, choose the CSV file from the dropdown, name your import and choose the post type.

Step 2: Map the SKU Field

In the Main section:

  • Map SKU to your SKU column

This is how the importer matches CSV rows to existing products.

Step 3: Map Stock & Price Fields

For stock updates:

  • Map Stock Qty to your stock column

For price updates:

  • Map Regular Price to your price column
  • Map Sale Price to your sale price column (if applicable)

Step 4: Leave Everything Else Unmapped

Don’t map Product Title, Description, or other fields – they won’t be changed if left unmapped. Only mapped fields are updated.

Step 5: Choose the Update Import Mode

For a daily price/stock feed, set What should this import do? in the Additional Options section to Only update prices & other item details (prices_only). This is the cheapest update path: it runs load-csv, match-existing, update-postmeta, insert-postmeta (to fill in metadata a product is missing), sync-variable-prices and the After Import tasks, and skips creating products, post-body updates and the image stages. It maps directly onto this use case – matching existing products by their unique identifier and writing the changed postmeta (_regular_price, _sale_price, _stock).

In this mode, when the file sets stock, the product’s out-of-stock catalogue visibility follows its new stock status. With WooCommerce’s Hide out of stock items from the catalog on, restocked products reappear in the shop and sold-out products disappear, as they do after a full import.

See Controlling which stages of an import actually run for the full list of presets and how to override them on a one-off CLI run.

Import modes and what each stage writes shows which fields this mode leaves alone, and how it differs from Only update existing items.

Step 6: Save the Import

Click Save to store your configuration. Note the Import ID shown in the URL (e.g., import_id=5) – you’ll need this for CLI and scheduled imports.


Running the Import

From the Admin Interface

  1. Click Run Import
  2. Monitor progress in the log output
  3. Important: Flush your object cache after completion (see below)

Measured speed

Measured with the WordPress.org build of version 3.40.0 on a 4-vCPU server, through the dashboard: 100,000 simple WooCommerce products imported in 81 seconds, 1,000 products with their images downloaded from a remote image host and resized in 105 seconds, and a price and stock update of 10,000 products in 11 seconds. Full details: Super Speedy Imports Lite 3.40.0 import speed.


How prices are written

Decimal marks

+ New Import reads the decimal mark from the file itself. It reads up to 500 data rows looking for prices, and the format most price cells use wins, so a European file with 12,99 prices is set to Decimal Point: Comma (,) whatever its field separator. The setting is under the advanced options of New Import if you need to change it.

A value that is clearly written in the other format is refused, not guessed at. Under a dot-decimal import, 12,99 and 1.234,50 are refused; under a comma-decimal import, 12.50 and 1,234.50 are refused. Currency symbols and spaces around the number are ignored. A value such as 1,234 under a dot-decimal import, where the other mark can only be a thousands separator, is accepted and read as 1234. A refused price:

  • leaves that product’s regular price, sale price and active price exactly as they were;
  • is reported against its CSV row and column, with the value and the decimal format that would read it;
  • does not stop the rest of the row, or the rest of the file, from importing. The run finishes with issues.

Blank prices

A blank cell in a mapped Regular Price column removes the product’s price, as clearing the price in WooCommerce does, so the product can no longer be bought at its old price. A price column that is not in the file, or not mapped, leaves the price alone.

Scheduled sales

To schedule a sale, map columns to the _sale_price_dates_from and _sale_price_dates_to meta keys. Columns named Date sale price starts and Date sale price ends, as the WooCommerce exporter names them, are mapped to those keys automatically. The dates are stored as WooCommerce stores them, read in the store’s timezone when they carry no offset. The sale price becomes the active price only while the import time is inside the sale dates; a sale that has ended or has not started yet leaves the regular price active, and WooCommerce starts and ends it on schedule. A date that cannot be read is imported as no date and reported as a warning against its row. A blank date cell clears that date.


Flushing the Object Cache

Critical: After updating stock and prices, you must flush your object cache for changes to appear on the frontend.

Why This Is Necessary

WooCommerce and WordPress cache product data in the object cache (Redis, Memcached, or similar). Without flushing, your site may display old prices and stock levels until the cache naturally expires.

Manual Flush

If using a caching plugin:

  • WP Redis: Go to Settings > Redis and click “Flush Cache”
  • Object Cache Pro: Dashboard widget or Settings > Object Cache Pro
  • W3 Total Cache: Performance > Dashboard > Empty All Caches
  • LiteSpeed Cache: LiteSpeed Cache > Toolbox > Purge All

CLI Flush

wp cache flush

Using the CLI

The CLI is the recommended way to run imports, especially for large datasets or automated workflows.

Basic Import Command

wp ssi <import_id>

Example:

wp ssi 5

Import with Cache Flush

Chain the commands to run the import and flush the cache in one go:

wp ssi 5 && wp cache flush

Using an Alternative CSV File

Use the --file parameter to run an import with a different CSV file:

wp ssi 5 --file="latest-stock.csv"

The file path is relative to wp-content/uploads/super-speedy-imports/. The CSV must have the same column headers as the original.

Full Example Script

#!/bin/bash
cd /var/www/html

# Run the stock & price update import
wp ssi 5

# Flush object cache
wp cache flush

# Optional: Clear page cache if using a caching plugin
wp litespeed-purge all

echo "Import complete and caches flushed"

Downloading from FTP

If your stock/price file is provided by a supplier or ERP system via FTP, you can download it before running the import.

Using wget

wget -O /var/www/html/wp-content/uploads/super-speedy-imports/stock-update.csv \
    ftp://username:password@ftp.supplier.com/exports/stock.csv

Using curl

curl -o /var/www/html/wp-content/uploads/super-speedy-imports/stock-update.csv \
    ftp://username:password@ftp.supplier.com/exports/stock.csv

Using lftp (for more complex scenarios)

lftp -u username,password ftp.supplier.com -e "get /exports/stock.csv -o /var/www/html/wp-content/uploads/super-speedy-imports/stock-update.csv; quit"

SFTP Download

scp user@sftp.supplier.com:/exports/stock.csv \
    /var/www/html/wp-content/uploads/super-speedy-imports/stock-update.csv

Or using sftp with a password (via sshpass):

sshpass -p 'password' sftp user@sftp.supplier.com:/exports/stock.csv \
    /var/www/html/wp-content/uploads/super-speedy-imports/stock-update.csv

Complete Download + Import Script

#!/bin/bash

# Configuration
WP_PATH="/var/www/html"
CSV_FILE="stock-update.csv"
CSV_PATH="$WP_PATH/wp-content/uploads/super-speedy-imports/$CSV_FILE"
FTP_URL="ftp://username:password@ftp.supplier.com/exports/stock.csv"
IMPORT_ID=5

cd "$WP_PATH"

# Download latest file from FTP
echo "Downloading stock file from FTP..."
wget -q -O "$CSV_PATH" "$FTP_URL"

if [ $? -ne 0 ]; then
    echo "Error: Failed to download file from FTP"
    exit 1
fi

echo "Download complete. Running import..."

# Run the import with the downloaded file
wp ssi $IMPORT_ID --file="$CSV_FILE"

if [ $? -ne 0 ]; then
    echo "Error: Import failed"
    exit 1
fi

# Flush caches
echo "Flushing caches..."
wp cache flush

echo "Stock and price update complete!"

Save this as /home/user/scripts/update-stock.sh and make it executable:

chmod +x /home/user/scripts/update-stock.sh

Scheduling with Crontab

Automate your stock and price updates to run on a schedule using crontab.

Edit Crontab

crontab -e

Schedule Examples

Every hour:

0 * * * * /home/user/scripts/update-stock.sh >> /var/log/stock-update.log 2>&1

Every 6 hours:

0 */6 * * * /home/user/scripts/update-stock.sh >> /var/log/stock-update.log 2>&1

Daily at 6 AM:

0 6 * * * /home/user/scripts/update-stock.sh >> /var/log/stock-update.log 2>&1

Twice daily (6 AM and 6 PM):

0 6,18 * * * /home/user/scripts/update-stock.sh >> /var/log/stock-update.log 2>&1

Every 15 minutes (high-frequency stock updates):

*/15 * * * * /home/user/scripts/update-stock.sh >> /var/log/stock-update.log 2>&1

Complete Crontab Script with Logging

Create a more robust script with timestamps and error handling:

#!/bin/bash

# /home/user/scripts/update-stock.sh

# Configuration
WP_PATH="/var/www/html"
CSV_FILE="stock-update.csv"
CSV_PATH="$WP_PATH/wp-content/uploads/super-speedy-imports/$CSV_FILE"
FTP_URL="ftp://username:password@ftp.supplier.com/exports/stock.csv"
IMPORT_ID=5
LOG_FILE="/var/log/ssi-stock-update.log"

# Timestamp function
timestamp() {
    date "+%Y-%m-%d %H:%M:%S"
}

cd "$WP_PATH"

echo "$(timestamp) - Starting stock update" >> "$LOG_FILE"

# Download file
wget -q -O "$CSV_PATH" "$FTP_URL"
if [ $? -ne 0 ]; then
    echo "$(timestamp) - ERROR: FTP download failed" >> "$LOG_FILE"
    exit 1
fi
echo "$(timestamp) - Downloaded CSV from FTP" >> "$LOG_FILE"

# Run import
wp ssi $IMPORT_ID --file="$CSV_FILE" >> "$LOG_FILE" 2>&1
if [ $? -ne 0 ]; then
    echo "$(timestamp) - ERROR: Import failed" >> "$LOG_FILE"
    exit 1
fi
echo "$(timestamp) - Import completed successfully" >> "$LOG_FILE"

# Flush cache
wp cache flush >> "$LOG_FILE" 2>&1
echo "$(timestamp) - Cache flushed" >> "$LOG_FILE"

echo "$(timestamp) - Stock update complete" >> "$LOG_FILE"
echo "---" >> "$LOG_FILE"

Monitoring the Log

View recent log entries:

tail -50 /var/log/ssi-stock-update.log

Watch the log in real-time:

tail -f /var/log/ssi-stock-update.log

Crontab with Email Notifications

To receive email notifications on errors, ensure your server has mail configured and add:

MAILTO=admin@yourstore.com
0 */6 * * * /home/user/scripts/update-stock.sh >> /var/log/stock-update.log 2>&1

Troubleshooting

Prices Not Updating on Frontend

  1. Check that you flushed the object cache
  2. Clear any page caching (LiteSpeed, Varnish, Cloudflare, etc.)
  3. Check browser cache (try incognito mode)

Products Not Matching

  1. Verify SKUs in your CSV match your stored SKUs. Whether case matters (ABC-123 vs abc-123) depends on your database collation – the default WordPress collation (utf8mb4_unicode_520_ci) is case-insensitive, so those match; a custom case-sensitive collation would treat them as different. When in doubt, normalise to one case in your CSV.
  2. Check for leading/trailing spaces in the SKU column (these are matched byte-for-byte and will prevent a match)

FTP Download Failing

  1. Test the FTP connection manually first
  2. Check firewall rules allow outbound FTP
  3. For passive FTP issues, try wget --passive-ftp

Cron Not Running

  1. Check cron is running: systemctl status cron
  2. Verify script permissions: chmod +x script.sh
  3. Test script manually first
  4. Check cron logs: grep CRON /var/log/syslog

Next Steps

Written for Super Speedy Imports 3.40.0.

Comments

▲
▼
1/1