ProductCat 1.0.0

ProductCat 1.0.0

Maintained by Ngo Hung.



  • By
  • Ngo Hung

ProductCat Swift SDK and Demo Source Code

Swift


Table of Contents

  1. Overview
  2. Setup
  3. Initialization
  4. Solution APIs
  5. Search Results
  6. Data Privacy Flow

1. Overview

Our ProductCat (Products Catalog) API enables you to find and search for products more easily by cataloguing your products automatically.ProductCat API Documentation.

This SDK is an open source software to provide easy integration of ProductCat Search APIs with your iOS applications. It provides three search methods - Search Product by Image, Search Product by text keywords and Get Search Results Page.

ProductCat database is partitioned globally based on country and geographical regions. It is required that you call the Product Search APIs with country parameter to ensure only products that ship to the country will be returned.

Current stable version: 0.2.0 (Swift 5+)

Supported iOS version: iOS 10.x and higher

2. Setup

2.1 Run the Demo

The source code of a demo application is provided together with the SDK (demo). You can simply open ProductCatExample.xcworkspace in Xcode and run the demo.

screenshot

You will need to initialize the ProductCat client in AppDelegate file by using your app key.

// TODO: fill in your app key and search country here
ProductCat.sharedInstance.setup(appKey: "YOUR_APP_KEY", country: ExampleSettings.getCountry() ?? "SG")
       
       

2.2 Set up Xcode project

2.3 Import ProductCat Swift SDK

2.3.1 Using CocoaPods

First you need to install the CocoaPods Ruby gem:

sudo gem install cocoapods --pre

Then go to your project directory to create an empty Podfile

cd /path/to/Demo
pod init

Edit the Podfile as follow:

platform :ios, '10.0'
use_frameworks!

target '<Your Target Name>' do
    pod 'ProductCat'
end
...

Install the SDK:

pod install

The Demo.xcworkspace project should be created.

2.3.2 Using Manual Approach

You can also download the iOS SDK directly. To use it, unzip it and drag ProductCat project into your project.

  • Open the ProductCat folder, and drag the ProductCat into the Project Navigator of your application's Xcode project.

    It should appear nested underneath your application's blue project icon. Whether it is above or below all the other Xcode groups does not matter.

  • Select the ProductCat.xcodeproj in the Project Navigator and verify the deployment target matches that of your application target.

  • Next, select your application project in the Project Navigator to navigate to the target configuration window and select the application target under the "Targets" heading in the sidebar.

  • In the tab bar at the top of that window, open the "Build Phases" panel.

  • Click on the + button under the "Link Binary with Libraries" section.

  • Select the ProductCat.framework.

  • You will also need to click on + button to add 'New Copy Files Phase' > set 'Frameworks' as Destination and ProductCat.framework to copy the framework into your project.

The ProductCat.framework is then registered as a target dependency, linked framework and embedded framework.

You are done!

2.4 Add Privacy Usage Description

iOS 10+ requires user permission to access camera and photo library. If your app requires these access, please add description for NSCameraUsageDescription, NSPhotoLibraryUsageDescription in the Info.plist. More details can be found here.

3. Initialization

ProductCat client must be initialized with an app_key before it can be used.

import ProductCat

...
// using default client which will connect to Visenze's server
// the country is passed to select the corresponding search points
// We provided 2 different points for China and the rest of the world
// productcat.visenze.com and productcat.visenze.com.cn
ProductCat.sharedInstance.setup(appKey: "YOUR_APP_KEY", country: "SG")
        
// specify custom timeout
ProductCat.sharedInstance.setup(baseUrl: "https://productcat.visenze.com", appKey: "YOUR_APP_KEY", country: "SG", timeout:20 )

...

4. Solution APIs

4.1 Search by Image

POST /summary/products

Search by image solution is to search for visually similar products in the global products database given a query image. You should construct the UIImage object and pass it to ImageSearchParams to start a search. Please also specify the country parameter to define which local database you want to search.

  • Using Image
import ProductCat
...

let image = UIImage(named: "someImage.png")
let params = ImageSearchParams(country: "SG", image: image!)

ProductCat.sharedInstance.imageSearch(params: params,
                    successHandler: {
                        (data : ProductSummaryResponse?) -> Void in
                        // Do something when request succeeds
                        // preview by calling : dump(data)
                        // check data.hasError and data.error for any errors return by ViSenze server
                    },
                    failureHandler: {
                        (err) -> Void in
                        // Do something when request fails e.g. due to network error
                        print ("error: \\(err.localizedDescription)")
					})
  • Alternatively, you can pass an image url directly to ImageSearchParams to start the search :
import ProductCat
...

let params = ImageSearchParams(country: "SG", imUrl: "http://somesite.com/sample_image.png")
        
...
  • If you are performing refinement on a previously uploaded image such as resizing the box, you can pass the im_id returned in the search result to start the search instead of uploading the image again.
import ProductCat
...

let params = ImageSearchParams(country: "SG", imId: "visenze_image_id_returned in previous search")
        
...

4.1.1 Selection Box

If the object you wish to search for takes up only a small portion of your image, or other irrelevant objects exist in the same image, chances are the search result could become inaccurate. Use the Box parameter to refine the search area of the image to improve accuracy. The box coordinated is set with respect to the original size of the uploading image. Note: the coordinate system uses pixel as unit instead of point.

// create the box to refine the area on the searching image
// Box(x1, y1, x2, y2) where (0,0) is the top-left corner
// of the image, (x1, y1) is the top-left corner of the box,
// and (x2, y2) is the bottom-right corner of the box.
...

let params = ImageSearchParams(.....)

let box = Box(x1: 0, y1: 0, x2: 100, y2: 100)
params.box = box
        
// start searching
...

4.1.2 Resizing Settings

When performing image search, you may notice the increased search latency with increased image file size. This is due to the increased time spent in network transferring your images to ViSenze server, and the increased time for processing larger image files.

To reduce upload search latency, by default the method makes a copy of your image file and resizes the copy to 512x512 pixels if one of the original dimensions exceed 512 pixels. This is the optimized size to lower search latency while not sacrificing search accuracy for general use cases:

// by default, the max width of the image is set to 512px, quality is 0.97
let params = ImageSearchParams(.....)

// or you can explicitly set a param's settings
params?.imgSettings = ImageSettings(setting: .highQualitySetting)
        

If your image contains fine details such as textile patterns and textures, you can use an image with larger size for search to get better search result:

// by default, the max width of the image is set to 512px, quality is 0.97
let params = ImageSearchParams(.....)

// set the image with high quality settings.
// Max width is 1024px, and the quality is 0.985. Note: Quality with 1.0 take hugespace
params?.imgSettings = ImageSettings(setting: .highQualitySetting)

Or, provide the customized resize settings. To make efficient use the of the memory and network bandwidth of mobile device, the maximum size is set at 1024 x 1024. Any image exceeds the limit will be resized to the limit:

//resize the image to 800 by 800 area using jpeg 0.9 quality
params?.imgSettings = ImageSettings(size: CGSize(width: 800, height: 800), quality: 0.9)
        

4.2 Search Results API

POST /summary/products/srp

Search Results Page API solution is to get a web url to display the searched results in browser. All parameters used in /summary/products are also valid in this api.

import ProductCat
...

ProductCat.sharedInstance.imageSearchResultPage(params: params,
                    successHandler: {
                        (data : ProductSummaryResponse?) -> Void in
                        // Do something when request succeeds
                        // preview by calling : dump(data)
                        // check data.hasError and data.error for any errors return by ViSenze server
                        // open the search results in a browser
                        
                        if let searchResultsUrl = data.srpUrl, let url = URL(string: searchResultsUrl) {
                        let vc = SFSafariViewController(url: url, entersReaderIfAvailable: false)
               vc.delegate = self
               self.present(vc, animated: true)
                        
                        }
                        
                        
                    },
                    failureHandler: {
                        (err) -> Void in
                        // Do something when request fails e.g. due to network error
                        print ("error: \\(err.localizedDescription)")
					})

...

4.3 Text Search

GET /summary/products

Text Search solution is to search similar products by given text keywords.

import ProductCat
...

let textSearchParams = TextSearchParams(country: "SG", q: "some keywords")
ProductCat.sharedInstance.textSearch(params: textSearchParams,
                             successHandler: {
             (data : ProductSummaryResponse?) -> Void in
                 // Do something when request succeeds
                 // preview by calling : dump(data)
                 // check data.hasError and data.error for any errors return by ViSenze server
                 dump(data)
                 
              
                               
         },
        failureHandler: {
             (err) -> Void in
             // Do something when request fails e.g. due to network error
             print ("error: \\(err.localizedDescription)")
            
         })

5. Search Results

After a successful search request, a list of results are passed to the callback function in the form of ProductSummaryResponse. You can use the following properties from the result to fulfill your own purpose.

Name Type Description
hasError Bool true if there are errors returned by Visenze server.
error [String] return the error messages from server if there is any.
result [ProductSummary] A list of products returned from the server.
reqid String A request id for debugging purpose
imId String An image id returned in the result which represents a image just uploaded. It can be re-used to do another search on the same image again.

Below are the properties of a ProductSummary represents a product.

Name Type Description
pid String product ID.
mainImage String image URL
title String product title
minPrice String product price
priceUnit String 3 letters ISO currency code e.g. "USD"
productUrl String product URL
stores [Store] list of stores this product is sold in. Array has at least 1 store

6. Data Privacy Flow

To analyze search performance and usage statistics (such as Click Through Rate, Active Users, Conversion Tracking, Retention Rate, etc), ProductCat SDK use UIDevice.current.identifierForVendor?.uuidString together with IDFA (from AdSupport.framework) to uniquely identify a user. Based on user's usage statistics, Visenze will push customized seach results and advertising products according to user's preference.

Please note that end-users need to:

  • Accept Visenze'ss Privacy Policy & Terms of Use in order to use our service
  • (Optionally) Accept advertisement terms to receive special offers, promotions information and product recommendations

ProductCat SDK will show user the "Terms and Conditions" dialog for the first time usage. Users need to accept the terms and conditions before using the APIs. If users do not accept the terms, the SDK will throw an error in its callback, it is up to the developer on whether to show up the consent form again or quit the service.


// error will be shown via failureHandler callback (ProductCatError.TERMS_NOT_ACCEPTED)

ProductCat.sharedInstance.imageSearch(params: params,
                    successHandler: {
                        
                    },
                    failureHandler: {
                        (err) -> Void in
                        
                        if (err == ProductCatError. ProductCatError.TERMS_NOT_ACCEPTED) {
                        
                        // show terms again
                        ProductCat.sharedInstance.showConsentForm(nil)
                        
                        }
					})


You can show the consent form and check whether user has accepted ViSenze terms using the following methods:

// show the form
ProductCat.sharedInstance.showConsentForm()

// check if user accept or reject the terms
ProductCat.sharedInstance.isAcceptedVisenzeTerms()