Skip to content

Guides

Each of these is a job rather than a screen. The quick start builds a first Google feed; these are the things you do after that.

Sell the same catalogue on Meta as well

A feed is one channel, so Meta is a second feed, and most of the work is already done, because the category mapping belongs to the store and language rather than to the feed.

  1. Press + on the feed list, choose Meta, the same store and the same language, and Continue.
  2. Open the Categories tab and check the banner: it should say how many other feeds draw on this mapping. Nothing to do here: Meta is sent the same placements as Google, as the full path rather than the numeric id.
  3. Open the Fields tab and clear the red badge. Meta's required set is wider than Google's in two places, and both are Meta's rule rather than ours: brand is required, so a product with no manufacturer set needs a fallback, and condition is required, which OpenCart has no column for at all, so map nothing and give it a fallback of new.
  4. Save, switch the feed on, and paste its URL into Commerce Manager as a scheduled feed.

Duplicate is for a second feed on the same channel (the same mapping over a different filter set, or the same channel for a second store), because the channel a feed is for cannot be changed once it exists.

Check a feed before you generate it

Press the eye button on the feed's row, or on the feed form. Preview shows the first 25 products this feed carries as the channel's own fields, in the channel's own order (g:id, g:title, g:price and the rest), so you can read a row the way Google will read it.

Above the table are two numbers you want to see before a channel reports them:

  • How many products reach this feed, against how many the store and language have at all. If your filters have taken a catalogue of four thousand down to eleven, that sentence is where you find out.
  • How many of the rows below the channel would refuse for a required field that resolved to nothing. Those rows are shown rather than dropped, with the offending cell marked, because the row you came here to find is the broken one. That count is over the rows shown, not over your whole catalogue. Counting the whole catalogue means assembling it, which is generating the feed.

Preview writes nothing. No run is opened, no file is touched, and the feed your channel is being served is as it was, so it is safe to press on a live feed, including one a schedule is about to regenerate.

It reads the feed as it was saved, so save the form before previewing. While you are still editing a mapping, the Fields tab is the faster loop: it resolves the field you are on against a few of your own products without leaving the form.

Send only part of your catalogue to a channel

Open the feed's Filters tab. It has four lists. Ticking nothing on a list means that list restricts nothing:

  • Categories: only products in one of the categories you tick. A product in several of them is still one row.
  • Brands: only products by the manufacturers you tick. Products with no manufacturer set are left out entirely, which is what ticking brands means.
  • Stock status: the wording a product shows when it is out of stock, not whether it is in stock. Tick Pre-Order here and you get the products marked pre-order, however many of them you have.
  • Price: your catalogue price, before any special. A range that moved as specials came and went would drop products out of the feed and back in, which channels read as delisting.

To take a category, a brand or a single product out of what these lists let in, see leave categories, brands or products out of a feed.

A price range whose lowest is above its highest is refused when you save, because no product could reach the feed.

Leave categories, brands or products out of a feed

You want everything except: the whole catalogue but the clearance category, one brand but three of its products, or a master product that is only a template for its variants.

  1. Open the feed's Filters tab.
  2. To leave out a category or a brand, tick Leave out on its row, beside the tick that includes it. Leave the include tick alone: ticking both on one row is refused when you save, because leaving out would win and the include tick would do nothing.
  3. To leave out individual products, type a name under Leave out these products and pick it. Each product you pick shows as a chip; press its × to take it off the list.
  4. Save, and preview the feed: the count above the table says how many products now reach it.

Leaving out wins over everything the include-lists let in. A category is left out exactly as ticked, so leaving out Laptops leaves Laptops > Gaming in until you tick that too. Leaving out a brand keeps the products with no brand. Up to 1,000 products can be named; past that, leave out their category or their brand instead. A product you delete from your catalogue drops off the list the next time you save.

The product search reads OpenCart's own product list, so your user group needs Access Permission on catalog/product; installing says where.

Leaving out costs nothing extra: it is part of the one statement that already reads each batch of products.

Group variant products for Google and Meta

You sell a T-shirt in three colours as a master product with three variants made with Add Variant, and you want the channel to show it as one product in three colours rather than three unrelated T-shirts.

  1. Open the feed's Fields tab.
  2. Map item_group_id from Master product ID (variants only). Every variant of one master now sends that master's id.
  3. Map color and size (or whichever of the channel's fields your variants differ by) from the matching entry under Variant options, one per option your store has. A variant sends the value chosen for it: Red, or Red / Blue where a checkbox option has two ticked.
  4. Check id. It has to be Product ID, or a Model you gave each variant yourself, because OpenCart copies the master's model onto every variant it makes and a channel reads a repeated id as one product sent several times.
  5. Save, and read the pane for a variant and for its master before you generate.

The master sends no item_group_id and no option value, because it has none of its own. If it is a template nobody buys rather than a product in its own right, leave it out by name, or Google will read it as a separate product with no colour.

A product that is not a variant sends nothing for these fields, so give them a fallback only if every such product should send the same value.

While any field is mapped from Variant options, generating costs two more database queries per batch of products (500 at a time, 100 with Conserve resources on), for the whole batch rather than per product. The preview and the Fields tab pay the same.

Send the price including tax

Your storefront shows prices including VAT, and the channel wants the price a shopper is charged.

  1. Open the feed's Fields tab.
  2. Map price from Price including tax instead of Price.
  3. If you send a sale price, map sale_price from Special price including tax, so the two agree.
  4. Save, and check the pane against a product page on your storefront, as a shopper who is not logged in.

The tax is your store's own rates for each product's tax class, worked out at the feed store's own address under its Use Store Tax Address setting. There is no setting for another country: a feed for another market is priced as your own storefront prices it.

To send the prices in another currency as well, open the General tab, pick the Currency and tick Convert prices into this currency. Every price is then multiplied by that currency's rate under System → Localisation → Currencies, after tax. Keep that rate current, by hand or with your store's currency auto-update, because the feed uses exactly what is there. Without the tick, the currency is only the code your numbers are sent with. If the store has no rate for the feed's currency, the run fails and the previous file keeps serving until you fix it.

While a price is mapped from a tax source, a run costs two or three more database queries to read your store's address and rates, and one more while conversion is on. A scheduled or command-line run reads them once. A run started from the button reads them again on every slice, because each slice is a request of its own; a slice is up to ten seconds' work, so that is a few queries per slice rather than per product. The price filter on the Filters tab still reads your catalogue price, before tax and conversion.

Regenerate a feed from the command line

The command line is useful for three things: an exact time that OpenCart's four cycles cannot express, a deploy pipeline that has to know whether the feed came out, and any store on OpenCart 4.1.0.4, where it is the only scheduler that works.

From the store's own directory:

php extension/product_feed/product_feed.php --feed 3
php extension/product_feed/product_feed.php --due

--feed regenerates that one feed to the end, whatever its schedule says. The feed's id is the one the admin's feed list edits. --due regenerates every feed its own cycle says is due, which is what the hourly scheduler does, and is the form to put in a crontab line for a time of your own:

10 3,15 * * 1-5 cd /path/to/store && php extension/product_feed/product_feed.php --due

There is a third command, --cron, and it is the one to use when what you want is the store's own schedule rather than a time of your own: on a host that does not call OpenCart's cron.php, or on OpenCart 4.1.0.4, where the store's own scheduler cannot run:

10 * * * * cd /path/to/store && php extension/product_feed/product_feed.php --cron

It runs the same job OpenCart's scheduler would have run rather than a second copy of it: the runs are recorded as scheduled rather than as yours, the module's own switch is honoured, and it prints nothing when it worked, because cron emails you whatever a job prints. See running the scheduled pass yourself.

--feed and --due exit 0 when the feeds they were asked for were generated and 1 for anything else: a failed run, a feed id that does not exist, a command it does not recognise. That way a pipeline cannot go green on a feed that never regenerated. --cron is the exception, and exits 1 only when it could not reach the scheduled job at all.

--due skips a feed the scheduler is already generating rather than starting a second run on it; --feed joins that run and drives it to the end. Either way one feed is only ever built once at a time. Failures are printed and also written to your store's error log, because a crontab line's output goes somewhere nobody reads.

Give a feed a new URL

Press New URL on the feed's row, or on the General tab. The old URL stops serving at once, so the channel is being refused until you paste the new one into its dashboard. Do the two together.

Do this if the URL has been in an email thread, a screenshot or a support ticket. It is not needed after an update: your tokens survive one.

Microsoft Advertising feeds have no URL and no token, so there is nothing to rotate: you download the file and upload it yourself.

Pause a feed without losing its configuration

Two switches, and they mean different things:

  • Regenerate on schedule, off, keeps the cycle and stops it running. This is how you pause a feed for a fortnight.
  • Status, off, also stops the schedule regenerating it, and stops its URL serving: a channel fetching it gets Not found until you switch it back on, when the file it last wrote is served again. To pause regenerating while the channel keeps reading the last file, use Regenerate on schedule instead.

For a channel you have finished with, switch the feed off rather than deleting it. If you do delete it, your category mapping stays behind for the other feeds on that store and language.

Work out why a product is not in the feed

In order, because the cheap answers are first:

  1. Is the product enabled, and in this feed's store? A disabled product is never in a feed.
  2. Do the feed's filters let it through? It has to pass every axis you have set something on, and not be left out by name or by a category or brand ticked Leave out, which wins over every other tick.
  3. Does it have every required field? Open the Fields tab, click each required field, and read the pane: it resolves against your own products and names the ones that come out empty. A product missing a required value is left out of the feed and counted in the regenerate message. If the product is among the feed's first 25, Preview marks the failing cell on its row outright.
  4. Was it added part-way through the last run? A run walks your catalogue by product id in order, so a product added below the point the run had reached goes in on the next run rather than that one.

Look after a store on shared hosting

Tick Conserve resources in the settings card at the top of the Product Feed screen. Feeds then generate in smaller slices with a rest between them: slower, and much less likely to have your host cut the request off. It applies to every feed the store runs, because the resource being conserved is the server's.

Nothing else about generation changes: the file that comes out is the same file.

Runs kept per feed, on the same card, is how much run history each feed keeps. A small host generating hourly may want fewer than the default twenty.