Search Using Swift SDK

The Experience Search API is a native, AI-powered, multi-modal search solution that enables personalized search experiences on your website or app. It supports:

  • Semantic Search: Understands natural language text queries, enabling you to deliver highly relevant search results that meet user expectations and drive conversions.
  • Visual Search: Enables users to search using images from their camera or gallery to find visually similar or relevant products.
📘

For more information see the following:

Semantic Search

Parameters

ParameterData Structure TypeMandatory?Description
pagePageYesInformation about the current page (screen name, referrer, categories)
textStringYesThe natural‑language query to process using Semantic Search
filters[Filter]?NoOptional attribute filters (brand, color, price range, and so on)
paginationPaginationYesDefines number of items and offset for pagination
sortBySortOptions?NoSorting rules (for example, by field or by relevance)
pageAttributes[String: PageAttribute]?NoKey–value attributes for campaign targeting or search context
branchIdString?NoBranch identifier for multi‑branch setups (stores, financial institutions, restaurants)
optionsSearchOptions?NoAdditional search configurations (for example, return analytics metadata)

Code example

func semanticSearch() async { 
    let result = await DYSdk.shared().search.semanticSearch() 

    switch result.status { 
    case .success, .warning: 
        guard 
            let choice = result.choice, 
            let variation = choice.variations.first 
        else { 
            print("SemanticSearch: No choice or variation returned for semantic search result") 
            return 
        } 

        let data = variation.payload.data 
        let spellCheckedQuery = data.spellCheckedQuery 
        let totalNumResults = data.totalNumResults 
        let custom = data.custom 

        print( 
            """ 
            SemanticSearch: 
              spellCheckedQuery=\(String(describing: spellCheckedQuery)) 
              totalNumResults=\(String(describing: totalNumResults)) 
              custom=\(String(describing: custom)) 
            """ 
        ) 

        // MARK: - Product Slots 
        data.slots?.forEach { slot in 
            let slotId = slot.slotId 
            let sku = slot.sku 
            print("SemanticSearch: slotId=\(String(describing: slotId)), sku=\(String(describing: sku))") 

            guard let product = slot.productData as? DefaultRecsProductData else { 
                print("SemanticSearch: productData is not DefaultRecsProductData for slot \(String(describing: slotId))") 
                return 
            } 

            let groupId = product.groupId 
            let name = product.name 
            let url = product.url 
            let price = product.price 
            let inStock = product.inStock 
            let imageUrl = product.imageUrl 
            let categories = product.categories 
            let keywords = product.keywords 

            print( 
                """ 
                SemanticSearch product: 
                  groupId=\(String(describing: groupId)), 
                  name=\(String(describing: name)), 
                  price=\(String(describing: price)), 
                  inStock=\(String(describing: inStock)), 
                  url=\(String(describing: url)) 
                """ 
            ) 

            print( 
                """ 
                SemanticSearch product details: 
                  imageUrl=\(String(describing: imageUrl)), 
                  categories=\(String(describing: categories)), 
                  keywords=\(String(describing: keywords)) 
                """ 
            ) 
        } 

        // MARK: - Facets 
        data.facets?.forEach { facet in 
            let column = facet.column 
            let displayName = facet.displayName 
            let valuesType = facet.valuesType 

            print( 
                """ 
                SemanticSearch facet: 
                  column=\(column), 
                  displayName=\(String(describing: displayName)), 
                  valuesType=\(valuesType) 
                """ 
            ) 

            if let numberFacet = facet as? NumberFacet { 
                let min = numberFacet.min 
                let max = numberFacet.max 
                print("SemanticSearch number facet: min=\(String(describing: min)), max=\(String(describing: max))") 

            } else if let stringFacet = facet as? StringFacet { 
                stringFacet.values.forEach { value in 
                    let name = value.name 
                    let count = value.count 
                    print("SemanticSearch string facet: name=\(name), count=\(count)") 
                } 
            } 
        } 

        // MARK: - Warnings 
        if result.status == .warning, let warnings = result.warnings { 
            warnings.forEach { print("SemanticSearch warning: \($0)") } 
        } 

    case .error: 
        if let error = result.error { 
            print("SemanticSearch error: \(error)") 

        } else { 
            print("SemanticSearch error: unknown error") 
        } 
    } 
} 

Visual Search

Parameters

ParameterData Structure TypeMandatory?Description
pagePageYesProvides screen context for the visual search request
imageBase64StringYesBase64‑encoded image to use for product matching
filters[Filter]?NoOptional attribute filters (brand, color, price range, and so on)
sortBySortOptions?NoSorting rules (for example, by field or by relevance)
pageAttributes[String: PageAttribute]?NoKey–value attributes for campaign targeting or search context
branchIdString?NoBranch identifier for multi‑branch setups (stores, financial institutions, restaurants)
optionsSearchOptions?NoAdditional search configurations (for example, return analytics metadata)

Code example

func visualSearch() async { 
    let result = await DYSdk.shared().search.visualSearch( 
        page: Page.homePage(pageLocation: "location"), 
        imageBase64: "imageBase64", 
        filters: [Filter.stringFilter("color", ["blue"])], 
        sortBy: SortOptions.byField("relevance", SortOrderType.desc), 
        pageAttributes: ["source": PageAttribute("mobile")], 
        branchId: "visual-search-branch", 
        options: SearchOptions(returnAnalyticsMetadata: true) 
    ) 

    switch result.status { 
    case .success, .warning: 
        guard 
            let choice = result.choice, 
            let variation = choice.variations.first 
        else { 
            print("VisualSearch: No choice or variation returned for visual search result") 
            return 
        } 

        let data = variation.payload.data 
        let totalNumResults = data.totalNumResults 
        let custom = data.custom 

        print("VisualSearch: totalNumResults=\(String(describing: totalNumResults)), custom=\(String(describing: custom))")  

        // Handle product slots 
        data.slots?.forEach { slot in 
            let slotId = slot.slotId 
            let sku = slot.sku 

            print("VisualSearch: slotId=\(String(describing: slotId)), sku=\(String(describing: sku))") 

            guard let productData = slot.productData as? DefaultRecsProductData else { 
                print("VisualSearch: productData is not DefaultRecsProductData for slot \(String(describing: slotId))") 
                return 
            } 

            let groupId = productData.groupId 
            let name = productData.name 
            let url = productData.url 
            let price = productData.price 
            let inStock = productData.inStock 
            let imageUrl = productData.imageUrl 
            let categories = productData.categories 
            let keywords = productData.keywords 

            print( 
                """ 
                VisualSearch product: 
                  groupId=\(String(describing: groupId)), 
                  name=\(String(describing: name)), 
                  price=\(String(describing: price)), 
                  inStock=\(String(describing: inStock)), 
                  url=\(String(describing: url)) 
                """ 
            ) 

            print( 
                """ 
                VisualSearch product details: 
                  imageUrl=\(String(describing: imageUrl)), 
                  categories=\(String(describing: categories)), 
                  keywords=\(String(describing: keywords)) 
                """ 
            ) 
        } 

        // Handle facets 
        data.facets?.forEach { facet in 
            let column = facet.column 
            let displayName = facet.displayName 
            let valuesType = facet.valuesType 

            print( 
                """ 
                VisualSearch facet: 
                  column=\(column), 
                  displayName=\(String(describing: displayName)), 
                  valuesType=\(valuesType) 
                """ 
            ) 

            if let numberFacet = facet as? NumberFacet { 
                let min = numberFacet.min 
                let max = numberFacet.max 
                print("VisualSearch number facet range: min=\(String(describing: min)), max=\(String(describing: max))") 

            } else if let stringFacet = facet as? StringFacet { 
                stringFacet.values.forEach { value in 
                    let name = value.name 
                    let count = value.count 
                    print("VisualSearch string facet value: name=\(name), count=\(count)") 
                } 
            } 
        } 

        // Log warnings (if any) in the .warning case 
        if result.status == .warning, let warnings = result.warnings { 
            warnings.forEach { warning in 
                print("VisualSearch warning: \(warning)") 
            } 
        } 

    case .error: 
        if let error = result.error { 
            print("VisualSearch error: \(error)") 
        } else { 
            print("VisualSearch error: unknown error") 
        } 
    } 
}