Constructor.io Swift Client
An iOS Client for Constructor.io. Constructor.io provides search as a service that optimizes results using artificial intelligence (including natural language processing, re-ranking to optimize for conversions, and user personalization).
Documentation
Full API documentation is available on Github Pages
1. Import
1.a Import using CocoaPods
First make sure you have CocoaPods installed. Then create an empty text file in your project’s root directory called ‘Podfile’. Add the following lines to the file:
target ‘YOUR_TARGET_NAME’ do
pod ‘ConstructorAutocomplete'
end
Open the terminal (make sure you’re located in the project root) and type
pod install
1.b Import using Carthage
First, make sure you have Carthage installed. Then create an empty text file called ‘Cartfile’ in your project root directory. Now, add the following lines:
github "Constructor-io/constructorio-client-swift"
Open the terminal (make sure you’re located in the project root) and type
carthage update
Drag the ConstructorIO.framework from Carthage/Build/iOS into your project and link it with your application target. Also, make sure to copy the framework by adding a new Copy Files phase.
1.c Import using Swift Package Manager
To install using SwiftPM. Go into Xcode and click on File > Add Package Dependency and enter Constructor’s Swift Client repository URL.
If you develop frameworks and would like to utilize the Swift API Client as a dependency, update your Package.swift file with the following:
let package = Package(
// 3.3.13 ..< 4.0.0
dependencies: [
.package(url: "https://github.com/constructor-io/constructorio-client-swift", from: "3.3.13")
],
// ...
)
Lastly, you’ll just need to import ConstructorAutocomplete to your source files to begin using it.
2. Retrieve an API key
You can find this in your Constructor.io dashboard. Contact sales if you’d like to sign up, or support if you believe your company already has an account.
3. Create a Client Instance
Make sure to import the ConstructorAutocomplete module at the top of your source file and then write the following
// Create the client config
let config = ConstructorIOConfig(
apiKey: "YOUR API KEY",
baseURL: "https://ac.cnstrc.com", // default service url. protocol must be specified (i.e. https)
resultCount: AutocompleteResultCount(numResultsForSection: ["Search Suggestions" : 3, "Products" : 0])
)
// Create the client instance
let constructorIO = ConstructorIO(config: config)
// Set the user ID (for a logged in user) used for cross device personalization
constructorIO.userID = "abcdefghijk-123"
4. Retrieving the clientID and sessionID
If you are retrieving results from your backend servers instead of direclty using our SDK, there are certain personalization parameters that are needed to be passed along with your requests. And those parameters can be accessed from the Constructor instance.
- Client Id
let constructorClientId = constructorIO.clientID
- Session Id
let constructorSessionId = constructorIO.sessionID
In most cases, you will want to store those parameters as cookies preferably as ConstructorioID_client_id and ConstructorioID_session_id to be sent with your requests to your backend servers.
5. Setting test cell information for A/B tests
When A/B testing, it is important to specify which cell the user is being assigned to. Information about the test cell can be set through the ConstructorIOConfig object.
let testCell = CIOABTestCell
let config = ConstructorIOConfig(
apiKey: "YOUR API KEY",
baseURL: "https://ac.cnstrc.com", // default service url. protocol must be specified (i.e. https)
testCells: [CIOABTestCell(key: "constructorio_test", value: "control_1")]
)
// Create the client instance
let constructorIO = ConstructorIO(config: config)
// The test cells in the config can be edited after instantiating the client instance
constructorIO.config.testCells = [CIOABTestCell(key: "constructorio_test", value: "experiment_1")]
6. Request Autocomplete Results
let query = CIOAutocompleteQuery(query: "apple", numResultsForSection: ["Products": 6, "Search Suggestions": 8])
constructorIO.autocomplete(forQuery: query) { (response) in
let data = response.data!
let error = response.error!
// ...
}
7. Request Search Results
let filters = CIOQueryFilters(groupFilter: "Bread", facetFilters: [
(key: "Nutrition", value: "Organic"),
(key: "Nutrition", value: "Natural"),
(key: "Nutrition", value: "Whole-grain")
])
let query = CIOSearchQuery(query: "Dave's Bread", page: 5, filters: filters)
// Specify the sort order in which groups are returned
let groupsSortOption = CIOGroupsSortOption(sortBy: CIOGroupsSortBy.value, sortOrder: CIOGroupsSortOrder.ascending)
constructorIO.search(forQuery: query, filters: filters, groupsSortOption: groupsSortOption) { (response) in
let data = response.data!
let error = response.error!
// ...
}
8. Request Browse Results
let query = CIOBrowseQuery(filterName: "group_id", filterValue: "sales")
// Specify the sort order in which groups are returned
let groupsSortOption = CIOGroupsSortOption(sortBy: CIOGroupsSortBy.value, sortOrder: CIOGroupsSortOrder.ascending)
constructorIO.browse(forQuery: query, groupsSortOption: groupsSortOption) { (response) in
let data = response.data!
let error = response.error!
// ...
}
9. Request Recommendation Results
let query = CIORecommendationsQuery(podID: "pdp_best_sellers", filters: filters)
constructorIO.recommendations(forQuery: query) { (response) in
let data = response.data!
let error = response.error!
// ...
}
With an item id (and variation id) for the alternative/complementary items recommendations strategy
let itemId = "P18232"
let variationId = "P18232-123"
let query = CIORecommendationsQuery(podID: "pdp_complementary_items", itemID: itemId, variationID: variationId)
constructorIO.recommendations(forQuery: query) { (response) in
let data = response.data!
let error = response.error!
// ...
}
With filters for the filtered item recommendations strategy
let filters = CIOQueryFilters(groupFilter: "cat_1234", facetFilters: [
(key: "Nutrition", value: "Organic"),
(key: "Nutrition", value: "Natural"),
(key: "Brand", value: "Kroger")
])
let query = CIORecommendationsQuery(podID: "pdp_filtered_items", filters: filters)
constructorIO.recommendations(forQuery: query) { (response) in
let data = response.data!
let error = response.error!
// ...
}
10. Request Quiz Next Question
let query = CIOQuizQuery(quizID: "quiz-1", answers: [["1"], ["2"]])
constructorIO.getQuizNextQuestion(forQuery: query) { (response) in
let data = response.data!
let error = response.error!
// ...
}
11. Request Quiz Results
let query = CIOQuizQuery(quizID: "quiz-1", answers: [["1"], ["2"]])
constructorIO.getQuizResults(forQuery: query) { (response) in
let data = response.data!
let error = response.error!
// ...
}
12. Instrument Behavioral Events
The iOS Client sends behavioral events to Constructor.io in order to continuously learn and improve results for future Autosuggest and Search requests. The Client only sends events in response to being called by the consuming app or in response to user interaction . For example, if the consuming app never calls the SDK code, no events will be sent. Besides the explicitly passed in event parameters, all user events contain a GUID based user ID that the client sets to identify the user as well as a session ID.
Three types of these events exist:
- General Events are sent as needed when an instance of the Client is created or initialized
- Autocomplete Events measure user interaction with autocomplete results
- Search Events measure user interaction with search results
- Browse Events measure user interaction with browse results
- Recommendation Events measure user interaction with recommendations
- Quiz Events measure user interaction with quiz results
- Conversion Events measure user events like
add to cartorpurchase - AI Shopping Agent Events measure user interaction with AI Shopping Agent results
- Product Insights Agent Events measure user interaction with the Product Insights Agent on product detail pages
Autocomplete Events
// Track when the user focuses into the search bar
constructorIO.trackInputFocus(searchTerm: "")
// Track when the user selects an autocomplete suggestion
constructorIO.trackAutocompleteSelect(searchTerm: "toothpicks", originalQuery: "tooth", sectionName: "Search Suggestions", group: CIOGroup(displayName: "Dental Health", groupID: "dental-92dk2", path: "health-2911e/dental-92dk2"), resultID: "179b8a0e-3799-4a31-be87-127b06871de2")
// Track when the user submits a search (either by selecting a suggestion or not selecting a suggestion)
constructorIO.trackSearchSubmit(searchTerm: "toothpicks", originalQuery: "tooth")
Search Events
// Track when search results are loaded into view (customer ID's are the ID's of shown items)
constructorIO.trackSearchResultsLoaded(searchTerm: "tooth", resultCount: 789, customerIDs: ["1234567-AB", "1234765-CD", "1234576-DE"])
// Track when a search result is clicked
constructorIO.trackSearchResultClick(itemName: "Fashionable Toothpicks", customerID: "1234567-AB", variationID: "1234567-AB-7463", searchTerm: "tooth", sectionName: "Products", resultID: "179b8a0e-3799-4a31-be87-127b06871de2")
Sponsored Search Events
// Track when sponsored search results are loaded into view (customer ID's are the ID's of shown items)
constructorIO.trackSearchResultsLoaded(searchTerm: "tooth", resultCount: 789, items: [CIOItem(customerID: "1234567-AB", slCampaignID: "campaign-1", slCampaignOwner: "owner-1")])
// Track when a sponsored search result is clicked
constructorIO.trackSearchResultClick(itemName: "Fashionable Toothpicks", customerID: "1234567-AB", searchTerm: "tooth", sectionName: "Products", slCampaignID: "campaign-1", slCampaignOwner: "owner-1")
Browse Events
// Track when browse results are loaded into view
constructorIO.trackBrowseResultsLoaded(filterName: "group_id", filterValue: "sales", resultCount: 674)
// Track when browse results are loaded into view with items array (supported in v3.1.2 and above)
constructorIO.trackBrowseResultsLoaded(filterName: "group_id", filterValue: "sales", resultCount: 674, customerIDs: ["1234567-AB", "1234765-CD", "1234576-DE"])
// Track when a browse result is clicked
constructorIO.trackBrowseResultClick(filterName: "group_id", filterValue: "sales", customerID: "7654321-BA", variationID: "7654321-BA-738", resultPositionOnPage: 4, sectionName: "Products", resultID: "179b8a0e-3799-4a31-be87-127b06871de2")
Sponsored Browse Events
// Track when sponsored browse results are loaded into view.
constructorIO.trackBrowseResultsLoaded(filterName: "group_id", filterValue: "sales", resultCount: "674", items: CIOItem(customerID: "10001", slCampaignID: "campaign-1", slCampaignOwner: "owner-1"))
// Track when a sponsored browse result is clicked
constructorIO.trackBrowseResultClick(filterName: "group_id", filterValue: "sales", customerID: "7654321-BA", variationID: "7654321-BA-738", resultPositionOnPage: 4, sectionName: "Products", slCampaignID: "campaign-1", slCampaignOwner: "owner-1")
Recommendations Events
// Track when recommendation results are viewed
constructorIO.trackRecommendationResultsView(podID: "pdp_best_sellers", numResultsViewed: 5, resultPage: 1, resultCount: 10, resultID: "179b8a0e-3799-4a31-be87-127b06871de2")
// Track when recommendation results are viewed with items array (supported in v3.3.13 and above)
constructorIO.trackRecommendationResultsView(podID: "pdp_best_sellers", numResultsViewed: 5, customerIDs: ["1234567-AB", "1234765-CD", "1234576-DE"], resultPage: 1, resultCount: 10, resultID: "179b8a0e-3799-4a31-be87-127b06871de2")
// Track when a recomendation result is clicked
constructorIO.trackRecommendationResultClick(podID: "pdp_best_sellers", strategyID: "best_sellers", customerID: "P183021", variationID: "7281930", numResultsPerPage: 30, resultPage: 1, resultCount: 15, resultPositionOnPage: 1, resultID: "179b8a0e-3799-4a31-be87-127b06871de2")
Quiz Events
// Track when a quiz result is clicked
ConstructorIo.trackQuizResultClick(quizID: "coffee-quiz", quizVersionID: "1231244", quizSessionID: "123", customerID: "123", itemName: "espresso")
// Track when quiz results are loaded
ConstructorIo.trackQuizResultsLoaded(quizID: "coffee-quiz", quizVersionID: "1231244", quizSessionID: "123", resultCount: 20)
// Track when a quiz result is converted on
ConstructorIo.trackQuizConversion(quizID: "coffee-quiz", quizVersionID: "1231244", quizSessionID: "123", customerID: "123", variationID: "167", itemName: "espresso", revenue: 20.0)
AI Shopping Agent Events
Supported in v4.7.0 and above. intentResultID is the intent result ID from the AI Shopping Agent response. searchResultID is the result ID of the search result that the item belongs to.
// Track when the user submits a question to the agent
constructorIO.trackAgentSubmit(intent: "show me running shoes")
// Track when agent results start loading
constructorIO.trackAgentResultLoadStarted(intent: "show me running shoes", intentResultID: "2b5f8c1e-6a0b-4c2d-9f3e-1a2b3c4d5e6f")
// Track when agent results finish loading
constructorIO.trackAgentResultLoadFinished(intent: "show me running shoes", searchResultCount: 3, intentResultID: "2b5f8c1e-6a0b-4c2d-9f3e-1a2b3c4d5e6f")
// Track when the user views the products in an agent result
let agentItems = [
CIOItem(customerID: "1234567-AB", itemName: "Trail Runner"),
CIOItem(customerID: "1234765-CD", itemName: "Road Runner")
]
constructorIO.trackAgentResultView(intent: "show me running shoes", searchResultID: "179b8a0e-3799-4a31-be87-127b06871de2", numResultsViewed: 2, items: agentItems, intentResultID: "2b5f8c1e-6a0b-4c2d-9f3e-1a2b3c4d5e6f")
// Track when the user clicks a product in an agent result
constructorIO.trackAgentResultClick(intent: "show me running shoes", searchResultID: "179b8a0e-3799-4a31-be87-127b06871de2", itemID: "1234567-AB", itemName: "Trail Runner", intentResultID: "2b5f8c1e-6a0b-4c2d-9f3e-1a2b3c4d5e6f")
// Track when the user selects a search term that the agent suggested
constructorIO.trackAgentSearchSubmit(intent: "show me running shoes", searchTerm: "trail running shoes", searchResultID: "179b8a0e-3799-4a31-be87-127b06871de2", intentResultID: "2b5f8c1e-6a0b-4c2d-9f3e-1a2b3c4d5e6f")
Product Insights Agent Events
Each event takes a request object. itemID is the ID of the product whose page the Product Insights Agent is on (for trackProductInsightsAgentResultClick, it is the clicked recommendation and seedItemID is the page’s product). qnaResultID is the answer result ID from the Product Insights Agent response. Every request also accepts itemName, variationID, threadID, sectionName and analyticsTags.
let questions = [
CIOProductInsightsAgentQuestion(question: "Why choose this?"),
CIOProductInsightsAgentQuestion(question: "How is this product made?", questionTopic: "materials")
]
// Track when the Product Insights Agent appears in the visible part of the page
constructorIO.trackProductInsightsAgentView(CIOTrackProductInsightsAgentViewRequest(itemID: "1234567-AB", questions: questions, itemName: "Trail Runner"))
// Track the periods of time during which the Product Insights Agent was visible
let viewStartDate = Date()
let viewEndDate = viewStartDate.addingTimeInterval(5)
let viewTimespans = [CIOProductInsightsAgentViewTimespan(start: viewStartDate, end: viewEndDate)]
constructorIO.trackProductInsightsAgentViews(CIOTrackProductInsightsAgentViewsRequest(itemID: "1234567-AB", questions: questions, viewTimespans: viewTimespans))
// Track when the Product Insights Agent disappears from the visible part of the page
constructorIO.trackProductInsightsAgentOutOfView(CIOTrackProductInsightsAgentOutOfViewRequest(itemID: "1234567-AB"))
// Track when the user focuses on the Product Insights Agent input
constructorIO.trackProductInsightsAgentFocus(CIOTrackProductInsightsAgentFocusRequest(itemID: "1234567-AB"))
// Track when the user clicks on a suggested question
constructorIO.trackProductInsightsAgentQuestionClick(CIOTrackProductInsightsAgentQuestionClickRequest(itemID: "1234567-AB", question: "Why choose this?"))
// Track when the user submits a question
constructorIO.trackProductInsightsAgentQuestionSubmit(CIOTrackProductInsightsAgentQuestionSubmitRequest(itemID: "1234567-AB", question: "Is this waterproof?", questionTopic: "materials"))
// Track when the user views an answer (answerText over 2000 characters is truncated; items and followUpQuestions are capped at 100)
constructorIO.trackProductInsightsAgentAnswerView(CIOTrackProductInsightsAgentAnswerViewRequest(itemID: "1234567-AB", question: "Is this waterproof?", answerText: "Yes, it has a waterproof membrane.", qnaResultID: "8c1e2b5f-0b6a-2d4c-3e9f-6f5e4d3c2b1a", items: [CIOItem(customerID: "1234765-CD", itemName: "Road Runner")], followUpQuestions: ["What sizes are available?"]))
// Track when the user gives feedback on an answer
constructorIO.trackProductInsightsAgentAnswerFeedback(CIOTrackProductInsightsAgentAnswerFeedbackRequest(itemID: "1234567-AB", feedbackLabel: .thumbsUp, qnaResultID: "8c1e2b5f-0b6a-2d4c-3e9f-6f5e4d3c2b1a"))
// Track when the user clicks a product recommended in an answer
constructorIO.trackProductInsightsAgentResultClick(CIOTrackProductInsightsAgentResultClickRequest(itemID: "1234765-CD", question: "Is this waterproof?", seedItemID: "1234567-AB", position: 0, qnaResultID: "8c1e2b5f-0b6a-2d4c-3e9f-6f5e4d3c2b1a", itemName: "Road Runner"))
Media Impression Events
// Track when a media impression is viewed
ConstructorIo.trackMediaImpressionView(bannerAdId: "banner-ad-id", placementId: "placement-id")
// Track when a media impression is clicked
ConstructorIo.trackMediaImpressionClick(bannerAdId: "banner-ad-id", placementId: "placement-id")
Results Impression Events
// Track when items are viewably impressed (50% visible for 1 second per MRC guidelines)
let items = [
CIOItem(customerID: "item-123", itemName: "Blue Widget"),
CIOItem(customerID: "item-456", itemName: "Red Widget", variationID: "var-789")
]
constructorIO.trackResultsImpressionView(items: items, searchTerm: "widget")
Conversion Events
// Track when an item converts (a.k.a. is added to cart) regardless of the user journey that led to adding to cart
constructorIO.trackConversion(itemName: "Fashionable Toothpicks", customerID: "1234567-AB", variationID: "1234567-AB-47398", revenue: 12.99, searchTerm: "tooth", conversionType: "add_to_cart")
// Track when items are purchased
constructorIO.trackPurchase(customerIDs: ["123-AB", "456-CD"], revenue: 34.49, orderID: "343-315")
// Tracking items w/ variations in purchases (supported in v2.5.5 and above)
let purchaseItems = [
CIOItem(customerID: "custID1", variationID: "varID1", quantity: 2),
CIOItem(customerID: "custID2", variationID: "varID2", quantity: 3)
]
constructorIO.trackPurchase(items: purchaseItems, revenue: 93.89, orderID: "423-2432")
Miscellaneous Events
// Track when a product detail page is loaded (a.k.a after a user clicks on an item)
constructorIO.trackItemDetailLoad(customerID: "10001", itemName: "item1", variationID: "var1", sectionName: "Products")
// Track when a generic result is clicked
constructorIO.trackGenericResultClick(itemID: "product123", itemName: "Product Name", variationID: "var456", sectionName: "Products")