project overview algolia
Brock Jungjohan
Created on November 19, 2024
Over 30 million people build interactive content in Genially.
Check out what others have designed:
QUOTE OF THE WEEK ACTIVITY - 10 WEEKS
Presentation
MASTER'S THESIS ENGLISH
Presentation
SPANISH: PARTES DE LA CASA WITH REVIEW
Presentation
PRIVATE TOUR IN SÃO PAULO
Presentation
SUMMER ZINE 2018
Presentation
RACISM AND HEALTHCARE
Presentation
FACTS IN THE TIME OF COVID-19
Presentation
Transcript
Enhancing Our Search Experience with Algolia Integration
Questions and Next Steps
Collaboration with Algolia Team
Proposed Solutions and Action Plan
Prioritized Goals and Features
Current State of Integration
Project Overview and Objectives
We are a eccomerce firearms retailer prioritizing high volume/turnover.We have a wide variety of products from firearms to apparell, accessories, etc..We have a high number of products (92,500-100,000) with frequent updates and new products (daily)Coreware is our hosting platform, there is currently a robust backend of data including thorough taxonomy and facets.Several integrations for importing products managing the site etc..Is semi built for/currently using csv's for data transfers for the most partEverything said to be taken with a grain of salt and am very open to different solutions/solves but this is the current state
Company Background - Battlehawk Armory
Key Objectives:Enhance search functionality on the website.Improve user experience through personalization.Automate data synchronization between Coreware and Algolia.Implement robust analytics and tracking.Ensure scalability, security, and data protection.
Project Goals
API Connection
Description of the hand-built API for indexing.Current use of Coreware API for product data.Overview of the existing autocomplete front end.Mention of facets already set up and retrievable via API.
Existing Infrastructure
Obviously there is a large number of api funcitons, aswell as there being some custom made ones but I beleive this likely contains much of the necessary information for indexing. notably it also contains a time changed and date created allowing for a potential automated update solve
" "product_addons": [] }, "api_domain_name": "battlehawkarmory.coreware.com", "result": "OK"
" "minimum_price": "", "manufacturer_advertised_price": "", "map_expiration_date": "", "width": "8.0000", "length": "10.0000", "height": "2.0000", "weight": "4.0000", "product_manufacturer_code": "HECKLER_KOCH_INC.", "product_manufacturer_description": "Heckler & Koch, Inc.", "product_category_codes": "PISTOLS", "product_tag_codes": "FFL_REQUIRED", "product_facets": "ACTION||Single/Double||||BARREL_LENGTH||3.58\"||||BARREL_LENGTH_RANGE||3.00\" to 3.99\"||||BARREL_TYPE||Polygonal Rifled||||CALIBER||.40 S&W||||CAPACITY||10+1||||FRAME_FINISH||Black||||FRAME_MATERIAL||Polymer||||GRIPS||Black Polymer Grip/Frame||||INCLUDES||3 Magazines||||OAL||6.81\"||||SAFETY||Decocker||||SEARCH_CODE||HK||||SERIES||V1 *CA/MA Compliant*||||SIGHT_CONFIGURATION||Night||||SIGHT_STYLE||Night||||SIMILAR_ITEMS||HG40||||SLIDE_DESCRIPTION||Blued Steel||||TYPE||Pistol||||WEIGHT||27.52 oz||||WEIGHT_RANGE||16.00 oz to 31.99 oz", "related_products": "642230254312||LEGAL_PROTECTION", "restricted_states": "", "alternate_images": "", "product_prices": [], "product_videos": [], "product_custom_fields": [], "custom_fields": [], "product_addons": [] }, "api_domain_name": "battlehawkarmory.coreware.com", "result": "OK"
" "search_multiplier": "1.00", "calculated_search_multiplier": "1.00", "points_multiplier": "1.00", "sort_order": 100, "requires_user": 0, "catalog_lock": 1, "no_update": 0, "not_searchable": 0, "cannot_dropship": 0, "reindex": 0, "custom_product": 0, "non_inventory_item": 0, "not_taxable": 0, "serializable": 1, "no_online_order": 0, "in_stock": 0, "internal_use_only": 0, "inactive": 0, "notes": "", "version": 1, "product_data_id": 196102, "product_distributor_id": 1, "unit_id": 44, "model": "USP40C", "upc_code": "642230254312", "isbn": "", "isbn_13": "", "manufacturer_sku": "704001LELA5", "minimum_price": "", "manufacturer_advertised_price": "", "map_expiration_date": "", "width": "8.0000", "length": "10.0000", "height": "2.0000", "weight": "4.0000", "product_manufacturer_code": "HECKLER_KOCH_INC.", "product_manufacturer_description": "Heckler & Koch, Inc.", "product_category_codes": "PISTOLS", "product_tag_codes": "FFL_REQUIRED", "product_facets": "ACTION||Single/Double||||BARREL_LENGTH||3.58\"||||BARREL_LENGTH_RANGE||3.00\" to 3.99\"||||BARREL_TYPE||Polygonal Rifled||||CALIBER||.40 S&W||||CAPACITY||10+1||||FRAME_FINISH||Black||||FRAME_MATERIAL||Polymer||||GRIPS||Black Polymer Grip/Frame||||INCLUDES||3 Magazines||||OAL||6.81\"||||SAFETY||Decocker||||SEARCH_CODE||HK||||SERIES||V1 *CA/MA Compliant*||||SIGHT_CONFIGURATION||Night||||SIGHT_STYLE||Night||||SIMILAR_ITEMS||HG40||||SLIDE_DESCRIPTION||Blued Steel||||TYPE||Pistol||||WEIGHT||27.52 oz||||WEIGHT_RANGE||16.00 oz to 31.99 oz", "related_products": "642230254312||LEGAL_PROTECTION", "restricted_states": "", "alternate_images": "", "product_prices": [], "product_videos": [], "product_custom_fields": [], "custom_fields": [], "product_addons": [] }, "api_domain_name": "battlehawkarmory.coreware.com", "result": "OK"
" "link_name": "hk-704001lela5-usp40c-cama-compliant-40-sw-3.58-101-black-blued-steel-black-polymer-grip", "product_type_id": "", "product_format_id": "", "product_manufacturer_id": 8578, "base_cost": "816.90", "list_price": "", "pricing_structure_id": "", "low_inventory_quantity": 0, "low_inventory_surcharge_amount": "", "virtual_product": 0, "file_id": "", "image_id": "", "remote_identifier": 2400, "cart_minimum": "", "cart_maximum": "", "order_maximum": "", "date_created": "2019-12-03", "expiration_date": "", "time_changed": "2023-04-04 19:18:18", "user_group_id": "", "error_message": "", "search_terms": "", "tax_rate_id": "", "search_multiplier": "1.00", "calculated_search_multiplier": "1.00", "points_multiplier": "1.00", "sort_order": 100, "requires_user": 0, "catalog_lock": 1, "no_update": 0, "not_searchable": 0, "cannot_dropship": 0, "reindex": 0, "custom_product": 0, "non_inventory_item": 0, "not_taxable": 0, "serializable": 1, "no_online_order": 0, "in_stock": 0, "internal_use_only": 0, "inactive": 0, "notes": "", "version": 1, "product_data_id": 196102, "product_distributor_id": 1, "unit_id": 44, "model": "USP40C", "upc_code": "642230254312", "isbn": "", "isbn_13": "", "manufacturer_sku": "704001LELA5", "minimum_price": "", "manufacturer_advertised_price": "", "map_expiration_date": "", "width": "8.0000", "length": "10.0000", "height": "2.0000", "weight": "4.0000", "product_manufacturer_code": "HECKLER_KOCH_INC.", "product_manufacturer_description": "Heckler & Koch, Inc.", "product_category_codes": "PISTOLS", "product_tag_codes": "FFL_REQUIRED", "product_facets": "ACTION||Single/Double||||BARREL_LENGTH||3.58\"||||BARREL_LENGTH_RANGE||3.00\" to 3.99\"||||BARREL_TYPE||Polygonal Rifled||||CALIBER||.40 S&W||||CAPACITY||10+1||||FRAME_FINISH||Black||||FRAME_MATERIAL||Polymer||||GRIPS||Black Polymer Grip/Frame||||INCLUDES||3 Magazines||||OAL||6.81\"||||SAFETY||Decocker||||SEARCH_CODE||HK||||SERIES||V1 *CA/MA Compliant*||||SIGHT_CONFIGURATION||Night||||SIGHT_STYLE||Night||||SIMILAR_ITEMS||HG40||||SLIDE_DESCRIPTION||Blued Steel||||TYPE||Pistol||||WEIGHT||27.52 oz||||WEIGHT_RANGE||16.00 oz to 31.99 oz", "related_products": "642230254312||LEGAL_PROTECTION", "restricted_states": "", "alternate_images": "", "product_prices": [], "product_videos": [], "product_custom_fields": [], "custom_fields": [], "product_addons": [] }, "api_domain_name": "battlehawkarmory.coreware.com", "result": "OK"
"post_variables": { "method": "get_full_product_information\n", "connection_key": "ope", "product_id": "196103", "upc_code": "SIGE26R9LEGIONSAORXP", "action": "get_full_product_information\n" }, "product_information": { "product_id": 196103, "client_id": 5, "product_code": "7079", "description": "HK 704001LELA5 USP40C *CA/MA Compliant 40 S&W 3.58\" 10+1 Black Blued Steel Black Polymer Grip", "detailed_description": "The HK USP (Universal Self-loading Pistol) is an accurate and ultra-reliable handgun. It utilizes a fiber-reinforced polymer frame stiffened by stainless steel inserts at areas subject to stress and friction. The control lever, a combination safety and decocking lever, is frame mounted and quickly accessible, unlike the slide-mounted safeties. The modular design of the USP's internal components allows the control lever function to be switched from the left to the right side of the pistol for left-handed shooters. The USP Compact are smaller and lighter than large frame USPs. The reduction in trigger reach and grip circumference increases concealability and enhances shooting ergonomics. It utilizes a narrow, full-hand grip frame with a choice of interchangeable extended or flush-fitting magazine floorplates. The USP Compact features a polygonal bore barrel, one-piece steel slide with contoured, extended release, bobbed hammer, universal mounting grooves, and ambidextrous magazine release lever. This model has a black frame with blued slide, captive recoil spring assembly with polymer absorber bushing, night sights, and comes with three 10-round magazines.", "link_name": "hk-704001lela5-usp40c-cama-compliant-40-sw-3.58-101-black-blued-steel-black-polymer-grip", "product_type_id": "", "product_format_id": "", "product_manufacturer_id": 8578, "base_cost": "816.90", "list_price": "", "pricing_structure_id": "", "low_inventory_quantity": 0, "low_inventory_surcharge_amount": "", "virtual_product": 0, "file_id": "", "image_id": "", "remote_identifier": 2400, "cart_minimum": "", "cart_maximum": "", "order_maximum": "", "date_created": "2019-12-03", "expiration_date": "", "time_changed": "2023-04-04 19:18:18", "user_group_id": "", "error_message": "", "search_terms": "", "tax_rate_id": "", "search_multiplier": "1.00", "calculated_search_multiplier": "1.00", "points_multiplier": "1.00", "sort_order": 100, "requires_user": 0, "catalog_lock": 1, "no_update": 0, "not_searchable": 0, "cannot_dropship": 0, "reindex": 0, "custom_product": 0, "non_inventory_item": 0, "not_taxable": 0, "serializable": 1, "no_online_order": 0, "in_stock": 0, "internal_use_only": 0, "inactive": 0, "notes": "", "version": 1, "product_data_id": 196102, "product_distributor_id": 1, "unit_id": 44, "model": "USP40C", "upc_code": "642230254312", "isbn": "", "isbn_13": "", "manufacturer_sku": "704001LELA5", "minimum_price": "", "manufacturer_advertised_price": "", "map_expiration_date": "", "width": "8.0000", "length": "10.0000", "height": "2.0000", "weight": "4.0000", "product_manufacturer_code": "HECKLER_KOCH_INC.", "product_manufacturer_description": "Heckler & Koch, Inc.", "product_category_codes": "PISTOLS", "product_tag_codes": "FFL_REQUIRED", "product_facets": "ACTION||Single/Double||||BARREL_LENGTH||3.58\"||||BARREL_LENGTH_RANGE||3.00\" to 3.99\"||||BARREL_TYPE||Polygonal Rifled||||CALIBER||.40 S&W||||CAPACITY||10+1||||FRAME_FINISH||Black||||FRAME_MATERIAL||Polymer||||GRIPS||Black Polymer Grip/Frame||||INCLUDES||3 Magazines||||OAL||6.81\"||||SAFETY||Decocker||||SEARCH_CODE||HK||||SERIES||V1 *CA/MA Compliant*||||SIGHT_CONFIGURATION||Night||||SIGHT_STYLE||Night||||SIMILAR_ITEMS||HG40||||SLIDE_DESCRIPTION||Blued Steel||||TYPE||Pistol||||WEIGHT||27.52 oz||||WEIGHT_RANGE||16.00 oz to 31.99 oz", "related_products": "642230254312||LEGAL_PROTECTION", "restricted_states": "", "alternate_images": "", "product_prices": [], "product_videos": [], "product_custom_fields": [], "custom_fields": [], "product_addons": [] }, "api_domain_name": "battlehawkarmory.coreware.com", "result": "OK"
Get_full_product info api call return data
// Function to index product data to Algoliaasync function indexProductData(productData) { try { // Function to parse product_facets string into an object function parseFacets(facetsString) { const facetsArray = facetsString.split('||||'); const facetsObject = {}; for (let i = 0; i < facetsArray.length; i += 2) { const key = facetsArray[i]; const value = facetsArray[i + 1]; if (key && value) { facetsObject[key] = value; } } return facetsObject; } // Fetch the image URL using the product's slug const imageUrl = await fetchImageUrl(productData.link_name); const algoliaProduct = { objectID: productData.product_id, link_name: productData.link_name, description: productData.description, product_code: productData.product_code, model: productData.model, upc_code: productData.upc_code, category: productData.product_category_codes, tags: productData.product_tag_codes, image_url: imageUrl || productData.image_url || null, // New fields search_terms: productData.search_terms, product_manufacturer_description: productData.product_manufacturer_description, product_facets: parseFacets(productData.product_facets), text_data: productData.text_data, in_stock: productData.in_stock, time_changed: productData.time_changed, }; await index.saveObject(algoliaProduct); console.log( `Product ID ${productData.product_id} indexed successfully to Algolia!` ); } catch (error) { console.error( `Error indexing product ID ${productData.product_id}:`, error.response ? error.response.data : error.message ); throw error; } } // Main function to fetch and push product data to Algolia async function fetchAndPushToAlgolia() { try { const productIds = [20]; // Replace with dynamic IDs or implement logic to fetch multiple IDs for (const productId of productIds) { const productData = await fetchProductData(productId); await indexProductData(productData); } } catch (error) { console.error('Error in fetchAndPushToAlgolia:', error.message); } } // Run the main function fetchAndPushToAlgolia();
const response = await axios.get(url, { headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)', Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'Accept-Language': 'en-US,en;q=0.9', }, }); const html = response.data; const $ = cheerio.load(html); // Adjust the selector based on your HTML structure const imageSrc = $('#_product_primary_image .product-image').attr('src') || null; return imageSrc; } catch (error) { console.error('Error fetching image URL:', error.message); return null; } } // Function to index product data to Algolia async function indexProductData(productData) { try { // Function to parse product_facets string into an object function parseFacets(facetsString) { const facetsArray = facetsString.split('||||'); const facetsObject = {}; for (let i = 0; i < facetsArray.length; i += 2) { const key = facetsArray[i]; const value = facetsArray[i + 1]; if (key && value) { facetsObject[key] = value; } } return facetsObject; } // Fetch the image URL using the product's slug const imageUrl = await fetchImageUrl(productData.link_name); const algoliaProduct = { objectID: productData.product_id, link_name: productData.link_name, description: productData.description, product_code: productData.product_code, model: productData.model, upc_code: productData.upc_code, category: productData.product_category_codes, tags: productData.product_tag_codes, image_url: imageUrl || productData.image_url || null, // New fields search_terms: productData.search_terms, product_manufacturer_description: productData.product_manufacturer_description, product_facets: parseFacets(productData.product_facets), text_data: productData.text_data, in_stock: productData.in_stock, time_changed: productData.time_changed, }; await index.saveObject(algoliaProduct); console.log( `Product ID ${productData.product_id} indexed successfully to Algolia!` ); } catch (error) { console.error( `Error indexing product ID ${productData.product_id}:`, error.response ? error.response.data : error.message ); throw error; } } // Main function to fetch and push product data to Algolia async function fetchAndPushToAlgolia() { try { const productIds = [20]; // Replace with dynamic IDs or implement logic to fetch multiple IDs for (const productId of productIds) { const productData = await fetchProductData(productId); await indexProductData(productData); } } catch (error) { console.error('Error in fetchAndPushToAlgolia:', error.message); } } // Run the main function fetchAndPushToAlgolia();
method: 'get_full_product_information', product_id: productId, connection_key: connectionKey, }, }); if (response.status !== 200 || !response.data.product_information) { throw new Error(`Failed to fetch product data for ID ${productId}`); } return response.data.product_information; } catch (error) { console.error( `Error fetching product data for ID ${productId}:`, error.response ? error.response.data : error.message ); throw error; } } // Function to fetch image URL using Axios and Cheerio async function fetchImageUrl(slug) { try { const url = `https://battlehawkarmory.com/product/${slug}`; const response = await axios.get(url, { headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)', Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'Accept-Language': 'en-US,en;q=0.9', }, }); const html = response.data; const $ = cheerio.load(html); // Adjust the selector based on your HTML structure const imageSrc = $('#_product_primary_image .product-image').attr('src') || null; return imageSrc; } catch (error) { console.error('Error fetching image URL:', error.message); return null; } } // Function to index product data to Algolia async function indexProductData(productData) { try { // Function to parse product_facets string into an object function parseFacets(facetsString) { const facetsArray = facetsString.split('||||'); const facetsObject = {}; for (let i = 0; i < facetsArray.length; i += 2) { const key = facetsArray[i]; const value = facetsArray[i + 1]; if (key && value) { facetsObject[key] = value; } } return facetsObject; } // Fetch the image URL using the product's slug const imageUrl = await fetchImageUrl(productData.link_name); const algoliaProduct = { objectID: productData.product_id, link_name: productData.link_name, description: productData.description, product_code: productData.product_code, model: productData.model, upc_code: productData.upc_code, category: productData.product_category_codes, tags: productData.product_tag_codes, image_url: imageUrl || productData.image_url || null, // New fields search_terms: productData.search_terms, product_manufacturer_description: productData.product_manufacturer_description, product_facets: parseFacets(productData.product_facets), text_data: productData.text_data, in_stock: productData.in_stock, time_changed: productData.time_changed, }; await index.saveObject(algoliaProduct); console.log( `Product ID ${productData.product_id} indexed successfully to Algolia!` ); } catch (error) { console.error( `Error indexing product ID ${productData.product_id}:`, error.response ? error.response.data : error.message ); throw error; } } // Main function to fetch and push product data to Algolia async function fetchAndPushToAlgolia() { try { const productIds = [20]; // Replace with dynamic IDs or implement logic to fetch multiple IDs for (const productId of productIds) { const productData = await fetchProductData(productId); await indexProductData(productData); } } catch (error) { console.error('Error in fetchAndPushToAlgolia:', error.message); } } // Run the main function fetchAndPushToAlgolia();
require('dotenv').config(); const algoliasearch = require('algoliasearch'); const axios = require('axios'); const cheerio = require('cheerio'); // Initialize Algolia client using credentials from environment variables const client = algoliasearch( process.env.ALGOLIA_APP_ID, process.env.ALGOLIA_ADMIN_API_KEY ); const index = client.initIndex(process.env.ALGOLIA_INDEX_NAME); // Coreware API endpoint and credentials const corewareURL = process.env.COREWARE_API_URL; const connectionKey = process.env.COREWARE_CONNECTION_KEY; // Function to fetch product data from Coreware API async function fetchProductData(productId) { try { const response = await axios.get(corewareURL, { params: { method: 'get_full_product_information', product_id: productId, connection_key: connectionKey, }, }); if (response.status !== 200 || !response.data.product_information) { throw new Error(`Failed to fetch product data for ID ${productId}`); } return response.data.product_information; } catch (error) { console.error( `Error fetching product data for ID ${productId}:`, error.response ? error.response.data : error.message ); throw error; } } // Function to fetch image URL using Axios and Cheerio async function fetchImageUrl(slug) { try { const url = `https://battlehawkarmory.com/product/${slug}`; const response = await axios.get(url, { headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)', Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'Accept-Language': 'en-US,en;q=0.9', }, }); const html = response.data; const $ = cheerio.load(html); // Adjust the selector based on your HTML structure const imageSrc = $('#_product_primary_image .product-image').attr('src') || null; return imageSrc; } catch (error) { console.error('Error fetching image URL:', error.message); return null; } } // Function to index product data to Algolia async function indexProductData(productData) { try { // Function to parse product_facets string into an object function parseFacets(facetsString) { const facetsArray = facetsString.split('||||'); const facetsObject = {}; for (let i = 0; i < facetsArray.length; i += 2) { const key = facetsArray[i]; const value = facetsArray[i + 1]; if (key && value) { facetsObject[key] = value; } } return facetsObject; } // Fetch the image URL using the product's slug const imageUrl = await fetchImageUrl(productData.link_name); const algoliaProduct = { objectID: productData.product_id, link_name: productData.link_name, description: productData.description, product_code: productData.product_code, model: productData.model, upc_code: productData.upc_code, category: productData.product_category_codes, tags: productData.product_tag_codes, image_url: imageUrl || productData.image_url || null, // New fields search_terms: productData.search_terms, product_manufacturer_description: productData.product_manufacturer_description, product_facets: parseFacets(productData.product_facets), text_data: productData.text_data, in_stock: productData.in_stock, time_changed: productData.time_changed, }; await index.saveObject(algoliaProduct); console.log( `Product ID ${productData.product_id} indexed successfully to Algolia!` ); } catch (error) { console.error( `Error indexing product ID ${productData.product_id}:`, error.response ? error.response.data : error.message ); throw error; } } // Main function to fetch and push product data to Algolia async function fetchAndPushToAlgolia() { try { const productIds = [20]; // Replace with dynamic IDs or implement logic to fetch multiple IDs for (const productId of productIds) { const productData = await fetchProductData(productId); await indexProductData(productData); } } catch (error) { console.error('Error in fetchAndPushToAlgolia:', error.message); } } // Run the main function fetchAndPushToAlgolia();
custom api
The product is pulled via product code, we can input as many as needed, and could create logic for automating indexing, can also tweak which fields for pulling different info.
} catch (error) { console.error('Error in fetchAndPushToAlgolia:', error.message); } } // Run the main function fetchAndPushToAlgolia();
}; await index.saveObject(algoliaProduct); console.log( `Product ID ${productData.product_id} indexed successfully to Algolia!` ); } catch (error) { console.error( `Error indexing product ID ${productData.product_id}:`, error.response ? error.response.data : error.message ); throw error; } } // Main function to fetch and push product data to Algolia async function fetchAndPushToAlgolia() { try { const productIds = [20]; // Replace with dynamic IDs or implement logic to fetch multiple IDs for (const productId of productIds) { const productData = await fetchProductData(productId); await indexProductData(productData); } } catch (error) { console.error('Error in fetchAndPushToAlgolia:', error.message); } } // Run the main function fetchAndPushToAlgolia();
// Fetch the image URL using the product's slug const imageUrl = await fetchImageUrl(productData.link_name); const algoliaProduct = { objectID: productData.product_id, link_name: productData.link_name, description: productData.description, product_code: productData.product_code, model: productData.model, upc_code: productData.upc_code, category: productData.product_category_codes, tags: productData.product_tag_codes, image_url: imageUrl || productData.image_url || null, // New fields search_terms: productData.search_terms, product_manufacturer_description: productData.product_manufacturer_description, product_facets: parseFacets(productData.product_facets), text_data: productData.text_data, in_stock: productData.in_stock, time_changed: productData.time_changed, }; await index.saveObject(algoliaProduct); console.log( `Product ID ${productData.product_id} indexed successfully to Algolia!` ); } catch (error) { console.error( `Error indexing product ID ${productData.product_id}:`, error.response ? error.response.data : error.message ); throw error; } } // Main function to fetch and push product data to Algolia async function fetchAndPushToAlgolia() { try { const productIds = [20]; // Replace with dynamic IDs or implement logic to fetch multiple IDs for (const productId of productIds) { const productData = await fetchProductData(productId); await indexProductData(productData); } } catch (error) { console.error('Error in fetchAndPushToAlgolia:', error.message); } } // Run the main function fetchAndPushToAlgolia();
custom api cont.
All that results in this index. using the current headless browser system it takes about 3 seconds per product to index.Though when looking at updates we wont have to pull images, not having to use the headless browser drastically reducing that time to search through the catalog for date ranges in order to than reindex/update.
Front end looks like this currently, when clicking into the search box it opens the autocomplete, when clicking out it closes it.NOTE: when clicking the search icon it reverts to our old search functionality showing our product display results page.Integrated through java css and html.
its further down the priority list but once we have a solid configuration base, indexing etc.. adding a sort of menu highlighting top trending items, facets, etc. replacing this leftmost collumn could be good
Push product id's of updated products for reindexing
pull full product data-run time changed date range
Can maybe grab from here
API - - algolia index
catalog update
Manual product entry/updates
3rd party integrations via php script uploading new products backend
Data Flow Diagram
List of Challenges:Manual indexing and lack of automation.Limited event tracking and analytics.Basic autocomplete without custom recommendations.Need for personalization and similar product suggestions.Integration of facets into the front end. Optimization and scalability concerns.
Challenges Identified
So maybe something like using a cron job to schedule a daily update
as mentioned with the diagram and prior slides. we have a need to set up robust efficient indexing updates for both new items and updated items. there are several approaches we could take from running daily csv imports and than searching through date ranges. maybe using a data proccessing software like apache. or maybe just with a custom script. Its possible we could build off the third party integrations running php scripts that upload new products and have them push to our index also though.
Top Priority – Automated and Accurate Indexing
In addition to great analyics for our own use they would also be great for upgraded reccomendations and related products and re-ranking/other personlization.
We would like the most robust analytics we can get so we'd be looking to add event listeners to every action possible for the most part.
Robust Event Tracking and Analytics
Fleshing out the backend of our index configurations by properly implementing logic like re-ranking based on stock status, proper searhcable attributes, typo tolerance, synonyms, facets etc..Testing and refining search configurations.
Enhanced Autocomplete with Custom Recommendations
As a part of the upgraded css front end leftmost column allowing potentially for a faceted search and other custom recommendations from usImproving product filtering and navigation.Enhancing the front end for a cleaner and more intuitive interface.
Integration of Facets into the Front End
We need to ensure once we're live were not breaking the website, causing downtime, not properly displaying results etc.. creating a robust system of 250,000 products, potentially daily updates, and a high user volume.Code optimization for indexing and front-end performance.Batch operations and efficient data handling.Monitoring and profiling for bottleneck identification.Designing solutions that can scale with increased data and user load.Future-proofing the system for long-term growth.
Optimization and Scalability
Have to ensure were not introducing vulnerabilities into the system, or sharing our or user data.
Security and Data Protection
Defining what the Algolia team will handle vs. internal tasks.
Roles and Responsibilities
Timeline for each prioritized feature.Key milestones and deadlines.
Proposed Timeline and Milestones
Preferred communication channels (e.g., email, Slack).Regular meeting schedules.Points of contact from both teams.
Communication and Collaboration Plan
Invite questions and feedback from the Algolia team.Address any concerns or clarifications.
Questions and Next Steps
Finalize the plan based on feedback.Set up the initial kickoff meeting.Assign tasks and set up collaboration tools.
Immediate Next Steps
1. api code2. api get request return 3.current index4. template integrations5. backend coreware info, facets, 6.7.8.9.10.
Document list
1. hosting the scripts? servers etc..2.testing other api calls 3.4. 5. 6.7.8.9.10.
questions to answer
InvokeHTTP (Get All Product IDs)SplitJSON (Split Product IDs)InvokeHTTP (Get Full Product Info)EvaluateJsonPath (Extract Fields)RouteOnAttribute (Filter by Date Range)Extract UPCsPrepare UPC ListExecuteProcess (Run Custom Script)