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
| Parameter | Data Structure Type | Mandatory? | Description |
|---|---|---|---|
| page | Page | Yes | Information about the current page (screen name, referrer, categories) |
| text | String | Yes | The natural‑language query to process using Semantic Search |
| filters | [Filter]? | No | Optional attribute filters (brand, color, price range, and so on) |
| pagination | Pagination | Yes | Defines number of items and offset for pagination |
| sortBy | SortOptions? | No | Sorting rules (for example, by field or by relevance) |
| pageAttributes | [String: PageAttribute]? | No | Key–value attributes for campaign targeting or search context |
| branchId | String? | No | Branch identifier for multi‑branch setups (stores, financial institutions, restaurants) |
| options | SearchOptions? | No | Additional 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
| Parameter | Data Structure Type | Mandatory? | Description |
|---|---|---|---|
| page | Page | Yes | Provides screen context for the visual search request |
| imageBase64 | String | Yes | Base64‑encoded image to use for product matching |
| filters | [Filter]? | No | Optional attribute filters (brand, color, price range, and so on) |
| sortBy | SortOptions? | No | Sorting rules (for example, by field or by relevance) |
| pageAttributes | [String: PageAttribute]? | No | Key–value attributes for campaign targeting or search context |
| branchId | String? | No | Branch identifier for multi‑branch setups (stores, financial institutions, restaurants) |
| options | SearchOptions? | No | Additional 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")
}
}
} Updated 5 days ago