Setting Up miniShop2 for an Online Store on MODX
miniShop2 is an e-commerce component for MODX Revolution developed by the Bezumkin team. It integrates seamlessly into MODX architecture: products are resources with additional fields, cart and orders are component-specific tables. The result is a catalog managed through the familiar MODX manager, not a separate admin panel.
Installation via Package Manager
Extras → Package Management → Search: miniShop2 → Download → Install
miniShop2 installs several components:
-
miniShop2— main component (products, orders, categories) -
pdoTools— optimized snippets for data output (required dependency) -
mSearch2— search and filtering (recommended) -
msOptionsPrice2— options affecting price (recommended)
After installation, new resource types appear in the context menu: "miniShop2 Product" and "miniShop2 Category".
Catalog Structure
MODX resources form a tree structure, which miniShop2 uses directly:
Catalog (msCategory)
├── Chairs (msCategory)
│ ├── Black Office Chair (msProduct)
│ └── Executive Chair (msProduct)
└── Tables (msCategory)
└── Corner Table (msProduct)
Creating a category:
Resources → Create Resource → Type: miniShop2 Category
→ Title: Chairs
→ Alias: chairs
→ Published: Yes
→ miniShop2 Tab: product display settings
Creating a product:
Inside category → Create Resource → Type: miniShop2 Product
→ Title, alias, description
→ "Product" Tab:
Price: 1499.00
Old Price: 1999.00
Article: CHAIR-BLK
Weight: 12.5
Quantity: 25
→ Gallery: upload images
→ Options: Color, Size
Catalog Output via Snippets
miniShop2 uses pdoTools snippets for data output. Product list output:
[[!msProducts?
&parents=`15`
&tpl=`tpl.msProduct.row`
&limit=`24`
&sortby=`{"price":"ASC"}`
&where=`{"msProduct.price:>":0}`
&includeTVs=`color,size`
]]
The tpl.msProduct.row template is a Chunk with placeholders:
<div class="product-card">
<a href="[[+uri]]">
<img src="[[+thumb]]" alt="[[+pagetitle]]">
</a>
<div class="product-title">[[+pagetitle]]</div>
<div class="product-price">
[[+old_price:notempty=`<span class="old-price">[[+old_price]] rubles</span>`]]
<strong>[[+price]] rubles</strong>
</div>
<button class="ms2_add_to_cart" data-id="[[+id]]">Add to Cart</button>
</div>
The &parents parameter is the ID of the parent category resource or comma-separated list of IDs. &includeTVs includes additional TV-fields in the output.
Product Options (msOptionsPrice2)
Options are attributes that affect price, article, and inventory:
Extras → msOptionsPrice2 → Options → Create
→ Name: Color
→ Type: select
→ Values:
Black [key=BLK, mod=0]
White [key=WHT, mod=0]
Red [key=RED, mod=150] ← $150 surcharge
Binding options to a product is done through the "Options" tab in the product editor. For each option combination, a separate article and quantity can be set.
JavaScript handler for option changes (built into miniShop2):
// miniShop2 automatically updates price on option change
// via AJAX request to ms2/product/options/get processor
document.addEventListener('ms2_options_changed', function(e) {
const { price, old_price, count } = e.detail
document.querySelector('.product-price').textContent = price + ' rubles'
})
Cart and Order Checkout
The cart is managed via AJAX calls to miniShop2 processors:
// Add to cart
fetch('/assets/components/minishop2/index.php', {
method: 'POST',
body: new URLSearchParams({
action: 'cart/add',
id: productId,
count: 1,
options: JSON.stringify({ color: 'BLK' })
})
})
.then(r => r.json())
.then(data => {
if (data.success) {
updateCartCounter(data.data.total_count)
}
})
Checkout form:
[[!msCart?
&tpl=`tpl.msCart`
]]
[[!msOrder?
&tpl=`tpl.msOrder`
&deliveries=`1,2,3`
&payments=`1,2`
]]
The msOrder snippet displays a form with delivery and payment selection and processes checkout via JavaScript + AJAX.
Shipping and Payment
miniShop2 → Shipping → Create
→ Name: Courier Delivery
→ Cost: $300
→ Free from: $2000
→ Description: City delivery 1–2 business days
miniShop2 → Payments → Create
→ Name: Bank Card
→ Class: msPaymentRobokassa (requires separate package)
→ Settings: login, password1, password2, test mode
For courier services, parcel services, or postal services — separate packages are installed:
Package Management → Search: msCdek → Download → Install
→ miniShop2 → Shipping → CDEK
→ Enter API key and sender city
Order Statuses
miniShop2 comes with basic statuses: New, Paid, Completed, Cancelled. Custom statuses:
miniShop2 → Statuses → Create
→ Name: Handed to Shipping Service
→ Color: #2196F3
→ Customer Notification: Yes (email template)
Change status programmatically:
// In a plugin or snippet
$order = $modx->getObject('msOrder', $orderId);
$order->set('status', 4); // Custom status ID
$order->save();
// Send notification (miniShop2 does this automatically via events)
$modx->invokeEvent('msOnChangeOrderStatus', [
'order' => $order,
'status' => 4,
]);
Filtering and Search (mSearch2)
mSearch2 provides faceted search across the catalog:
[[!mFilter2?
&filters=`price||ms|numrange,color||ms|select,size||ms|select`
&tpl=`tpl.Filter`
&parents=`15`
&element=`msProducts`
&sortby=`{"price":"ASC"}`
]]
Filtering works via AJAX — updating the filter refreshes the product list without page reload.
For facet optimization — the ms2_properties field in the modx_ms2_products table is indexed:
ALTER TABLE modx_ms2_products ADD INDEX idx_price (price);
ALTER TABLE modx_ms2_products ADD INDEX idx_count (count);
Product Import
miniShop2 doesn't include an importer out of the box. Use additional components:
Package Management → Search: Commerce2 (or msImportExporter)
For large catalogs (thousands of products) — direct load script via MODX API:
// Batch import from CSV
$rows = array_map('str_getcsv', file($csvPath));
foreach ($rows as $row) {
$resource = $modx->newObject('msProduct');
$resource->fromArray([
'pagetitle' => $row[0],
'alias' => $modx->filterPathSegment($row[0]),
'parent' => $categoryId,
'published' => 1,
'class_key' => 'msProduct',
]);
$resource->save();
$product = $modx->getObject('msProductData', $resource->id);
$product->fromArray([
'price' => (float) $row[2],
'vendor' => $row[3],
'count' => (int) $row[4],
'article' => $row[5],
]);
$product->save();
}
SEO Configuration
miniShop2 products are MODX resources, so SEO works via standard means:
- Meta Title =
longtitleorpagetitleresource - Meta Description = TV-field
descriptionor built-in description
For meta tag auto-generation — use seoSuite plugin or pdoPage with custom templates.
URL structure for catalog is configured via System Settings:
System Settings → friendly_url: Yes
System Settings → friendly_alias_path: Yes
→ Catalog Resource → alias: catalog
→ Category: catalog/chairs
→ Product: catalog/chairs/black-office-chair
Implementation Timeline
- Component installation + basic setup: 1 day
- Catalog templates, product cards, cart: 3–5 days
- Shipping + payment setup: 1–2 days
- Product import from Excel/CSV: 1–2 days
- mSearch2 with faceted filtering: 2–3 days
- SEO + schema.org markup: 1 day
Total typical miniShop2 store: 1.5–2 weeks.







