Here we present Javascript, Jquery and PHP code to call the hybrid filter API. You can take the response from these methods to create your own unique UI and logic to present visual search to your users.
var data = null; var xhr = new XMLHttpRequest(); xhr.open("GET", "https://api.okkular.io/v1/feed/59632/filters"); xhr.setRequestHeader("content-type", "application/json"); xhr.setRequestHeader("x-api-key", "*******b0fb159f2a2dc92d5a22c1b9de1afcc84a6deb*********"); xhr.send(data);
var params = { "async": true, "crossDomain": true, "url": "https://api.okkular.io/v1/feed/59632/filters", "method": "GET", "headers": { "content-type": "application/json", "x-api-key": "*******b0fb159f2a2dc92d5a22c1b9de1afcc84a6deb*********", } } $.ajax(params).done(function (response) { console.log(response); });
<?php $request = new HttpRequest(); $request->setUrl('https://api.okkular.io/v1/feed/59632/filters'); $request->setMethod(HTTP_METH_GET); $request->setHeaders(array( 'postman-token' => 'b67f7151-d703-efa0-ba2c-446905778db2', 'cache-control' => 'no-cache', 'x-api-key' => '*******b0fb159f2a2dc92d5a22c1b9de1afcc84a6deb*********', 'content-type' => 'application/json' )); try { $response = $request->send(); echo $response->getBody(); } catch (HttpException $ex) { echo $ex; } ?>
Integrate visual search into your web application by using the example code below
HTML Code
Paste this code before closing of body tag
<div class="hybrid-modal-body"></div>
Example of a button how you call hybrid plugin from click of button
<button type="button" class="btn btn-primary" onclick="callHybrid(59632)">Show Similar Images </button>
CSS (put css in head secrion)
<link rel="stylesheet" href="https://s3-us-west-2.amazonaws.com/hybrid-plugin-resources/hybridplugin.css" type="text/css"/>
SCRIPTS(put scripts at bottom of page)
Use below CDN hosted plugin
<script type="text/javascript" src="https://s3-us-west-2.amazonaws.com/hybrid-plugin-resources/hybridplugin-minified.js"> </script>
or you could download hybrid plugin here and make your changes
Download
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"> </script>
<script type="text/javascript" src="https://s3-us-west-2.amazonaws.com/hybrid-plugin-resources/hybridplugin-minified.js"> </script>
<script>
// Configuration function. Here you could set values for currency, plugintitle and okkularlogo
let config = () => {
return new Promise(function(resolve, reject){
var config_object = {};
config_object = {'currency':'$', 'pugintitle':'Similar Styles','okkularlogo':false};
resolve(config_object);
})
}
//This function should return metadata in an object form. like: {product_price: 3434, product_name:'Macbook air 128'}
let getMetaData = (skuList) => {
return new Promise(function(resolve,reject){
const metadata = [];
metadata.push({ sku: 'OC2116', product_price: '$34', product_name: 'Michael Kors Classic Watch'}, { sku: 'OC2715', product_price: '$50', product_name: 'Kors Classic Watch '}, { sku: 'A954-2357', product_price: '$50', product_name: 'Kors Classic Watch '}, { sku: 'YA126243', product_price: '$50', product_name: 'Kors Classic Watch '}, { sku: 'YA126243', product_price: '$50', product_name: 'Kors Classic Watch '});
resolve(metadata);
})
}
// this function is used to call hybrid filter function. API key is present in your retailer panel. Login to https://wwww.okkular.io/app/login and on settings page under credentials you will find your API key.
function callHybrid(sku){
var api_key = '***api key*****'
HybriDResults.init([sku, api_key, config, getMetaData]);
HybriDResults.ResultsHybrid();
}
</script>
// This block ensures that the code is executed after the document is fully loaded. $(document).ready(function () { /* Insert Modal into Page */ $("body").append(''); // Initiating the Okkular visual search plugin. /* You could modify button as per your need */ var visual_search_button = ''; /* Place your API Key */ var api_key = "0d740541b338c-xxxxx-xxxxx-xxxx"; // Place your storefront access token to execute the graphql using storefront api. var VISUAL_SEARCH_STOREFRONT_ACCESS_TOKEN = 'xxxxxxxx'; /* DYNAMIC_VALUE: product sku */ var my_sku = "6869653717126"; let updateProductDetailsInRealTime = (skuList) => { return new Promise(function (resolve, reject) { // Array that will hold list of metadata objects. const metadata = []; if (skuList.length !== 0) { var gql_sku_list = []; // Formatting the list of sku's in graphql format. gql_sku_list = skuList.map( (sku) => '"' + btoa(`gid://shopify/Product/${sku}`) + '"' ); /** * GraphQL query to fetch product's metadata of given SKUs. * Using ProductPricing @inContext(country: ${Shopify.country}) * to fetch price based on market price for the country name passed to the query. */ const query = ` query ProductPricing @inContext(country: ${Shopify.country}){ nodes(ids: [${gql_sku_list.toString()}]) { ...on Product { id title totalInventory availableForSale handle priceRange { minVariantPrice { amount } maxVariantPrice { amount } } variants(first: 1) { edges { node { id title priceV2 { amount currencyCode } } } } } } } `; /** * Function to make AJAX call to graphql.json. */ function queryGraphQL(query) { return fetch(`https://${window.location.host}/api/2021-07/graphql.json`, { method: "POST", headers: { "Content-Type": "application/graphql", "Access-Control-Origin": "*", "X-Shopify-Storefront-Access-Token": VISUAL_SEARCH_STOREFRONT_ACCESS_TOKEN, }, body: query, }).then((response) => response.json()); } /** * Calling queryGraphQL() function to load product metadata. */ queryGraphQL(query).then((response) => { for (let k = 0; k < response.data.nodes.length; k++) { if (response.data.nodes[k] !== null) { // If you want to show or hide visually similar product based on availability or status of the product, // they can manage that thing here like below. let product_status = "active"; // If you always want your product to show despite it is available for sale or not then remove or comment the below if-else statement. if (response.data.nodes[k].availableForSale) { product_status = "active"; } else { product_status = "inactive"; } // Defaulting the total Inventory to 1 to show on the popup. Update this dynamically if you want to show and hide bases on availablity and non-availablity. response.data.nodes[k].totalInventory = 1; // Pushing metadata per product in the list. // Modify product_url given below if the product URL changes as per specific market or country. metadata.push({ sku: skuList[k], product_price: response.data.nodes[k]["priceRange"]["maxVariantPrice"]["amount"],// Modify as what price you want to show product_name: response.data.nodes[k].title, product_url: "https://" + window.location.host + "/products/" + response.data.nodes[k].handle, // Modify product URL if URL fromation is different for you. product_inventory: response.data.nodes[k].totalInventory, product_status: product_status, }); } } if (metadata.length !== 0) { resolve(metadata); } }); } }); }; // Configuration function. Here you could set values for currency, plugintitle and okkularlogo. let config = () => { return new Promise(function (resolve, reject) { var confarray = {}; confarray = { currency: "$", pugintitle: "Similar Styles", okkularlogo: false, }; resolve(confarray); }); }; // Here we pass updateProductDetailsInRealTime as a callback function that overrides the product metadata in real-time. VisualSearch.init([my_sku, api_key, config, updateProductDetailsInRealTime]) .then(function (hasdata) { if (hasdata) { /* Replace 'selector_to_append_button' with your selector where you want button to appear */ $(".product-img-box").append(visual_search_button); $("._okkular_similar_view_button").css("display", "block"); } else { $("._okkular_similar_view_button").css("display", "none"); } }) .catch(function (reason) { $("._okkular_similar_view_button").css("display", "none"); }); });