Skip to content
ms3ProductSets
ms3ProductSets
Dynamic product recommendations for MiniShop3. Manual links, auto rules, manager templates
  • MODX 3
  • PHP 8.1
  • miniShop3
  1. Extras
  2. ms3ProductSets
  3. Integration and customization

Site integration ​

How to wire snippets in Fenom and standard MODX, and how to verify the result.

1. Load assets (required) ​

In the template (or shared head/footer), load lexicon first, then CSS and JS.

fenom
{'mspsLexiconScript' | snippet}
<link rel="stylesheet" href="{'assets_url' | option}components/ms3productsets/css/productsets.css">
<script src="{'assets_url' | option}components/ms3productsets/js/productsets.js" defer></script>
modx
[[!mspsLexiconScript]]
<link rel="stylesheet" href="[[++assets_url]]components/ms3productsets/css/productsets.css">
<script src="[[++assets_url]]components/ms3productsets/js/productsets.js" defer></script>

2. Block in the product card: “Frequently bought together” ​

After you add the call, a recommendations block should appear on the product card. If there are no products, the block is not shown.

fenom
{set $buyTogether = 'ms3ProductSets' | snippet : [
  'type' => 'buy_together',
  'resource_id' => $_modx->resource.id,
  'max_items' => 6,
  'tpl' => 'tplSetItem'
]}
{if $buyTogether != ''}
<section class="product-set">
  <h2>{'ms3productsets_type_buy_together' | lexicon}</h2>
  {$buyTogether}
</section>
{/if}
modx
[[!ms3ProductSets?
  &type=`buy_together`
  &resource_id=`[[*id]]`
  &max_items=`6`
  &tpl=`tplSetItem`
  &toPlaceholder=`msps_buy_together`
]]
[[+msps_buy_together:notempty=`
<section class="product-set">
  <h2>[[%ms3productsets_type_buy_together? &namespace=`ms3productsets` &topic=`default`]]</h2>
  [[+msps_buy_together]]
</section>
`]]

3. Auto recommendations by category ​

For home or landing when you need a block from a specific category.

fenom
{'ms3ProductSets' | snippet : [
  'type' => 'auto',
  'category_id' => 5,
  'resource_id' => 0,
  'max_items' => 8,
  'tpl' => 'tplSetItem'
]}
modx
[[!ms3ProductSets?
  &type=`auto`
  &category_id=`5`
  &resource_id=`0`
  &max_items=`8`
  &tpl=`tplSetItem`
]]

4. VIP set ​

  1. Fill system setting ms3productsets.vip_set_1 (1,2,3,...).
  2. Ensure products are published.
fenom
{'ms3ProductSets' | snippet : [
  'type' => 'vip',
  'set_id' => 1,
  'max_items' => 6,
  'tpl' => 'tplSetVIP'
]}
modx
[[!ms3ProductSets?
  &type=`vip`
  &set_id=`1`
  &max_items=`6`
  &tpl=`tplSetVIP`
]]

5. Empty result: hide block or show emptyTpl ​

Default hideIfEmpty=true returns an empty string.

fenom
{'ms3ProductSets' | snippet : [
  'type' => 'similar',
  'resource_id' => $_modx->resource.id,
  'hideIfEmpty' => false,
  'emptyTpl' => 'tplSetEmpty'
]}
modx
[[!ms3ProductSets?
  &type=`similar`
  &resource_id=`[[*id]]`
  &hideIfEmpty=`0`
  &emptyTpl=`tplSetEmpty`
]]

6. AJAX block render (JS API) ​

render() works the same. Templates differ in resource_id and container markup.

fenom
<div id="msps-auto"></div>
<script>
document.addEventListener('DOMContentLoaded', function () {
  if (window.ms3ProductSets) {
    window.ms3ProductSets.render('#msps-auto', {
      type: 'auto',
      category_id: 5,
      resource_id: {$_modx->resource.id},
      max_items: 8,
      tpl: 'tplSetItem'
    });
  }
});
</script>
modx
<div id="msps-auto"></div>
<script>
document.addEventListener('DOMContentLoaded', function () {
  if (window.ms3ProductSets) {
    window.ms3ProductSets.render('#msps-auto', {
      type: 'auto',
      category_id: 5,
      resource_id: [[*id]],
      max_items: 8,
      tpl: 'tplSetItem'
    });
  }
});
</script>

On pages without a current resource (home, and similar) pass resource_id: 0 or omit the field. See API.

7. “Add to cart” in set card ​

Button label from MiniShop3 lexicon (ms3_cart_add), same as chunk tplSetItem.

fenom
<button type="button" data-add-to-cart="{$id}" data-count="1">{'ms3_cart_add' | lexicon}</button>
modx
<button type="button" data-add-to-cart="[[+id]]" data-count="1">[[%ms3_cart_add? &namespace=`minishop3` &topic=`default`]]</button>

Stock tplSetItem is a MiniShop3 ms3_form, not data-add-to-cart. The example below is custom. productsets.js hits MiniShop3 Web API first (ms3Config.actionUrl). Connector add_to_cart is fallback.

8. “Add entire set” button ​

data-add-set adds all products in the set. Used in tplSetVIP and tplSetWrapper (when count > 0).

tplSetVIP / tplSetWrapper / tplPopcorn set data-msps-product-ids. JS reads that first, then [data-product-id] / [data-add-to-cart], then input[name="id"].

fenom
<button type="button" data-add-set="1">
  {'msproductsets_add_all_to_cart' | lexicon}
</button>
modx
<button type="button" data-add-set="1">
  [[%msproductsets_add_all_to_cart? &namespace=`ms3productsets` &topic=`default`]]
</button>

Use component lexicon (ms3productsets, topic default) for the label, not hard-coded text.

Post-integration checklist ​

  • The page loads mspsLexiconScript, productsets.css, and productsets.js.
  • Snippet ms3ProductSets is called with a valid resource_id or category_id.
  • Products are published and available in the current context.
  • For type vip, vip_set_1 is configured or manual set rows exist in the database.