A simple guide for merchants and developers
This guide explains, step-by-step, how to install and set up your Shopify PLP personalization app (powered by Webon) so it can:
- Automatically re-order products on collection / PLP pages
- Track anonymous session behavior with a pixel
- Inject personalized product cards into your collection template via an app proxy
It’s written for non-technical merchants and technical theme developers.
1. What the App Does (High Level)
Once installed, the app:
- Reads your Shopify order and catalog data to understand what sells and how.
- Drops a pixel on your storefront that tracks anonymous click and browse events per session.
- Uses this session and order data to decide which products should appear at the top of your PLPs/collections.
- Injects product cards back into your collection page via a Shopify app proxy, using a small Liquid + JavaScript snippet.
No personally identifiable information (PII) is collected unless you explicitly configure it to do so in your merchant settings.
2. Installing the App from the Shopify App Store
- Go to the Shopify App Store and find the app.
- Click Add app and follow Shopify’s standard install flow.
- Review the requested permissions and click Install app to give consent.
After installation, the app will immediately:
- Start reading product and order data from your store
- Install a tracking pixel that listens to storefront events
3. Initial Data Sync and Indexing (1–2 hours)
Once installed, the app needs a bit of time to get ready:
- If you have many products, the first indexing run can take 1–2 hours, sometimes more on very large catalogs.
- During this time, the app imports product and order data and builds an internal index for sorting and personalization.
You don’t need to do anything while this runs. Just keep the app installed and your store active.
4. Let the Pixel Learn: Session Data Collection
As soon as the app is installed:
- A custom pixel and cookie are added to your storefront.
- The pixel collects click and view events: which products were clicked, which collections were visited, what pages users browsed, etc.
- Each session is tied to a session key stored in a browser cookie (no PII by default).
For best results:
- Let the app run for a few days so it can collect enough session data before you rely heavily on personalization.
- The more real sessions you collect, the better the app can reorder PLPs in a meaningful way.
You’ll be able to access this session behavior data from the app’s backend inside Shopify admin for manual inspection and pattern recognition.
5. Using Auto-Sort from the App Home Page
Once your initial data sync is done:
- Go to Apps → Playground in Shopify admin.
- On the home screen of the app, you’ll see options for:
- Auto-sort rules
- Vendor-based placement
- Custom sort orders based on price or behavior
You can start configuring these rules immediately.
However, for front-end personalization on the live PLP, you also need to integrate a small Liquid snippet into your theme.
6. Theme Integration Overview (For Developers)
To render personalized products on the collection page using the app proxy:
- Create a new Liquid snippet (recommended) called something like:
collection-playground.liquid - Paste the provided HTML, CSS, and JavaScript into that snippet.
- Include the snippet in your collection template before the main product loop.
- The snippet will:
- Read the
webon_session_keycookie - Call the Shopify app proxy endpoint (
/apps/sproxy) - Fetch personalized product HTML from the Webon servers
- Inject that HTML into the
#product-gridelement - Remove duplicates and hide the loader when done
- Read the
⚠️ Note: The code below is a reference implementation based on the Dawn theme structure. You may need to adapt selectors and classes for your custom theme. It is also strongly recommended to create your own collection template and not edit the core template when working with this personalization product cards
7. Step-by-Step: Create the collection-playground.liquid Snippet
In your Shopify admin:
- Go to Online Store → Themes.
- Click … → Edit code on the theme you want to customize.
- Under Snippets, click Add a new snippet.
- Name it:
collection-playground.
This createssnippets/collection-playground.liquid. - Paste the following code into that file and save:
<div class="loader-overlay webonElement">
<div class="loader"></div>
</div>
{%- style -%}
.product-grid-container {
position: relative;
}
.loader-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #fff; /* white background hides any shifts */
z-index: 999;
display: flex;
align-items: center;
justify-content: center;
transition: opacity 0.3s ease;
}
.loader {
width: 40px;
height: 40px;
border: 4px solid rgba(0, 0, 0, 0.1);
border-top-color: #333;
border-radius: 50%;
animation: spin 1s linear infinite;
display: block !important;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
{%- endstyle -%}
<script type="text/javascript">
function getCookie(name) {
const cookies = document.cookie.split('; ');
for (let cookie of cookies) {
let [key, value] = cookie.split('=');
if (key === name) {
return decodeURIComponent(value);
}
}
return null; // Return null if the cookie does not exist
}
const wsk = getCookie("webon_session_key");
const container = document.getElementsByClassName("product-grid-container")[0];
const overlay = container.querySelector(".loader-overlay");
const params = new URLSearchParams(window.location.search);
if (params.has('page')) {
overlay.style.opacity = 0;
overlay.style.display = "none";
}
console.log('wsk:',wsk)
if(wsk && !params.has('page')) {
let cid = {{ collection.id }}
const productGrid = document.getElementById("product-grid");
// Show overlay/spinner
overlay.style.display = "flex";
fetch('/apps/sproxy?collection_id=' + cid + '&wsk=' + encodeURIComponent(wsk))
.then((res) => res.text())
.then((data) => {
// Create a new DOMParser instance
const parser = new DOMParser();
// Parse the string into an HTML Document
const doc = parser.parseFromString(data, "text/html");
// Query the <main> tag in the parsed document
const mainTag = doc.querySelector("main");
// If a <main> tag exists, get its innerHTML; otherwise, fall back to the full data
const innerContent = mainTag ? mainTag.innerHTML : '';
//console.log(innerContent)
// existing Product Grid
const existingGrid = document.getElementById("product-grid").innerHTML;
document.getElementById("product-grid").innerHTML = "";
document.getElementById("product-grid").innerHTML= innerContent + existingGrid;
document.querySelectorAll("#product-grid .grid__item.scroll-trigger--offscreen").forEach(el => el.classList.remove("scroll-trigger--offscreen"));
})
.catch((error) => {
console.error("Error fetching or parsing content:", error);
})
.finally(() => {
// grab all the <li> items under #product-grid
const items = document.querySelectorAll('#product-grid li');
const seen = new Set();
items.forEach(li => {
const id = li.getAttribute('data-product-id');
if (seen.has(id)) {
// duplicate → hide it
li.style.display = 'none';
} else {
// first time → keep and mark as seen
seen.add(id);
}
});
// Remove the loader regardless of success or failure
// The fade-out transition will help make it seamless.
setTimeout(() => {
overlay.style.opacity = 0;
overlay.style.display = "none";
}, 300);
});
}
</script>
What this does:
- Shows a loader overlay over the product grid
- Reads the Webon session cookie
- Calls the app proxy to fetch personalized products for that collection
- Injects the returned HTML into
#product-grid - Removes duplicate products and hides the loader
Again: treat the CSS/JS as reference; adapt selectors to match your theme if needed.
8. Include the Snippet in Your Collection Template
Now you need to tell the collection template to run that snippet before the product loop.
- In Edit code, open your main collection template or section.
For Dawn, this is often something like:sections/main-collection-product-grid.liquidor similar. - Find the
ulwith IDproduct-gridand the main productforloop. - Insert this line just before the
<ul id="product-grid" ...>or before the productforloop:
{% render 'collection-playground' %}
- Also do not forget to update in the product grid loop’s item li element to add
data-product-id="{{ product.id }}"this will remove duplicate products if there are any on the same collection page and selected as top products as well as per the JS code.
For example, you might end up with something like:
{% render 'collection-playground' %}
<ul
id="product-grid"
data-id="{{ section.id }}"
class="
grid product-grid grid--{{ section.settings.columns_mobile }}-col-tablet-down
grid--{{ section.settings.columns_desktop }}-col-desktop
{% if section.settings.quick_add == 'bulk' %} collection-quick-add-bulk{% endif %}
"
>
{% assign skip_card_product_styles = false %}
{%- for product in collection.products -%}
<li
class="grid__item{% if settings.animations_reveal_on_scroll %} scroll-trigger animate--slide-in{% endif %}"
data-product-id="{{ product.id }}"
>
...
{%- endfor -%}
</ul>
The app proxy will now prepend personalized product cards into #product-grid while the original loop remains as a fallback.
9. Default Product Card Rendering (Dawn Example)
On the server side, the app returns product cards as HTML. A typical default implementation for the Dawn theme looks like this:
{%- for product_handle in product_handle_array -%}
<li data-product-id="{{ all_products[product_handle].id }}" class="grid__item scroll-trigger animate--slide-in">
{%
render 'card-product',
card_product: all_products[product_handle]
%}
</li>
{%- endfor -%}
You can customize this markup:
- Use a different snippet instead of
'card-product' - Add custom classes or badges (e.g. “Sponsored”, vendor logo, etc.)
- Align with your own grid markup and theme structure
All of this is configurable under your Playground App Settings / product card settings in the app.
10. Customization, Support, and Limits
- This guide and the provided code are reference implementations based on a standard Shopify theme structure (e.g. Dawn).
- If your theme uses a very different DOM structure or grid layout, you’ll need to adapt:
- The CSS selectors (e.g.
.product-grid-container,#product-grid) - Where the snippet is placed in your template
- The CSS selectors (e.g.
- For custom installation help, you can contact the dev team at: [email protected]
- Free users get the app as-is and can follow this guide to self-install and self-configure. Custom engineering work may require a paid engagement.
11. Summary
For non-technical merchants:
- Install the app from the Shopify App Store.
- Wait 1–2 hours for initial sync.
- Let the pixel run for a few days to collect session data.
- Ask your developer (or theme partner) to follow the snippet integration steps above.
- Then start configuring auto sort rules in the app.
For developers:
- Create
snippets/collection-playground.liquidwith the provided code. - Include
{% render 'collection-playground' %}before the#product-gridloop. - Make sure the selectors match your theme.
- Adjust the product card snippet markup to fit your store’s design.
Once everything is wired up, your PLPs will automatically pull in personalized, session-aware product ordering from Webon’s servers via the Shopify app proxy, giving each shopper a smarter, data-driven collection page.

Leave a Reply