Examples

Creating a Products For You Block

Learn how to create a Products For You Block in PersonalizeWP.

This guide will walk you through creating a personalized "Products For You" block using PersonalizeWP's REST API. This feature enhances user experience by showing tailored product recommendations based on visitor segments.

Overview

The "Products For You" block displays product recommendations specifically chosen for the current visitor based on their segment memberships. This implementation uses the /visitor-segments endpoint to retrieve the visitor's segments and then displays relevant products.

Prerequisites

  1. PersonalizeWP Pro installed and activated
  2. Segments properly configured in your PersonalizeWP dashboard
  3. Basic knowledge of JavaScript and WordPress development
  4. Access to your theme files or a custom plugin where you can add JavaScript code

Implementation Steps

Step 1: Create the HTML Structure

First, create the HTML structure for your "Products For You" block. You can add this to your theme or plugin as a snippet in a template or you can adapt it to use in a custom Block Editor block:

Products For You

Create a JavaScript function to fetch the visitor's segments and display recommended products from the PersonalizeWP REST API (you do not need to authenticate to the API from your own site):

NOTE: The UID is an obfuscated non-incrementing ID that is stored on the visitors local browser storage and specific to their interaction with your site.

function initProductsForYouBlock() { // Get the container element const container = document.getElementById('pwp-recommended-products-container');

// If the container doesn't exist, exit early if (!container) return;

// Fetch visitor segments and display recommended products fetchVisitorSegmentsAndProducts(container); }

async function fetchVisitorSegmentsAndProducts(container) { const PWP = localStorage.getItem('pwptrackeduser') || ''; const UID = (PWP) ? JSON.parse(PWP).id : null;

if (!UID) { container.closest('.pwp-products-for-you').style.display = 'none'; return; }

const baseURL = window.pwpSettings?.root || '/wp-json/'; const namespace = 'personalizewp/v1/'; const endpoint = 'visitor-segments';

try { const response = await fetch(${baseURL}${namespace}${endpoint}, { method: "POST", cache: "no-cache", headers: { "Accept": "application/json, /;q=0.1", "Cache-Control": "no-cache, private", "Content-type": "application/json", "X-Requested-With": "XMLHttpRequest", }, body: JSON.stringify({ uid: UID }), });

if (!response.ok) { throw new Error('Network response was not ok'); }

const segments = await response.json();

// If no segments, show default products or hide the container if (segments.length === 0) { showDefaultRecommendations(container); return; }

// Get product recommendations based on segments const recommendedProducts = await getProductRecommendations(segments);

// Display the products or fall back to defaults if none found if (recommendedProducts.length > 0) { displayRecommendedProducts(recommendedProducts, container); } else { showDefaultRecommendations(container); } } catch (error) { console.error('Error fetching visitor segments:', error); showDefaultRecommendations(container); } }

async function getProductRecommendations(segments) { // This function maps visitor segments to product recommendations // In a real implementation, you would have a more sophisticated mapping logic

// Example: Map segment IDs or types to product categories or tags const segmentProductMap = { 'high-value-customer': [101, 102, 103], // Product IDs for high value customers 'tech-enthusiast': [201, 202, 203], // Product IDs for tech enthusiasts 'fashion-lover': [301, 302, 303], // Product IDs for fashion lovers // Add more segment-to-product mappings as needed };

// Define priority segments (you might want to prioritize some segments over others) const prioritySegments = ['high-value-customer', 'new-visitor'];

// Find highest priority segment the visitor belongs to let targetSegment = null; for (const priority of prioritySegments) { if (segments.some(segment => segment.type === priority)) { targetSegment = priority; break; } }

// If no priority segment found, use the first segment if (!targetSegment && segments.length > 0) { targetSegment = segments[0].type; }

// Get product IDs for the target segment const productIds = segmentProductMap[targetSegment] || [];

// Fetch product data if (productIds.length > 0) { return await fetchProductsData(productIds); }

return []; }

async function fetchProductsData(productIds) { // This is a simplified example. In a real implementation, you would fetch // the product data from your WordPress site using REST API or AJAX.

// For WooCommerce, you might use the WC API: const baseURL = '/wp-json/wc/v3/products'; const queryParams = new URLSearchParams({ include: productIds.join(','), per_page: productIds.length // In production, add proper authentication });

const response = await fetch(${baseURL}?${queryParams}); return await response.json(); }

function displayRecommendedProducts(products, container) { // Clear the container container.innerHTML = '';

// Limit to 3 products for display const limitedProducts = products.slice(0, 3);

// Create and append product elements limitedProducts.forEach(product => { const productElement = createProductElement(product); container.appendChild(productElement); });

// Show the container container.closest('.pwp-products-for-you').style.display = 'block'; }

function showDefaultRecommendations(container) { // This function shows default product recommendations when no segments are found // or when the segments don't map to specific products

// You could fetch featured or popular products here, or hide the block

// Option 1: Hide the block // container.closest('.pwp-products-for-you').style.display = 'none';

// Option 2: Show featured products instead fetchFeaturedProducts().then(products => { if (products.length > 0) { displayRecommendedProducts(products, container); } else { container.closest('.pwp-products-for-you').style.display = 'none'; } }).catch(error => { console.error('Error fetching featured products:', error); container.closest('.pwp-products-for-you').style.display = 'none'; }); }

async function fetchFeaturedProducts() { // Fetch featured products as a fallback const baseURL = '/wp-json/wc/v3/products'; const queryParams = new URLSearchParams({ featured: true, per_page: 3 // In production, add proper authentication });

const response = await fetch(${baseURL}?${queryParams}); return await response.json(); }

// Helper function to create a product element function createProductElement(product) { const productDiv = document.createElement('div'); productDiv.className = 'pwp-product-item';

productDiv.innerHTML = `

${product.name}

${product.name}

${product.price_html}
`;

return productDiv; }

// Initialize the block when DOM is ready document.addEventListener('DOMContentLoaded', initProductsForYouBlock);

Step 3: Add CSS Styling

Add CSS to style your "Products For You" block:

.pwp-products-for-you { margin: 2rem 0; padding: 1.5rem; background-color: #f7f7f7; border-radius: 4px; }

.pwp-products-for-you h2 { margin-bottom: 1.5rem; font-size: 1.5rem; color: #333; text-align: center; }

.pwp-recommended-products { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 1.5rem; }

.pwp-product-item { border: 1px solid #eee; border-radius: 4px; padding: 1rem; background-color: white; transition: transform 0.2s, box-shadow 0.2s; }

.pwp-product-item:hover { transform: translateY(-3px); box-shadow: 0 5px 15px rgba(0,0,0,0.1); }

.pwp-product-image img { width: 100%; height: auto; object-fit: cover; border-radius: 3px; }

.pwp-product-title { margin: 0.5rem 0; font-size: 1rem; font-weight: 600; }

.pwp-product-price { color: #555; margin-bottom: 0.5rem; }

.pwp-add-to-cart { width: 100%; padding: 0.5rem; background-color: #3498db; color: white; border: none; border-radius: 3px; cursor: pointer; transition: background-color 0.2s; }

.pwp-add-to-cart:hover { background-color: #2980b9; }

Step 4: Enqueue Your Script and Styles

Add this to your theme's functions.php file or your custom plugin:

function pwpenqueueproductsforyouscripts() { // Enqueue on appropriate pages (home, shop, etc.) if (isfrontpage() || isshop() || isproductcategory()) { wpenqueuescript( 'pwp-products-for-you', gettemplatedirectory_uri() . '/assets/js/products-for-you.js', array('jquery'), '1.0.0', true );

wpenqueuestyle( 'pwp-products-for-you-styles', gettemplatedirectory_uri() . '/assets/css/products-for-you.css', array(), '1.0.0' );

// Pass the WordPress REST API root URL to JavaScript wplocalizescript( 'pwp-products-for-you', 'pwpSettings', array( 'root' => escurlraw(resturl()), 'nonce' => wpcreatenonce('wprest') ) ); } } addaction('wpenqueuescripts', 'pwpenqueueproductsforyouscripts');

Step 5: Add the Block to Your Theme

Insert the HTML structure in your theme's appropriate template file. For WooCommerce, you might add it to front-page.php , archive-product.php , or use a hook:

function pwpaddproductsforyou_block() { echo '<div class="pwp-products-for-you">

Products For You

‘; } add_action(‘woocommerce_before_shop_loop’, ‘pwp_add_products_for_you_block’, 5);

Result

When implemented correctly, your website will now display a "Products For You" block that shows personalized product recommendations based on the visitor's segments. This creates a tailored shopping experience that can significantly improve engagement and conversion rates.

Troubleshooting

If your "Products For You" block isn't working as expected:

  1. Check the browser console for JavaScript errors
  2. Verify that the visitor has a UID in local storage
  3. Test the API endpoint directly using the browser console
  4. Ensure your segment configuration is properly set up in PersonalizeWP
  5. Verify product data is being fetched correctly from WooCommerce

Common Issues and Solutions

Issue

Solution

Block shows no products

Check if the visitor belongs to any segments or adjust your fallback strategy

Products don't match expectation

Review segment mapping logic and ensure proper configuration

API errors

Verify endpoint URLs and authentication credentials

Performance concerns

Implement caching and limit API calls

Block appears on wrong pages

Review page condition logic in enqueue_scripts function

For additional help, please refer to the PersonalizeWP documentation or contact our support team.