Introduction
Welcome to PersonaClick API Reference. This reference will help you to create new, more effective S2S or M2S integration.
Our API is RESTful and you can use any language to work with it.
We provide examples as:
- cURL
- Javascript (web)
- Swift (iOS)
- Kotlin (Android)
- Java (Android)
Authentication
To authorize, send all requests with shop_id
parameter. You can send it both in POST and GET requests.
This parameter identifies your shop.
Some operations require secret API key. You'll provide it in shop_secret
parameter.
Initialize
Setup
# No setup is needed
// Put this code in the <head> section of web page.
// During initialization, the cookieless parameter is set to false by default.
// If cookies are unavailable in the browser, the cookieless parameter is set to true.
// When cookieless is true, local storage is used instead of cookies.
(function(r){
window.personaclick=window.personaclick||function(){(window.personaclick.q=window.personaclick.q||[]).push(arguments)};
var c="https://cdn.personaclick.com",v="/v3.js",s={link:[{href:c,rel:"dns-prefetch"},{href:c,rel:"preconnect"},{href:c+v,rel:"preload",as:"script"}],script:[{src:c+v,async:""}]};
Object.keys(s).forEach(function(c){s[c].forEach(function(d){var e=document.createElement(c),a;for(a in d)e.setAttribute(a,d[a]);document.head.appendChild(e)})});
})();
// Cocoapods
target '...' do
// ...
// Add this
pod 'PersonaClick'
// ...
end
// ... and this (to be able to run it on simulators):
post_install do |installer|
installer.pods_project.build_configurations.each do |config|
config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64"
end
end
// Swift package manager (XCode >= 11)
// 1. Click File menu
// 2. Swift Packages
// 3. Add Package Dependency...
// 4. Specify the git URL for SDK repo: https://github.com/PersonaClick/ios-sdk.git
// 1. Add to dependencies:
dependencies {
implementation 'com.rees46:rees46-sdk:+'
implementation 'com.google.firebase:firebase-bom:32.7.0'
implementation 'com.google.firebase:firebase-messaging:23.4.1'
implementation 'com.google.dagger:dagger:2.51.1'
kapt 'com.google.dagger:dagger-compiler:2.48'
}
// Add to plugins:
plugins {
id 'kotlin-kapt'
}
// 2. Append to your project build.gradle
buildscript {
dependencies {
...
classpath 'com.google.gms:google-services:4.3.10'
}
}
// 3. Append to your app module `build.gradle` after line `id 'com.android.application'`
plugins {
id 'com.google.gms.google-services'
id 'org.jetbrains.kotlin.android'
}
// 4. Create your app in the Firebase console
// and copy file google-services.json to your app root path.
// Sync gradle now.
// 5. Library versions used in the SDK:
// Java 22
// Kotlin 2.0.0
// Gradle 8.8
// Android Gradle Plugin 8.5.1
// 1. Add to dependencies:
implementation 'com.personaclick:personaclick-sdk:+'
implementation 'com.google.firebase:firebase-bom:29.0.3'
implementation 'com.google.firebase:firebase-messaging:23.0.0'
// 2. Append to your project build.gradle
buildscript {
dependencies {
...
classpath 'com.google.gms:google-services:4.3.10'
}
}
// 3. Append to your app module build.gradle after line apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
// 4. Create your app in the Firebase console
// and copy file google-services.json to your app root path.
// Sync gradle now.
// 5. Library versions used in the SDK:
// Java 22
// Kotlin 2.0.0
// Gradle 8.8
// Android Gradle Plugin 8.5.1
// If you are using version 1.8 or above, you don't need to use permissions like SCHEDULE_EXACT_ALARM or USE_EXACT_ALARM.
// The notifee dependency introduced in version 1.7.1 also isn't required starting from version 1.8 of the SDK.
// Add required packages:
yarn add @personaclick/react-native-sdk
yarn add @react-native-async-storage/async-storage
yarn add react-native-device-info
// For push notifications also add:
yarn add react-native-push-notification
yarn add @react-native-firebase/app
yarn add @react-native-firebase/messaging
// On application launch initialize the SDK:
import PersonaClick from '@personaclick/react-native-sdk';
...
// The parameter autoSendPushToken is responsible for automatically sending the push notification token upon initialization.
// Its default value is true, meaning the token will be sent automatically.
// Set it to false if you want to manage token sending manually.
const sdk = new PersonaClick("YOUR_SHOP_ID", "stream", "debug", autoSendPushToken);
// Initialization is async, so you have a method to test, if SDK is initialized or not:
sdk.isInit(); // returns true/false
// To collect push tokens, you have to make some adjustments to the app:
// ** For iOS:
// Open your /ios/{projectName}/AppDelegate.m file, and add the following: At the top of the file, import the Firebase SDK:
import <Firebase.h>
// Open a terminal window and navigate to the location of the Xcode project for your app
cd ios/
pod install
// ** For Android
// In your android/build.gradle
buildscript {
dependencies {
...
//Add this \/
classpath 'com.google.gms:google-services:4.3.4'
}
}
// In your android/app/build.gradle add
apply plugin: 'com.google.gms.google-services'
Before using API you have to setup SDK.
Start session
curl https://api.personaclick.com/init?did=DEVICE_ID&shop_id=SHOP_ID&v=3&sid=SEANCE_ID&referrer=REF_URL
// Put this line right after setup code
personaclick('init', 'SHOP_ID', 'STREAM', success, failure);
// Cookie-less mode
const cookieLess = true;
personaclick('init', 'SHOP_ID', 'STREAM', success, failure, cookieLess)
import PersonaClick
var sdk = createPersonalizationSDK(shopId: "SHOP_ID", stream: "ios", userEmail: "[email protected]", userPhone: "String", userLoyaltyId: "String", apiDomain: "String", enableLogs: Bool, autoSendPushToken: Bool)
class SampleApplication: Application() {
override fun onCreate() {
super.onCreate()
//Initialize
val sdk = Personaсlick.getInstance()
Personaсlick.initialize(applicationContext, SHOP_ID)
//Notification callback
sdk.setOnMessageListener(object : OnMessageListener {
override fun onMessage(data: Map<String, String>) {
//----->
//Show your custom notification
//----->
}
})
}
}
// 2. For On-Premise integration need use initialize with custom api domain:
Personaсlick.initialize(applicationContext, SHOP_ID, API_DOMAIN)
// Initialization with token automatic sending flag
Personaсlick.initialize(applicationContext, SHOP_ID, API_DOMAIN, autoSendPushToken)
// 3. Check AndroidManifest.xml and add android:name=".SampleApplication" to application item.
<application
...
android:name=".SampleApplication"
public class SampleApplication extends Application {
public void onCreate() {
super.onCreate();
//Initialize
Personaсlick.initialize(getApplicationContext(), SHOP_ID);
//Notification callback
Personaсlick.setOnMessageListener(new MessagingService.OnMessageListener() {
@Override
public void onMessage(Map<String, String> data) {
//----->
//Show your custom notification
//----->
}
});
}
}
// 2. For On-Premise integration need use initialize with custom api domain:
Personaсlick.initialize(getApplicationContext(), SHOP_ID, API_DOMAIN);
// 3. Check AndroidManifest.xml and add android:name=".SampleApplication" to application item.
<application
...
android:name=".SampleApplication"
GET https://api.personaclick.com/init
Before using SDK or API you have to initialize SDK. Initialization takes current user identifier and requests API for project settings and this user preferences.
Depending on platform there are different requirements when to run init:
- cURL: on every page render
- Web: on every opened page (even for single-page applications)
- iOS: on each application launch
- Android: on each application launch
If you don't have device identifier (first launch on new device), you have to request API's init
method to generate new one. Store this identifier (it's named did
) in local storage of mobile application or in database: you'll need it for the future requests to API.
Query Parameters
Parameter | Required | Description |
---|---|---|
shop_id | true | Your API key |
did | false | Is mandatory if you have it. Request without did will generate new one in our DB. Use it as device ID for future requests. |
v | true | Version. Just use 3 as value. |
sid | true | User's temporary identifier for the current session. Must be regenerated every time user starts new session. Unique string. This parameter is handled automatically in all SDKs. |
referrer | false | Referrer page URL for web integration. |
tz | false | Timezone offset (integer, positive or negative number as difference with GMT). |
stream | false | Data stream code. Alphanumeric string (letters, numbers only). Max length: 16. Default: null (means "web"). Can be "ios", "android" or any other string. Used to distinguish between mobile apps, web and other events sources. |
API response
Name | Type | Description |
---|---|---|
did | string | Device id |
seance | string | Seance |
currency | string | Currency |
email_collector | boolean | Enable or disable email_collector service |
has_email | boolean | User has an email address |
recommendations | boolean | Recommendations are enabled or disabled |
lazy_load | boolean | Lazy load option is enabled or disabled |
auto_css_recommender | boolean | auto_css_recommender is enabled or disabled |
cms | string | CMS |
snippets | array | List of snippets |
search | object | Objects with search configuration |
* enabled - boolean value | ||
* landing - string with a page address | ||
* type - string with a type of search: full, instant, blank | ||
* settings - object with settings that can be configured in dashboard | ||
- redirects - object inside settings with redirects. Format "string":"string". Redirect request and page address | ||
- suggestions_title - a string with suggestion title | ||
- categories_title - a string with category title | ||
- brands_title - a string with brand title | ||
- filters_title - a string with filter title | ||
- items_title - a string with items title | ||
- show_all_title - a string with all titles that match query | ||
- last_queries_title - a string with recent search | ||
- last_products_title - a string with a recently viewed products | ||
- empty_title - a string with message that nothing was found | ||
- book_author_title - a string with book author | ||
- enable_full_search - boolean value | ||
- append_to_body - boolean value | ||
- enable_last_queries - boolean value | ||
- enable_old_price - boolean value | ||
- popular_links_title - string. Popular search queries | ||
- popular_categories_title - string. Popular category title | ||
- popular_brands_title - string. Popular brands | ||
- price_filter_name - string. Price filter. Affected by localization settings | ||
- price_filter_from - string. Minimum price filer. Affected by localization settings | ||
- price_filter_to - string. Maximum price filter. Affected by localization settings | ||
- sort_by_name - string. Sorting by name. Affected by localization settings | ||
- sort_dir_desc - string. Sorting direction. Descending. Affected by localization settings | ||
- sort_dir_asc - string. Sorting direction. Ascending. Affected by localization settings | ||
- sort_by_popular - string. Sorting by popularity. Affected by localization settings | ||
- sort_by_price - string. Sorting by price. Affected by localization settings | ||
- sort_by_discount - string. Sorting by discount. Affected by localization settings | ||
- sort_by_sales_rate - string. Sorting by sales. Affected by localization settings | ||
- sort_by_new - string. Affected by localization settings | ||
web_push_settings | object | Object with web-push settings. |
* public_key - a string with the shop's public key | ||
* safari_enabled - a boolean value | ||
* safari_id - a string. If safari_enable is false. The string is empty | ||
* service_worker - a string with a path to the service worker | ||
recone | boolean | A boolean value |
Import
Information about import.
Update category
curl https://api.personaclick.com/import/categories
No implementation needed
No implementation needed
No implementaion needed
No implementaion needed
No implementaion needed
HTTP Request
PUT https://api.personaclick.com/import/categories
Query Parameters
Parameter | Required | Description |
---|---|---|
shop_id | true | Your API key |
shop_secret | true | Your secret key |
categories | true | An array with categories you want to update |
webhook | false | URL-address for HTTP request. If not empty, sends a notification with the categories update status |
This method allows to update categories that were put in the request.
It updates existing categories or creates a new one.
It does not modify categories that were not included in the request.
Events tracking
You have to track all user's behavior to get real time statistics and user's segmentation.
The platform provides different kinds of events:
- pre-defined events for main reports and segmentation
- user defined events
Events can be tracked in default mode (user did something) and assisted mode (user did something with help of some platform's instruments: search, push, email, recommendations, etc).
To track assisted events, you need to user recommendedBy
(or recommended_by
, depending on SDK) params.
Required params
All events require at least these parameters:
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
did | String | true | Device ID |
sid | String | true | User's current session |
event | String | true | Type of an event |
stream | String | false | Data stream code. Alphanumeric string (letters, numbers only). Max length: 16. Default: null (means "web"). Can be "ios", "android" or any other string. Used to distinguish between mobile apps, web and other events sources |
SDKs already handle these parameters out of the box.
Source tracking
# No code implementation
// It's done automatically. You don't have to do anything.
// Track launch from drip campaign (chain).
// Message ID and source will be provided in mobile push payload
sdk.trackSource(source: .chain, code: "MESSAGE_ID")
sdk.trackEventManager.track(Params.TrackEvent.VIEW, "37")
Personaсlick.track(Params.TrackEvent.VIEW, "37");
// See click on push notification
For mobile apps you have to track all app launches, happened by drip campaigns, mailings and push notifications. It will allow to track campaigns efficiency properly.
User viewed a product
#Full request without widget recommendation identifiers
curl 'https://api.personaclick.com/push' \
-X 'POST' \
-H 'Content-Type: application/json' \
--data-raw '{"event":"view", "shop_id":"SHOP_ID", "did":"DEVICE_ID", "sid":"SEANCE_ID", "segment":"A or B", "items":[{"id":"PRODUCT_ID"}]}'
#Full request with widget recommendation identifiers
curl 'https://api.personaclick.com/push' \
-X 'POST' \
-H 'Content-Type: application/json' \
--data-raw '{"event":"view", "shop_id":"SHOP_ID", "did":"DEVICE_ID", "sid":"SEANCE_ID", "segment":"A or B", "items":[{"id":"PRODUCT_ID"}], "recommended_by":"dynamic", "recommended_code":"UNIQUE_RECOMMENDER_CODE"}'
#Short request with minimum required parameters
curl 'https://api.personaclick.com/push' \
-X 'POST' \
-H 'Content-Type: application/json' \
--data-raw '{"event":"view", "shop_id":"SHOP_ID", "did":"DEVICE_ID", "items":[{"id":"PRODUCT_ID"}]}'
// Simple track
personaclick("track", "view", "37");
// Also notify the product is in stock (if it was not in stock)
personaclick("track", "view", {
id: "37",
stock: true
});
// Or not in stock anymore (to prevent recommending it on the next requests)
personaclick("track", "view", {
id: "37",
stock: false
});
// Track if product was viewed after click on product recommendations
personaclick("track", "view", {
id: "37",
recommended_by: "dynamic",
recommended_code: "jkIWdXSRfwVyK"
});
// Track if product was viewed after click on suggest results
personaclick("track", "view", {
id: "37",
recommended_by: "instant_search"
});
// ... or on full results
personaclick("track", "view", {
id: "37",
recommended_by: "full_search"
});
// Plain tracking
sdk.track(event: .productView(id: "PRODUCT_ID")) { trackResponse in
print("Product viewed callback")
switch trackResponse {
case let .success(response):
print("Successful")
case let .failure(error):
switch error {
case .custom(let customError):
print("Error: ", customError)
default:
print("Error: ", error.localizedDescription)
}
fatalError("Task failed successfully")
}
}
// Tracking after product recommendation click
let recData = RecomendedBy(type: .dynamic, code: "beb620922934b6ba2d6a3fb82b8b3271")
sdk.track(event: .productView(id: "PRODUCT_ID"), recommendedBy: recData) { trackResponse in
// ...
}
// View product (simple)
sdk.track("view", "37");
// View product (extended, try to avoid)
sdk.track("view", {
id: "37",
stock: true
});
// View product after click on recommender block
sdk.track("view", {
id: PRODUCT_ID,
recommended_by: 'dynamic',
recommended_code: 'UNIQUE_RECOMMENDER_CODE'
});
// View product after search results (instant search)
sdk.track("view", {
id: PRODUCT_ID,
recommended_by: 'full_search',
recommended_code: QUERY_STRING
});
// View product after search results (full search)
sdk.track("view", {
id: PRODUCT_ID,
recommended_by: 'instant_search',
recommended_code: QUERY_STRING
});
Send this event when user opens product's details page.
JS SDK syntax
Syntax |
---|
personaclick("track", "view", {params}); |
JS SDK Parameters
Parameter | Type | Requirement | Description |
---|---|---|---|
id | string | required | The ID of the product being viewed |
stock | boolean | optional | Product availability. If defined, it overwrites the value received from the product feed (XML) and HTTP-import of the product catalog. |
recommended_by | string | required in some cases | If a product from a recommendation widget was opened in a popup or a website uses a "single page" architecture, this parameter must contain the value "dynamic". |
recommended_code | string | required in some cases | If a product from the recommendations widget was opened in the pop-up or the site uses a "single page" architecture, this parameter must contain a unique code of the recommendations widget, available in the account in the "data-recommender-code" attribute for each widget. |
User viewed a category
#Full request
curl 'https://api.personaclick.com/push' \
-X 'POST' \
-H 'Content-Type: application/json' \
--data-raw '{"event":"category", "shop_id":"SHOP_ID", "did":"DEVICE_ID", "sid":"SEANCE_ID", "segment":"A or B", "category_id":"CATEGORY_ID"}'
#Short request with minimum required parameters
curl 'https://api.personaclick.com/push' \
-X 'POST' \
-H 'Content-Type: application/json' \
--data-raw '{"event":"category", "shop_id":"SHOP_ID", "did":"DEVICE_ID", "category_id":"CATEGORY_ID"}'
personaclick("track", "category", "100500");
sdk.track(event: .categoryView(id: "CATEGORY_ID")) { trackResponse in
// ... see product viewed event for details about a callback
}
sdk.trackEventManager.track(Params.TrackEvent.CATEGORY, Params().put(Params.Parameter.CATEGORY_ID, "100"))
Personaсlick.track(Params.TrackEvent.CATEGORY, (new Params()).put(Params.Parameter.CATEGORY_ID, "100"));
sdk.track("category", "100500");
Send this event when user opens category page.
JS SDK syntax
Syntax |
---|
personaclick("track", "category", category_id); |
JS SDK Parameters
Parameter | Type | Requirement | Description |
---|---|---|---|
category_id | string | required | The ID of the category being viewed |
User searched something
#Full request
curl 'https://api.personaclick.com/push' \
-X 'POST' \
-H 'Content-Type: application/json' \
--data-raw '{"event":"search", "shop_id":"SHOP_ID", "did":"DEVICE_ID", "sid":"SEANCE_ID", "segment":"A or B", "search_query":"SEARCH_QUERY"}'
#Short request with minimum required parameters
curl 'https://api.personaclick.com/push' \
-X 'POST' \
-H 'Content-Type: application/json' \
--data-raw '{"event":"search", "shop_id":"SHOP_ID", "did":"DEVICE_ID", "search_query":"SEARCH_QUERY"}'
// Added in iOS SDK 2.1.0
sdk.track(event: .search(query: "red shoes")) { trackResponse in
// ...
}
personaclick('track', 'search', search_query);
sdk.track("search", "This is a search example");
JS SDK syntax
Syntax |
---|
personaclick("track", "search", search_query); |
JS SDK Parameters
Parameter | Type | Requirement | Description |
---|---|---|---|
search_query | string | required | The search query text |
User added product to cart
#Full request for a single product without widget recommendation identifiers
curl 'https://api.personaclick.com/push' \
-X 'POST' \
-H 'Content-Type: application/json' \
--data-raw '{"event":"cart", "shop_id":"SHOP_ID", "did":"DEVICE_ID", "sid":"SEANCE_ID", "segment":"A or B", "items":[{"id":"PRODUCT_ID"}]}'
#Full request for a single product with widget recommendation identifiers
curl 'https://api.personaclick.com/push' \
-X 'POST' \
-H 'Content-Type: application/json' \
--data-raw '{"event":"cart", "shop_id":"SHOP_ID", "did":"DEVICE_ID", "sid":"SEANCE_ID", "segment":"A or B", "items":[{"id":"PRODUCT_ID"}], "recommended_by":"dynamic", "recommended_code":"UNIQUE_RECOMMENDER_CODE"}'
#Short request for a single product with minimum required parameters
curl 'https://api.personaclick.com/push' \
-X 'POST' \
-H 'Content-Type: application/json' \
--data-raw '{"event":"cart", "shop_id":"SHOP_ID", "did":"DEVICE_ID", "items":[{"id":"PRODUCT_ID"}]}'
#Full request to send the full current cart
# Clear all products on our side
curl 'https://api.personaclick.com/push' \
-X 'POST' \
-H 'Content-Type: application/json' \
--data-raw '{"event":"cart", "shop_id":"SHOP_ID", "did":"DEVICE_ID", "sid":"SEANCE_ID", "segment":"A or B", "items":[{"id":"PRODUCT_ID", "amount":"PRODUCT_QUANTITY"}], "full_cart":true}'
//Short request for a single product
personaclick('track', 'cart', 'id');
//Full request for a single product with widget recommendation identifiers
personaclick('track', 'cart', {
id: PRODUCT_ID,
amount: PRODUCT_QUANTITY,
stock: true,
recommended_by: 'dynamic',
recommended_code: 'UNIQUE_RECOMMENDER_CODE'
});
//Full request to send the full current cart
personaclick('track', 'cart', [
{
id: FIRST_PRODUCT_ID,
amount: FIRST_PRODUCT_QUANTITY
},
...
{
id: LAST_PRODUCT_ID,
amount: LAST_PRODUCT_QUANTITY
}
]);
// Full request to send the empty current cart
// Clear all products on our side
personaclick('track', 'cart', []);
// Track product added to cart
sdk.track(event: .productAddedToCart(id: "PRODUCT_ID", amount: 3)) { trackResponse in
// ... see product viewed event for details about a callback
}
// Sync full cart with products quantity (automatically adds and removes products)
sdk.track(event: .synchronizeCart(items: [CartItem(productId: "784"), CartItem(productId: "785", quantity: 3)] )) { _ in
print("Cart is synced callback")
}
// Add to cart (simple)
sdk.trackEventManager.track(Params.TrackEvent.CART, "37")
// Add to cart (extended)
val cart = Params().apply {
put(
Params.Item("37").apply {
set(Params.Item.COLUMN.FASHION_SIZE, "M")
set(Params.Item.COLUMN.AMOUNT, 2)
}
)
put(Params.RecommendedBy(Params.RecommendedBy.TYPE.RECOMMENDATION, "e9ddb9cdc66285fac40c7a897760582a"))
}
sdk.trackEventManager.track(Params.TrackEvent.CART, cart)
// Tracking full cart
val fullCart = Params().apply {
put(Params.Parameter.FULL_CART, true)
put(
Params.Item("37").apply {
set(Params.Item.COLUMN.AMOUNT, 2)
set(Params.Item.COLUMN.FASHION_SIZE, "M")
}
)
put(
Params.Item("40").apply {
set(Params.Item.COLUMN.AMOUNT, 1)
set(Params.Item.COLUMN.FASHION_SIZE, "M")
}
)
}
sdk.trackEventManager.track(Params.TrackEvent.CART, fullCart)
//Add to cart (simple)
Personaсlick.track(Params.TrackEvent.CART, "37");
//Add to cart (extended)
Params cart = new Params();
cart
.put(new Params.Item("37")
.set(Params.Item.COLUMN.FASHION_SIZE, "M")
.set(Params.Item.COLUMN.AMOUNT, 2)
)
.put(new Params.RecommendedBy(Params.RecommendedBy.TYPE.RECOMMENDATION, "e9ddb9cdc66285fac40c7a897760582a"));
Personaсlick.track(Params.TrackEvent.CART, cart);
//Tracking full cart
Params full_cart = new Params();
full_cart
.put(Params.Parameter.FULL_CART, true)
.put(new Params.Item("37")
.set(Params.Item.COLUMN.AMOUNT, 2)
.set(Params.Item.COLUMN.FASHION_SIZE, "M")
)
.put(new Params.Item("40")
.set(Params.Item.COLUMN.AMOUNT, 1)
.set(Params.Item.COLUMN.FASHION_SIZE, "M")
);
Personaсlick.track(Params.TrackEvent.CART, full_cart);
// Add to cart (simple)
sdk.track("cart", "id");
// Add to cart (from recommender block)
sdk.track("cart", {
id: PRODUCT_ID,
amount: PRODUCT_QUANTITY,
recommended_by: 'dynamic',
recommended_code: 'UNIQUE_RECOMMENDER_CODE'
});
//Full request to send the full current cart
sdk.track("cart", [
{
id: FIRST_PRODUCT_ID,
amount: FIRST_PRODUCT_QUANTITY
},
...
{
id: LAST_PRODUCT_ID,
amount: LAST_PRODUCT_QUANTITY
}
]);
JS SDK syntax (short request for a single product)
Syntax |
---|
personaclick("track", "cart", "id"); |
JS SDK Parameters
Parameter | Type | Requirement | Description |
---|---|---|---|
id | number/string | required | The ID of the product added to the cart |
JS SDK syntax (full request for a single product)
Syntax |
---|
personaclick("track", "cart", {params}); |
JS SDK Parameters
Parameter | Type | Requirement | Description |
---|---|---|---|
id | string | required | The ID of the product added to the cart |
amount | number | optional | Product quantity |
stock | boolean | optional | Product availability. If defined, it overwrites the value received from the product feed (XML) and HTTP-import of the product catalog. |
recommended_by | string | required in some cases | If a product from a recommendation widget was opened in a popup or a website uses a "single page" architecture, this parameter must contain the value "dynamic". |
recommended_code | string | required in some cases | If a product from the recommendations widget was opened in the pop-up or the site uses a "single page" architecture, this parameter must contain a unique code of the recommendations widget, available in the account in the "data-recommender-code" attribute for each widget. |
JS SDK syntax (request to send the full current cart)
Syntax |
---|
personaclick("track", "cart", [{params}, ..., {params}]); |
JS SDK Parameters
Parameter | Type | Requirement | Description |
---|---|---|---|
id | string | required | The ID of the product added to the cart |
amount | number | optional | Product quantity |
User removed product from cart
#Full request
curl 'https://api.personaclick.com/push' \
-X 'POST' \
-H 'Content-Type: application/json' \
--data-raw '{"event":"remove_from_cart", "shop_id":"SHOP_ID", "did":"DEVICE_ID", "sid":"SEANCE_ID", "segment":"A or B", "items":[{"id":"PRODUCT_ID"}]}'
#Short request for a single product with minimum required parameters
curl 'https://api.personaclick.com/push' \
-X 'POST' \
-H 'Content-Type: application/json' \
--data-raw '{"event":"remove_from_cart", "shop_id":"SHOP_ID", "did":"DEVICE_ID", "items":[{"id":"PRODUCT_ID"}]}'
//Full request for a single product
personaclick('track', 'remove_from_cart', 'id');
sdk.track(event: .productRemovedFromCart(id: "PRODUCT_ID")) { trackResponse in
// ... see product viewed event for details about a callback
}
// Not described yet
// Not described yet
sdk.track("remove_from_cart", id);
JS SDK syntax (full request for a single product)
Syntax |
---|
personaclick("track", "remove_from_cart", "id"); |
JS SDK Parameters
Parameter | Type | Requirement | Description |
---|---|---|---|
id | string | required | The ID of the product removed from the cart |
User purchased products
// Custom order properties are supported.Property value depends on key type. // Supported key types are: string, integer,date.
#Full request
curl 'https://api.personaclick.com/push' \
-X 'POST' \
-H 'Content-Type: application/json' \
--data-raw '{"event":"purchase", "shop_id":"SHOP_ID", "did":"DEVICE_ID", "email":"[email protected]", "phone": "4400114527199", "sid":"SEANCE_ID", "segment":"A or B", "items":[{"id":"PRODUCT_ID", "price": PRODUCT_PRICE, "amount": PRODUCT_QUANTITY}], "order_id":"ORDER_NUMBER", "order_price":TOTAL_ORDER_PRICE}'
#Short request with minimum required parameters
curl 'https://api.personaclick.com/push' \
-X 'POST' \
-H 'Content-Type: application/json' \
--data-raw '{"event":"purchase", "shop_id":"SHOP_ID", "did":"DEVICE_ID", "sid":"SEANCE_ID", "items":[{"id":"PRODUCT_ID"}]}'
//Full request
personaclick('track', 'purchase', {
email: "[email protected]",
phone: "4400114527199",
products: [
{id: 37, price: 318, amount: 3},
{id: 187, price: 5000, amount: 1}
],
order: 'N318',
order_price: 29999
});
// Custom order tracking
r46('track', 'purchase', {
'email': "[email protected]",
'phone': "4400114527199",
'products': [
{'id': 37, 'price': 318, 'amount': 1},
],
'custom': {
'date_start': '2024-03-01',
'date_finish': '2024-03-11',
'duration': 11,
'route': 'Moscow - Берлин',
'route_start': 'Moscow',
'route_finish': 'Berlin',
'tour_class': 'Lux',
'adults_count': 2,
'children_count': 1,
'infants_count': 1,
'deck': 'lower',
'rooms': '334,335'
},
'order': 'N318',
'order_price': 29999
});
// Track product added to cart
sdk.track(event: .orderCreated(orderId: "123", totalValue: 33.3, products: [(id: "PRODUCT_ID_1", amount: 3, price: 300), (id: "PRODUCT_ID_2", amount: 1, price: 100)])) { trackResponse in
// ... see product viewed event for details about a callback
}
val purchase = Params().apply {
put(
Params.Item("37").apply {
set(Params.Item.COLUMN.AMOUNT, 2)
set(Params.Item.COLUMN.PRICE, 100)
}
)
put(Params.Parameter.ORDER_ID, "100234")
put(Params.Parameter.ORDER_PRICE, 100500)
put(Params.Parameter.DELIVERY_ADDRESS, "1860 street")
put(Params.RecommendedBy(Params.RecommendedBy.TYPE.RECOMMENDATION, "e9ddb9cdc66285fac40c7a897760582a"))
}
sdk.trackEventManager.track(Params.TrackEvent.PURCHASE, purchase
Params purchase = new Params();
purchase
.put(new Params.Item("37").set(Params.Item.COLUMN.AMOUNT, 2).set(Params.Item.COLUMN.PRICE, 100))
.put(Params.Parameter.ORDER_ID, "100234")
.put(Params.Parameter.ORDER_PRICE, 100500)
.put(Params.Parameter.DELIVERY_ADDRESS, "1860 street")
.put(new Params.RecommendedBy(Params.RecommendedBy.TYPE.RECOMMENDATION, "e9ddb9cdc66285fac40c7a897760582a"));
Personaсlick.track(Params.TrackEvent.PURCHASE, purchase);
sdk.track("purchase", {
products: [
{id: "37", price: 318, amount: 3},
{id: "187", price: 5000, amount: 1}
],
order: 'N318',
order_price: 29999
});
// Custom order tracking
sdk.track('purchase', {
'email': "[email protected]",
'phone': "4400114527199",
'products': [
{'id': 37, 'price': 318, 'quantity': 1},
],
'custom': {
'date_start': '2024-03-01',
},
'order': 'N318',
'order_price': 29999
});
JS SDK syntax
Syntax |
---|
personaclick("track", "purchase", {params}); |
JS SDK Parameters
Parameter | Type | Requirement | Description |
---|---|---|---|
products | array | required | An array of objects with product information in the order. Description of parameters in the table below. |
order | string | optional | Order number in the store. If not defined, the internal order numbering system will be used. In this case synchronization of order status is impossible. |
string | optional | Client email. | |
phone | string | optional | Client phone. |
promocode | string | optional | Promo code used in transaction. |
order_price | number | optional | The final cost of the order including all discounts, bonuses, and additional services. If not defined, the cost of the order is calculated from the data in the product database without discounts and additional services. |
order_cash | number | optional | How much a customer paid with real money. |
order_bonuses | number | optional | How much a customer paid with bonuses. |
order_delivery | number | optional | Delivery fee. |
order_discount | number | optional | Order discount. |
delivery_type | string | optional | Method of delivery. |
payment_type | string | optional | Payment type. Can by any string value. Ex: cash, card, wire. |
tax_free | boolean | optional | Tax free |
custom | object | optional | Not empty object. Not array, not null. |
Description of parameters in the objects of the "products" array:
Parameter | Type | Requirement | Description |
---|---|---|---|
id | string | required | The ID of the product in the order |
amount | number | required | Product quantity |
price | number | optional | Product cost per unit |
line_id | string | optional | Unique identifier of the item position in the order on the store's side |
User added product to favorites
# Full request
curl 'https://api.personaclick.com/push' \
-X 'POST' \
-H 'Content-Type: application/json' \
--data-raw '{"event":"wish", "shop_id":"SHOP_ID", "did":"DEVICE_ID", "sid":"SEANCE_ID", "items":[{"id":"PRODUCT_ID"}]}'
#Full request to send the full current wish
curl 'https://api.personaclick.com/push' \
-X 'POST' \
-H 'Content-Type: application/json' \
--data-raw '{"event":"wish", "shop_id":"SHOP_ID", "did":"DEVICE_ID", "sid":"SEANCE_ID", "segment":"A or B", "items":["FIRST_PRODUCT_ID", "LAST_PRODUCT_ID"], "full_wish":true}'
#Full request to send the empty current wish
# Clear all products on our side
curl 'https://api.personaclick.com/push' \
-X 'POST' \
-H 'Content-Type: application/json' \
--data-raw '{"event":"wish", "shop_id":"SHOP_ID", "did":"DEVICE_ID", "sid":"SEANCE_ID", "segment":"A or B", "full_wish":true}'
personaclick('track', 'wish', product_id);
// Full request to send the full current wish
personaclick('track', 'wish', [FIRST_PRODUCT_ID, ..., LAST_PRODUCT_ID]);
// Full request to send the empty current wish
// Clear all products on our side
personaclick('track', 'wish', []);
sdk.trackEventManager.track(Params.TrackEvent.WISH, "37")
// Full wish tracking
Params full_wish = new Params();
full_wish
.put(Params.Parameter.FULL_WISH, true)
.put(new Params.Item("37"))
.put(new Params.Item("40"));
T.track(Params.TrackEvent.WISH, full_wish);
Personaсlick.track(Params.TrackEvent.WISH, "37");
sdk.track(event: .productAddToFavorities(id: "PRODUCT_ID")) { trackResponse in
// ... see product viewed event for details about a callback
}
// Full wish tracking
sdk.track(event: .synchronizeFavorites( ids: ["PRODUCT_ID"])){
// items and full_wish flag added to request parameters
// event type set to wish
}
sdk.track("wish", id);
// Full wish tracking - if the parameter is an array, full_wish is true.
sdk.track('wish', [17515, 17520]);
// If the parameter is a primitive, full_wish won't be forwarded
sdk.track('wish', 17515);
User removed product from favorites
#Full request
curl 'https://api.personaclick.com/push' \
-X 'POST' \
-H 'Content-Type: application/json' \
--data-raw '{"event":"remove_wish", "shop_id":"SHOP_ID", "did":"DEVICE_ID", "sid":"SEANCE_ID", "items":[{"id":"PRODUCT_ID"}]}'
personaclick('track', 'remove_wish', product_id);
sdk.track(event: .productRemovedToFavorities(id: "PRODUCT_ID")) { trackResponse in
// ... see product viewed event for details about a callback
}
sdk.trackEventManager.track(Params.TrackEvent.REMOVE_FROM_WISH, "37")
Personaсlick.track(Params.TrackEvent.REMOVE_FROM_WISH, "37");
sdk.track("remove_wish", id);
Track custom event
# Basic tracking
curl 'https://api.personaclick.com/push/custom' \
-X 'POST' \
-H 'Content-Type: application/json' \
--data-raw '{"event":"my_event", "shop_id":"SHOP_ID", "did":"DEVICE_ID", "sid":"SEANCE_ID"}'
# With other identifiers
curl 'https://api.personaclick.com/push/custom' \
-X 'POST' \
-H 'Content-Type: application/json' \
--data-raw '{"event":"my_event", "shop_id":"SHOP_ID", "email":"EMAIL", "phone":"PHONE", "loyalty_id":"LOYALTY_ID", "external_id":"EXTERNAL_ID"}'
# With custom parameters
curl 'https://api.personaclick.com/push/custom' \
-X 'POST' \
-H 'Content-Type: application/json' \
--data-raw '{"event":"my_event", "shop_id":"SHOP_ID", "email":"EMAIL", "phone":"PHONE", "loyalty_id":"LOYALTY_ID", "external_id":"EXTERNAL_ID", "category":"event category", "label":"event label", "value":100}'
# With custom time
curl 'https://api.personaclick.com/push/custom' \
-X 'POST' \
-H 'Content-Type: application/json' \
--data-raw '{"event":"my_event", "shop_id":"SHOP_ID", "did":"DEVICE_ID", "sid":"SEANCE_ID", "time": "1652648400"}'
// Simple tracking
personaclick("track", "my_event");
// Tracking with custom parameters
personaclick("track", "my_event", {
category: "event category",
label: "event label",
value: 100
});
// Simple custom event tracking
sdk.trackEvent(event: "something_happened")
// With parameters
sdk.trackEvent(event: "something_happened", category: "important", label: "banner_click", value: 42)
// with custom properties
sdk.trackEvent(event: "something_happened", category: "important", label: "user_event", value: 5, completion: @escaping (Result<Void, SDKError>) -> Void) {
sessionQueue.addOperation {
let path = "push/custom"
var params: [String: Any] = [
// `shop_id`,`did`,`seance`,`sid`,`segment`,`event`
]
}
// Simple tracking of custom event
sdk.trackEventManager.customTrack("my_event")
// Tracking with additional parameters
sdk.trackEventManager.customTrack(
event = "my_event",
category = "event category",
label = "event label",
value = 100
)
// Simple tracking of custom event
Personaсlick.track("my_event");
// Tracking with additional parameters
Personaсlick.track("my_event", "event category", "event label", 100);
// Simple tracking
sdk.trackEvent('my_event');
// Tracking with custom parameters
sdk.trackEvent('my_event', {
category: "event category",
label: "event label",
value: 100
});
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
email* | String | true | User's email |
phone* | String | true | User's phone number |
loyalty_id* | String | true | User's loyalty card id |
external_id* | String | true | User's shop internal id |
Optional parameters
Custom event can be tracked in simple mode (just event name) and advanced mode (with 3 optional parameters).
Parameter | Type | Requirement | Description |
---|---|---|---|
category | String | optional | Event category |
label | String | optional | Event label |
value | Integer | optional | Event value |
time* | Timestamp | optional | Event time |
User received on mobile push
curl 'https://api.personaclick.com/track/opened' \
-X 'POST' \
-H 'Content-Type: application/json' \
--data-raw '{"shop_id":"SHOP_ID", "code":"CODE", "type":"TYPE"}'
// No implementation
sdk.notificationReceived(code: "i7ykuagkjgfs", type: "mobile_push_transactional")
// Automatically called from SDK when receiving data from firebase
// Automatically called from SDK when receiving data from firebase
// Code and type are received in push notification structure
const params = {
code: 'CODE',
type: 'TYPE'
};
// Track when the notification is received and displayed
sdk.notificationOpened(params) {
// return this.notificationTrack(event,params)
};
When the push had been delivered and shown to the user, the parameters that have to be sent to the API are code and type
This method uses separate endpoint:
Endpoint: POST https://api.personaclick.com/track/opened
Required params
All events require at least these parameters:
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
code | String | true | Message identifier. Value can be taken from push's JSON payload. For Android it's located in id property. In iOS SDK it's src.id |
type | String | true | Message type. Value can be taken from push's JSON payload. For Android it's located in type property. In iOS SDK it's src.type .Supported types are: bulk , chain , transactional |
Message delivered
curl 'https://api.personaclick.com/track/delivered' \
-X 'POST' \
-H 'Content-Type: application/json' \
--data-raw '{"shop_id":"SHOP_ID", "code":"CODE", "type":"TYPE"}'
Message delivered to user's device event tracking. Event - push had been delivered, but had not been shown to the user yet
// Event - push had been delivered, but had not been shown to the user yet.
sdk.notificationDelivered(params) {
// return this.notificationTrack(event,params)
}
//Required parameters are code:"string" and type:"string"
sdk.notificationDelivered(parameters)
// example
sdk.notificationDelivered(code: "i7ykuagkjgfs", type: "mobile_push_transactional")
no implementation yet
no implementation yet
Endpoint: POST https://api.personaclick.com/track/delivered
Required params
All events require at least these parameters:
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
code | String | true | Message identifier. Value can be taken from push's JSON payload. For Android it's located in id property. In iOS SDK it's src.id |
type | String | true | Message type. Value can be taken from push's JSON payload. For Android it's located in type property. In iOS SDK it's src.type .Supported types are: bulk , chain , transactional |
User clicked on mobile push
curl 'https://api.personaclick.com/track/clicked' \
-X 'POST' \
-H 'Content-Type: application/json' \
--data-raw '{"shop_id":"SHOP_ID", "code":"CODE", "type":"TYPE"}'
// No implementation
sdk.notificationClicked(code: "i7ykuagkjgfs", type: "mobile_push_transactional")
// Add notification identification data to the intent
intent.putExtra( Personaсlick.NOTIFICATION_TYPE, data["type"])
intent.putExtra( Personaсlick.NOTIFICATION_ID, data["id"])
// Add click tracking in the method of activity creation
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Для отслеживания кликов по уведомлению
if (intent.extras != null) {
sdk.notificationClicked(intent.extras)
}
}
// Add notification identification data to the intent
intent.putExtra(Personaсlick.NOTIFICATION_TYPE, data.get("type"));
intent.putExtra(Personaсlick.NOTIFICATION_ID, data.get("id"));
// Add click tracking in the method of activity creation
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//For tracking notification clicked
if( getIntent().getExtras() != null ) {
Personaсlick.notificationClicked(getIntent().getExtras());
}
}
// Code and type are received in push notification structure
const params = {
code: 'CODE',
type: 'TYPE'
};
// Track when user clicked the notification
sdk.notificationClicked(params);
When user clicks on mobile push notification in mobile app, you have to send event to API with code
and type
parameters.
This method uses separate endpoint:
Endpoint: POST https://api.personaclick.com/track/clicked
Required params
All events require at least these parameters:
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
code | String | true | Message identifier. Value can be taken from push's JSON payload. For Android it's located in id property. In iOS SDK it's src.id |
type | String | true | Message type. Value can be taken from push's JSON payload. For Android it's located in type property. In iOS SDK it's src.type |
User closed on mobile push
curl 'https://api.personaclick.com/track/closed' \
-X 'POST' \
-H 'Content-Type: application/json' \
--data-raw '{"shop_id":"SHOP_ID", "code":"CODE", "type":"TYPE"}'
// No implementation
sdk.notificationClosed(code: "i7ykuagkjgfs", type: "mobile_push_transactional")
// Not supported
// Not supported
// Not supported
When user clicks on mobile push notification in mobile app, you have to send event to API with code
and type
parameters.
This method uses separate endpoint:
Endpoint: POST https://api.personaclick.com/track/closed
Required params
All events require at least these parameters:
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
code | String | true | Message identifier. Value can be taken from push's JSON payload. For Android it's located in id property. In iOS SDK it's src.id |
type | String | true | Message type. Value can be taken from push's JSON payload. For Android it's located in type property. In iOS SDK it's src.type . |
Stories tracking
Events tracking depends on rules that were configured during stories creation. Backend method 'checkRule' checks if the event-based rule is true, tracking clicks, views, etc. It is based on 'Clickhouse::get()->exists' method, which checks DB for events.
track(event, story_id, slide_id) {
return this.core.ajax.sendPost(this.core.api.getAPIUrl('/track/stories'), {
shop_id: this.core.shop.token,
did: this.core.user.did,
sid: this.core.user.seance,
event: event,
code: this.code,
story_id: story_id,
slide_id: slide_id,
})
}
//Events tracking depends on rules that were configured during stories creation.
// Backend method 'checkRule' checks if the event-based rule is true, tracking clicks, views, etc.
// It is based on 'Clickhouse::get()->exists' method, which checks DB for events.
track() {
local event=$1
local story_id=$2
local slide_id=$3
local apiUrl="https://api.personaclick.com/track/stories"
curl -X POST "$apiUrl" \
-d "shop_id=$SHOP_ID" \
-d "did=$USER_DID" \
-d "sid=$USER_SEANCE" \
-d "event=$event" \
-d "code=$CODE" \
-d "story_id=$story_id" \
-d "slide_id=$slide_id"
}
//Events tracking depends on rules that were configured during stories creation.
// Backend method 'checkRule' checks if the event-based rule is true, tracking clicks, views, etc.
// It is based on 'Clickhouse::get()->exists' method, which checks DB for events.
track(event, story_id, slide_id) {
return this.core.ajax.sendPost(this.core.api.getAPIUrl('/track/stories'), {
shop_id: this.core.shop.token,
did: this.core.user.did,
sid: this.core.user.seance,
event: event,
code: this.code,
story_id: story_id,
slide_id: slide_id,
})
}
Product recommendations
Service provides access to product recommendations endpoint.
Request product recommendations
// No implementation is needed in HTTP
personaclick("recommend", "1fd1b3495137bc3c9299816026acf36f", {item: 100500, exclude: [3, 14, 159, 26535], category: 146, search_query: "To be or not to be", limit: 15, brands: ["Alas", "poor", "Yorick"], categories: [1, 146, 100500], extended: true, with_locations:true }, function(response) {
// the functionality of rendering a block of product recommendations
}, function(error) {
// when something went wrong
});
// Basic request
sdk.recommend(blockId: "BLOCK_ID") { recommendResult in
print("Callback")
}
// Request with additional data (for example with product ID)
sdk.recommend(blockId: "block_id", currentProductId: "PRODUCT_ID") { recommendResult in
print("Callback")
}
// Request with locations
// It has extended and withLocations parameters.
// To get locations in the response, the extended parameter must be included in the request and set to true
sdk.recommend(blockId: "block_id", extended: true, with_locations: true) {
// An array with JSON objects containing information about locations will be part of the response.
// locations: [ { "id": "loc1", "name": "Location 1" }, { "id": "loc2", "name": "Location 2" } ]
}
// Create Recommendations Widget collection programmatically.
public var recommendationsCollectionView = RecommendationsWidgetView()
// Load Recommendations Widget view and setup height and position settings.
DispatchQueue.main.async {
self.recommendationsCollectionView.loadWidget(sdk: globalSDK, blockId: "bc1f41f40bb4f92a705ec9d5ec2ada42")
self.view.addSubview(self.recommendationsCollectionView)
self.recommendationsCollectionView.heightAnchor.constraint(equalToConstant: 460).isActive = true //height
self.recommendationsCollectionView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 20).isActive = true
self.recommendationsCollectionView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true //left
self.recommendationsCollectionView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true //right
}
// Setup Recommendations Widget configuration.
sdk.configuration().recommendations.setWidgetBlock(widgetFontName: "Museo",
widgetBackgroundColor: "#ffffff",
widgetBackgroundColorDarkMode: "#000000",
widgetCellBackgroundColor: "#ffffff",
widgetCellBackgroundColorDarkMode: "#000000",
widgetBorderWidth: 1,
widgetBorderColor: "#c3c3c3",
widgetBorderColorDarkMode: "#c3c3c3",
widgetBorderTransparent: 0.4,
widgetCornerRadius: 9,
widgetStarsColor: "#ff9500",
widgetAddToCartButtonText: "Add to cart",
widgetRemoveFromCartButtonText: "Remove from cart",
widgetAddToCartButtonFontSize: 17,
widgetRemoveFromCartButtonFontSize: 14,
widgetCartButtonTextColor: "#ffffff",
widgetCartButtonTextColorDarkMode: "#ffffff",
widgetCartButtonBackgroundColor: "#000000",
widgetCartButtonBackgroundColorDarkMode: "#ffffff",
widgetCartButtonNeedOpenWebUrl: false,
widgetFavoritesIconColor: "#000000",
widgetFavoritesIconColorDarkMode: "#ffffff",
widgetPreloadIndicatorColor: "#ffffff"
)
val params = Params().apply {
put(Params.Parameter.ITEM, "37")
// category filtration
put(Params.Parameter.CATEGORY, "111")
}
// get recommendation with product ids
sdk.recommendationManager.getRecommendation("RECOMMENDER_CODE", params, { getRecommendationResponse ->
Log.i(TAG, "Get recommandation response: $getRecommendationResponse")
})
// get recommendation with products info
sdk.recommendationManager.getExtendedRecommendation("RECOMMENDER_CODE", params, { getExtendedRecommendationResponse ->
Log.i(TAG, "Get extended recommandation response: $getExtendedRecommendationResponse")
})
Params params = new Params();
params.put(Params.Parameter.EXTENDED, true);
params.put(Params.Parameter.ITEM, "37");
params.put(Params.Parameter.CATEGORY, "111"); //filter by category
Personaсlick.recommend("RECOMMENDER_CODE", params, new Api.OnApiCallbackListener() {
@Override
public void onSuccess(JSONObject response) {
Log.i(TAG, "Recommender response: " + response.toString());
}
});
const recommender_code = 'recommender_code';
const params = {
item: 100500,
exclude: [3, 14, 159, 26535],
search_query: "To be or not to be"
extended:true
with_locations:true
// other params
};
sdk.recommend(recommender_code, params)
.then((res) => {
console.log(res);
})
.catch((error) => {
console.log(error);
});
// Example of a request containing the with_locations parameter.
// The parameter extended with the value true must be present in the request. Otherwise, only product IDs will be returned and with_locations parameter will be ignored.
// Locations will be shown in the "location_ids" field, which will contain an array with location IDs.
sdk.recommend(`recommend/${recommender_code}`, {
params: {
shop_id: this.shop_id,
stream: this.stream,
recommender_code,
extended:true,
with_locations:true,
},
})
HTTP Request
GET https://api.personaclick.com/recommend/{%recommender_code%}
Query Parameters
Parameter | Required | Description |
---|---|---|
did | true | Device ID. You get it from init method in SDK. |
shop_id | true | Your API key |
sid | true | Temporary user session ID |
recommender_code | true | ID of product recommendations block. You get it from blocks management UI. |
resize_image | false | Image size (px) to resize. Supported: 120, 140, 160, 180, 200, 220. |
extended | false | If true, it will return all information about recommended products. If false - only product IDs will be returned. Default is false. |
with_locations | false | If true and if parameter extended is in request and is true, the answer will return location_ids where product is available. If request doesn't have extended parameter or its false, with_locations` parameter is ignored. Default value is false. |
Syntax |
---|
personaclick("recommend", code, params, success, error); |
Name | Type | Requirement | Description |
---|---|---|---|
code | string | required | Unique code of the recommendation block. See this value in the "data-recommender-code" attribute of the block created in account |
params | object | required | Object with request parameters |
success | function | required in some cases | A callback function, to which the API response will be passed. Response type: object. |
error | function | optionally | A callback function that will be called when an error occurs (any HTTP status code other than 200) |
Request parameters
Name | Type | Requirement | Description |
---|---|---|---|
item | number/string | required in some cases | Product ID. This parameter is mandatory for the requests of blocks that use the algorithms "Similar" and "Also bought". |
exclude | array | optionally | Product IDs array, which should be excluded from the recommended products list. |
category | number/string | required in some cases | Category ID. This parameter is mandatory for all blocks set on category pages. |
search_query | string | required in some cases | The text of the search query. This parameter is mandatory for the requests of blocks that use the "Search" algorithm. |
limit | number | optionally | A maximum number of products in the API response. |
locations | string | optionally | A string with location IDs. IDs are separated by comma. If used, the API response will return products available in the listed locations. Locations must be specified in the XML product feed. |
brands | array | optionally | Array with brand names. If used, only the products of the listed brands will be returned in the API response. Brands must be specified in the XML product feed. |
exclude_brands | array | optionally | Array with brand names. If used, the API response will exclude the products of the listed brands. Brands must be specified in the XML product feed. |
categories | array | optionally | Array with category IDs. If used, the API response will only return products that are included in the listed categories. |
discount | boolean | optionally | If used with "true" value, then only those products, the value of which is less than the "oldprice" value, will be returned in the API response. The old price must be specified in the XML product feed. |
extended | number | optionally | Supports: 1 or empty. If 1 , it will return all information about recommended products. If omit, it returns only products IDs. |
prevent_shuffle | boolean | optionally | If true, it disables shuffling of products in the response. |
page | number | optionally | The parameter for creating pagination, by default 1. Returns the number of products based on the limit per page. |
with_locations | boolean | optionally | Locations where product is available. Returned only if parameter extended is in request and is true. |
API response
Name | Type | Description |
---|---|---|
html | string | HTML-code of the block with products. The template is customized in the PersonaClick personal account. |
title | string | The block title. Corresponds to the value of the "Action" element in the block rules. |
recommends | array | Array with product IDs. |
id | number | Unique block identifier. Corresponds to the block ID in the list of blocks in the PersonaClick personal account. |
Search
Service provides 2 types of search: instant (typeahead) and full search.
Instant search
personaclick("suggest", {search_query: "To be or not to be"}, function(response) {
// the functionality of rendering a block of instant search
}, function(error) {
// when something went wrong
});
// Instant search
sdk.suggest(query: "ipho") { searchResult in
print("Suggest callback")
}
//Instant search
SearchParams params = new SearchParams();
params.put(SearchParams.Parameter.LOCATIONS, "location");
Personaсlick.search("SEARCH_QUERY", SearchParams.TYPE.INSTANT, params, new Api.OnApiCallbackListener() {
@Override
public void onSuccess(JSONObject response) {
Log.i(TAG, "Search response: " + response.toString());
}
});
//Search blank request
Personaсlick.search_blank(new Api.OnApiCallbackListener() {
@Override
public void onSuccess(JSONObject response) {
Log.i(T.TAG, "Search response: " + response.toString());
}
});
//Instant search
sdk.searchManager.searchInstant("SEARCH_QUERY", "locations", { searchInstantResponse ->
Log.i(TAG, "Search instant response: $searchInstantResponse")
})
//Search blank request
sdk.searchManager.searchBlank({ searchBlankResponse ->
Log.i(TAG, "Search blank response: $searchBlankResponse")
})
const type = 'instant_search';
let search_query = 'your_search_text';
sdk.search({
type: type,
search_query: search_query,
// other params
})
.then((res) => {
console.log(res);
})
.catch((error) => {
console.log(error);
});
HTTP Request
// No implementation is needed in HTTP
Query Parameters
Parameter | Required | Description |
---|---|---|
did | true | Device ID. You get it from init method in SDK. |
shop_id | true | Your API key |
sid | true | Temporary user session ID |
type | true | In this case: "instant_search" |
search_query | true | Search query |
locations | false | Comma separated list of locations IDs |
API response
Name | Type | Description |
---|---|---|
search_query | string | Search query |
categories | array | Array with information about categories. Each object has the following properties: |
* id – category id (string) | ||
* name – category name (string) | ||
* url – category url (string) | ||
* count – count of products in category (number) | ||
queries | Objects with the found items: | |
* The key is the index number of the item found through the search, and the value is an object containing the following properties: | ||
- key: name, value: the name of the search item (string) | ||
- key: url_handle, value: URL handle (string) | ||
- key: url, value: full URL (string) | ||
- key: score, value: a score that used for ranking the search suggestions (float) | ||
filters | array | Array with information about filters. Each object has the following properties: |
* filter – filter object. Has the following properties: | ||
* count – total count of products with this parameters (number) | ||
* values – array of values (object). Has the following properties: | ||
* value – value label. (string) | ||
* count – cont of products with this parameter (number) | ||
* ranges - an object with the following properties: | ||
- key: min, value: the minimum value of product (string) | ||
- key: max, value: the maximum value of product (string) | ||
html | string | HTML-code of the block with products. The template is customized in the PersonaClick personal account. |
price_range | object | Min and max price of products. Has the following properties: |
* min – min price (number) | ||
* max – max price (number) | ||
products | array | Array with information about products. Each object has the following properties: |
* description – product description (string) | ||
* url – absolute product URL (string) | ||
* url_handle – relative product URL (string) | ||
* picture – product's picture URL in the PersonaClick storage (string) | ||
* name – product name (string) | ||
* price – product price (number / int) | ||
* price_full – product price (number / float) | ||
* price_formatted – product price with currency (string) | ||
* price_full_formatted – product price with currency (string) | ||
* image_url - absolute product's picture URL in the PersonaClick storage (string) | ||
* image_url_handle - relative product's picture URL in the PersonaClick storage (string) | ||
* image_url_resized - product image resizes url (array) | ||
* currency – product currency (string, corresponds to the currency of the personal account in PersonaClick, or a custom value specified in the shop settings in the personal account) | ||
* id – product ID (string) | ||
* old_price – product old price (number / int, default - 0) | ||
* old_price_full – product old price (number / float) | ||
* old_price_formatted – product old price with currency (string) | ||
* old_price_full_formatted – product old price with currency (string) | ||
Additional properties. If a parameter "extended" is passed in the request | ||
* categories – product categories (array). Has the following properties: | ||
* id – category id (string) | ||
* name – category name (string) | ||
* parent_id – parent category id (string) | ||
* url - category url | ||
* category_ids - product categories ids (array). | ||
search_query_redirects | array | Array with information about redirects. Each object has the following properties: |
* query – search query (string) | ||
* redirect_link – Url for redirect (string) | ||
* deep_link – Url for mobile apps (string) | ||
products_total | number | Total count of products |
book_author | array | Reserved |
book_editor | array | Reserved |
book_publisher | array | Reserved |
book_series | array | Reserved |
book_illustrator | array | Reserved |
book_isbn | array | Reserved |
book_isbn_vars | array | Reserved |
Full search
personaclick("search", {search_query: "To be or not to be", page: 2, limit: 15, brands: ["Alas", "poor", "Yorick"], categories: [1, 146, 100500], filters: {'key':['value'], 'key':['value']}, merchants: ['merchant1', 'merchant2'],fashion_sizes:['L','XXL'], sort_by: "price", order: "asc"}, function(response) {
// the functionality of rendering a block of full search
}, function(error) {
// when something went wrong
});
// Basic full search
sdk.search(query: "iphone") { searchResult in
print("Full search callback")
}
// Full search with additional parameters
sdk.search(query: "laptop", limit: nil, offset: nil, categoryLimit: nil, categories: nil, extended: nil, sortBy: nil, sortDir: nil, locations: nil, brands: nil, filters: nil, priceMin: nil, priceMax: nil, colors: nil, exclude: nil, fashion_sizes: nil) { searchResult in
print("Full search callback")
}
// Search with locations
val params = SearchParams()
params.put(SearchParams.Parameter.LOCATIONS, "location")
//Additional filters
val filters = SearchParams.SearchFilters()
filters.put("voltage", arrayOf("11.1", "14.8"))
params.put(SearchParams.Parameter.FILTERS, filters)
//Disable clarification search
params.put(SearchParams.Parameter.NO_CLARIFICATION, true)
// Support for FASHION_SIZES filter
filters.put("fashion_sizes", arrayOf("S", "M", "L"))
params.put(SearchParams.Parameter.FASHION_SIZES, filters)
//Full search
sdk.searchManager.searchFull("SEARCH_QUERY", params, { searchFullResponse ->
Log.i(TAG, "Search full response: $searchFullResponse")
})
//Full search
SearchParams params = new SearchParams();
params.put(SearchParams.Parameter.LOCATIONS, "location");
//Additional filters
SearchParams.SearchFilters filters = new SearchParams.SearchFilters();
filters.put("voltage", new String[] {"11.1", "14.8"});
params.put(SearchParams.Parameter.FILTERS, filters);
//Disable clarification search
params.put(SearchParams.Parameter.NO_CLARIFICATION, true);
Personaсlick.search("SEARCH_QUERY", SearchParams.TYPE.FULL, params, new Api.OnApiCallbackListener() {
@Override
public void onSuccess(JSONObject response) {
Log.i(TAG, "Search response: " + response.toString());
}
});
const type = 'full_search';
let search_query = 'your_search_text';
sdk.search({
type,
search_query,
// other params
})
.then((res) => {
console.log(res);
})
.catch((error) => {
console.log(error);
});
//Full search with additional parameters filters_search_by is fully supported
sdk.search({type: 'full_search', search_query: 'string', filters_search_by: 'popularity'});
LOG Request:
{
"headers": {"Content-Type": "application/x-www-form-urlencoded", "User-Agent": "ReactNative Android SDK v1.6.34"},
"method": "GET",
"params": {"did": "e0747b709b5b6467", "filters_search_by": "popularity", "seance": "MC44NjAwMD",
"search_query": "string", "shop_id": "357382bf66ac0ce2f1722677c59511", "sid": "MC44NjAwMD", "stream": "android",
"type": "full_search"}
}
HTTP Request
GET https://api.personaclick.com/search
Query Parameters
Parameter | Required | Description |
---|---|---|
did | true | Device ID. You get it from init method in SDK. |
shop_id | true | Your API key |
sid | true | Temporary user session ID |
type | true | In this case: "full_search" |
search_query | true | Search query |
limit | false | Limit of results |
offset | false | Offset of results |
category_limit | false | How many categories for sidebar filter to return |
categories | false | Comma separated list of categories to filter |
extended | false | It's better to use true for full search results |
sort_by | false | Sort by parameter: popular , price , discount , sales_rate , date |
order | false | Sort direction: asc or desc (default) |
locations | false | Comma separated list of locations IDs |
brands | false | Comma separated list of brands to filter |
filters | false | Optional escaped JSON string with filter parameters. For example: {"bluetooth":["yes"],"offers":["15% cashback"],"weight":["1.6"]} |
price_min | false | Min price |
price_max | false | Max price |
colors | false | Comma separated list of colors |
fashion_sizes | false | Comma separated list of sizes |
exclude | false | Comma separated list of products IDs to exclude from search results |
false | It's only for S2S integration, when service doesn't have user's session. Mobile SDK doesn't use it. | |
no_clarification | false | Disable clarified search (true, false, default: false). Don't use it. God mode only. |
merchants | false | Comma separated list of merchants |
filters_search_by | false | Available options for filter: name, quantity, popularity.If this parameter in query global settings from dashboard are ignored |
API response
Name | Type | Description |
---|---|---|
brands | array | Array with information about brands. Each object has the following properties: |
* name – brand name (string) | ||
* picture – brand picture (string) | ||
categories | array | Array with information about categories. Each object has the following properties: |
* alias – category alias (string) | ||
* id – category id (string) | ||
* name – category name (string) | ||
* parent – parent category id (string) | ||
* url – category url (string) | ||
filters | array | Array with information about filters. Each object has the following properties: |
* filter – fitler object. Has the following properties: | ||
* count – total count of products whith this parameters (number) | ||
* values – array of values (object). Has the following properties: | ||
* value – value label. (string) | ||
* count – cont of products whith this parameter (number) | ||
industrial_filters | array | Array with information about industrial filters. For example: colors and fashion_sizes |
colors (array of objects) has the following properties: color, count | ||
fashion_sizes (array of objects) has the following properties: size, count | ||
html | string | HTML-code of the block with products. The template is customized in the PersonaClick personal account. |
price_range | object | Min and max price of products. Has the following properties: |
* min – min price (number) | ||
* max – max price (number) | ||
products | array | Array with information about products. Each object has the following properties: |
* brand – product brand (string) | ||
* currency – product currency (string, corresponds to the currency of the personal account in PersonaClick, or a custom value specified in the shop settings in the personal account) | ||
* id – product ID (string) | ||
* is_new – product property (boolean, default - null) | ||
* name – product name (string) | ||
* old_price – product old price (string, default - 0) | ||
* picture – product's picture URL in the PersonaClick storage (string) | ||
* price – product price (number) | ||
* price_formatted – product price with currency (string) | ||
* url – product URL (string) | ||
Additional properties. If a parameter "extended" is passed in the request | ||
* barcode – product barcode (string) | ||
* categories – product categories (array). Has the following properties: | ||
* id – category id (string) | ||
* name – category name (string) | ||
* parent – parent category id (string) | ||
* params – array with information about params. Each object has the following properties: | ||
* key – param name (string) | ||
* values – array of values (array) | ||
products_total | number | Total count of products |
search_query | string | Search query |
book_authors | array | Reserved |
keywords | array | Reserved |
queries | array | Reserved |
virtual_categories | array | Reserved |
Search queries with zero results
This method returns a list of queries which return zero results and number of usages of this queries during previous 2 weeks.
For server-to-server integration only.
HTTP Request
GET https://api.personaclick.com/search/no_result_queries
curl https://api.personaclick.com/search/no_result_queries?shop_id=...&shop_secret=...
// No implementation. See CURL
// No implementation. See CURL
// No implementation. See CURL
// No implementation. See CURL
Response example
[
{
"query": "iphone 4s",
"quantity": 3844
},
{
"contact_type": "covfefe",
"quantity": 384491
}
]
Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Secret API key |
Response properties
Parameter | Type | Description |
---|---|---|
query | String | Search query value |
quantity | Integer | Number of query usages during 2 weeks |
Subscriptions
Service provides methods to manage user's subscriptions to email/SMS channels
Manage subscriptions
HTTP Request
POST https://api.personaclick.com/subscriptions/manage
Change user's subscription to different channels and campaigns types
# Full example
curl -d "shop_id=SHOPID&shop_secret=SECRET&[email protected]&phone=+10000000000&email_bulk=true&email_chain=true&email_transactional=true&sms_bulk=true&sms_chain=true&sms_transactional=true" \
https://api.personaclick.com/subscriptions/manage
# Change only specific subscriptions
curl -d "shop_id=SHOPID&shop_secret=SECRET&[email protected]&phone=+10000000000&email_bulk=true&email_chain=true&sms_chain=true&sms_transactional=true" \
https://api.personaclick.com/subscriptions/manage
# Change without phone
curl -d "shop_id=SHOPID&shop_secret=SECRET&[email protected]&email_bulk=true&email_chain=true&sms_chain=true&sms_transactional=true" \
https://api.personaclick.com/subscriptions/manage
# Change without email
curl -d "shop_id=SHOPID&shop_secret=SECRET&phone=+10000000000&email_bulk=true&email_chain=true&sms_chain=true&sms_transactional=true" \
https://api.personaclick.com/subscriptions/manage
# Doesn't work, because there is no identifier
curl -d "shop_id=SHOPID&shop_secret=SECRET&email_bulk=true&email_chain=true&sms_chain=true&sms_transactional=true" \
https://api.personaclick.com/subscriptions/manage
// Subscribe user to all kids of email campaigns and SMS
personaclick('subscription', 'manage', {
email: '[email protected]',
phone: '+100000000000',
email_bulk: true,
email_chain: true,
email_transactional: true,
sms_bulk: true,
sms_chain: true,
sms_transactional: true
});
// Change only specific subscriptions
personaclick('subscription', 'manage', {
email: '[email protected]',
phone: '+100000000000',
email_chain: true,
sms_bulk: true,
sms_transactional: true
});
// Change without phone
personaclick('subscription', 'manage', {
email: '[email protected]',
email_chain: true,
sms_bulk: true,
sms_transactional: true
});
// Change without email
personaclick('subscription', 'manage', {
phone: '+100000000000',
email_chain: true,
sms_bulk: true,
sms_transactional: true
});
// Change by `did` only
personaclick('subscription', 'manage', {
email_chain: true,
sms_bulk: true,
});
// With `did` only
sdk.manageSubscription(bulkEmail: true)
// With email and phone
sdk.manageSubscription(email: "[email protected]", phone: "+10000000000", emailBulk: true, smsBulk: true)
// Unsubscribe from bulk SMS and email
sdk.manageSubscription(emailBulk: false, smsBulk: false)
// With everything
sdk.manageSubscription(email: "[email protected]", phone: "+10000000000", userExternalId: "String", userLoyaltyId: "String", telegramId: "String",
emailBulk: true,
emailChain: true,
emailTransactional: true,
smsBulk: true,
smsChain: true,
smsTransactional: true,
webPushBulk: true,
webPushChain: true,
webPushTransactional: true,
mobilePushBulk: true,
mobilePushChain: true,
mobilePushTransactional: true
)
// With `did` only
val subscriptions = hashMapOf<String, Boolean>()
subscriptions["email_bulk"] = true
sdk.manageSubscription(null, null, subscriptions)
// With email and phone
val subscriptions = hashMapOf<String, Boolean>()
subscriptions["email_bulk"] = true
sdk.manageSubscription("[email protected]", "+10000000000", subscriptions)
// With email and phone and listener
val subscriptions = hashMapOf<String, Boolean>()
subscriptions["email_bulk"] = true
sdk.manageSubscription("[email protected]", "+10000000000", subscriptions, listener)
// With email, phone, externalId, loyaltyId, telegramId
val subscriptions = hashMapOf<String, Boolean>()
subscriptions["email_bulk"] = true
subscriptions["sms_chain"] = false
sdk.manageSubscription("[email protected]", "+10000000000", "externalID", "loyaltyId", "telegramId", subscriptions)
// With email, phone, externalId, loyaltyId, telegramId and listener
val subscriptions = hashMapOf<String, Boolean>()
subscriptions["email_bulk"] = true
subscriptions["email_transactional"] = false
subscriptions["sms_chain"] = true
sdk.manageSubscription("[email protected]", "+10000000000", "externalID", "loyaltyId", "telegramId", subscriptions, listener)
// Unsubscribe from bulk SMS and email
val subscriptions = hashMapOf<String, Boolean>()
subscriptions["email_bulk"] = false
subscriptions["sms_bulk"] = false
sdk.manageSubscription(null, null, subscriptions)
// With `did` only
HashMap<String, Boolean> subscriptions = new HashMap<>();
subscriptions.put("email_bulk", true);
Personaсlick.manageSubscription(null, null, subscriptions);
// With email and phone
HashMap<String, Boolean> subscriptions = new HashMap<>();
subscriptions.put("email_bulk", true);
Personaсlick.manageSubscription("[email protected]", "+10000000000", subscriptions);
// With email and phone and listener
HashMap<String, Boolean> subscriptions = new HashMap<>();
subscriptions.put("email_bulk", true);
Personaсlick.manageSubscription("[email protected]", "+10000000000", subscriptions, listener);
// With email, phone, externalId, loyaltyId, telegramId
HashMap<String, Boolean> subscriptions = new HashMap<>();
subscriptions.put("email_bulk", true);
subscriptions.put("sms_chain", false);
Personaсlick.manageSubscription("[email protected]", "+10000000000", "externalID", "loyaltyId", "telegramId", subscriptions);
// With email, phone, externalId, loyaltyId, telegramId and listener
HashMap<String, Boolean> subscriptions = new HashMap<>();
subscriptions.put("email_bulk", true);
subscriptions.put("email_transactional", false);
subscriptions.put("sms_chain", true);
Personaсlick.manageSubscription("[email protected]", "+10000000000", "externalID", "loyaltyId", "telegramId", subscriptions, listener);
// Unsubscribe from bulk SMS and email
HashMap<String, Boolean> subscriptions = new HashMap<>();
subscriptions.put("email_bulk", false);
subscriptions.put("sms_bulk", false);
Personaсlick.manageSubscription(null, null, subscriptions);
The method changes user's subscription to different channels (email
, sms
) and campaigns types (bulk
, chain
, transactional
).
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true* | Secret API key. Required only for REST integration. |
String | true* | User's email | |
phone | String | true* | User's email |
external_id | String | true* | User's ID from external source |
telegram_id | String | true* | User's telegram ID |
loyalty_id | String | true* | User's loyalty card ID |
did | String | true* | Users device ID. It's handled automatically on JS SDK and don't needed in REST API |
email_bulk | Boolean | false | Subscribe user to email bulk campaigns |
email_chain | Boolean | false | Subscribe user to email drip/trigger campaigns |
email_transactional | Boolean | false | Subscribe user to email transactional campaigns |
sms_bulk | Boolean | false | Subscribe user to SMS bulk campaigns |
sms_chain | Boolean | false | Subscribe user to SMS drip/trigger campaigns |
sms_transactional | Boolean | false | Subscribe user to SMS transactional campaigns |
web_push_bulk | Boolean | false | Subscribe user to Web push bulk campaigns |
web_push_chain | Boolean | false | Subscribe user to Web push drip/trigger campaigns |
web_push_transactional | Boolean | false | Subscribe user to Web push transactional campaigns |
mobile_push_bulk | Boolean | false | Subscribe user to Mobile push bulk campaigns |
mobile_push_chain | Boolean | false | Subscribe user to Mobile push drip/trigger campaigns |
mobile_push_transactional | Boolean | false | Subscribe user to Mobile push transactional campaigns |
System operations: unsubscribe, complaint, hard bounce and blacklist
This method is used to mark email with specific status.
POST https://api.personaclick.com/subscriptions/callback
Email is bounced
Use this method only for hard bounces. Don't use it for soft bounce, because it purges email from database forever.
curl -d "shop_id=SHOPID&shop_secret=SECRET&[email protected]&event=hard_bounced" \
https://api.personaclick.com/subscriptions/callback
# Response:
{"status": "success"}
// No implementation. See CURL
// No implementation. See CURL
// No implementation. See CURL
// No implementation. See CURL
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Secret API key. Required only for REST integration. |
String | true | User's email | |
event | String | true | Event to process: hard_bounced |
Email is complained
Use this method on FBL request (user marked email as spam):
curl -d "shop_id=SHOPID&shop_secret=SECRET&[email protected]&event=complained" \
https://api.personaclick.com/subscriptions/callback
# Response:
{"status": "success"}
// No implementation. See CURL
// No implementation. See CURL
// No implementation. See CURL
// No implementation. See CURL
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Secret API key. Required only for REST integration. |
String | true | User's email | |
event | String | true | Event to process: complained |
Email is blacklisted
Use this method to add email to black list:
curl -d "shop_id=SHOPID&shop_secret=SECRET&[email protected]&event=blacklisted" \
https://api.personaclick.com/subscriptions/callback
# Response:
{"status": "success"}
// No implementation. See CURL
// No implementation. See CURL
// No implementation. See CURL
// No implementation. See CURL
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Secret API key. Required only for REST integration. |
String | true | User's email | |
event | String | true | Event to process: blacklisted |
Email is unsubscribed
Use this method to unsubscribe email:
curl -d "shop_id=SHOPID&shop_secret=SECRET&[email protected]&event=unsubscribed" \
https://api.personaclick.com/subscriptions/callback
# Response:
{"status": "success"}
// No implementation. See CURL
// No implementation. See CURL
// No implementation. See CURL
// No implementation. See CURL
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Secret API key. Required only for REST integration. |
String | true | User's email | |
event | String | true | Event to process: unsubscribed |
Check subscription status
GET https://api.personaclick.com/subscriptions/check
curl https://api.personaclick.com/subscriptions/check
personaclick('subscription', 'check',
function (subscriptions) {
console.log(subscriptions)
},
function(error) {
console.log(error)
});
// No implementation. See CURL
// No implementation. See CURL
// No implementation. See CURL
Response example
{
"exists": false,
"email_bulk": false,
"email_chain": false,
"email_transactional": false,
"email_invalid": false,
"email_blacklisted": false,
"email_bounced": false,
"email_suppressed": false,
"email_confirmed": false,
"web_push_bulk": false,
"web_push_chain": false,
"web_push_transactional": false,
"mobile_push_bulk": false,
"mobile_push_chain": false,
"mobile_push_transactional": false,
"sms_bulk": false,
"sms_chain": false,
"sms_transactional": false
}
Checks email's subscription status.
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true** | Secret API key. Can be sent as header X-Shop-Secret . |
String | true* | User's email | |
phone | String | true* | User's phone. |
did | String | true* | User's did. |
Response flags:
Property | Type | Description |
---|---|---|
exists | Boolean | Check if user with specified contact is present in CDP |
email_bulk | Boolean | Email is subscribed to bulk emails |
email_chain | Boolean | Email is subscribed to drip campaigns (triggers) |
email_transactional | Boolean | Email is subscribed to transactional emails |
email_invalid | Boolean | Email is invalid or disposal email |
email_blacklisted | Boolean | Email is blacklisted (spam trap, etc) |
email_bounced | Boolean | Email is hard bounced |
email_suppressed | Boolean | Email is suppressed due to complaint |
email_confirmed | Boolean | Email is confirmed by DOI |
web_push_bulk | Boolean | User has phone and subscribed to bulk Web push campaigns |
web_push_chain | Boolean | User has phone and subscribed to drip Web push campaigns (triggers) |
web_push_transactional | Boolean | User has phone and subscribed to transactional Web push campaigns |
mobile_push_bulk | Boolean | User has phone and subscribed to bulk Mobile push campaigns |
mobile_push_chain | Boolean | User has phone and subscribed to drip Mobile push campaigns (triggers) |
mobile_push_transactional | Boolean | User has phone and subscribed to transactional Mobile push campaigns |
sms_bulk | Boolean | User has phone and subscribed to bulk SMS campaigns |
sms_chain | Boolean | User has phone and subscribed to drip SMS campaigns (triggers) |
sms_transactional | Boolean | User has phone and subscribed to transactional SMS campaigns |
Changed subscriptions list
This method returns users with changed subscriptions statuses during defined dates range (default 24 hours).
Returns an array of users with email or/and phone, who changed subscriptions status during last 24 hours. Sorted by time ascending.
GET https://api.personaclick.com/subscriptions/changes
curl https://api.personaclick.com/subscriptions/changes?shop_id=...&shop_secret=...
// No implementation. See CURL
// No implementation. See CURL
// No implementation. See CURL
// No implementation. See CURL
Response example
[
{
"contact_type": "email",
"contact": "[email protected]",
"campaign_type": "chain",
"event": "subscribe",
"channel": "popup",
"datetime": "2020-09-24 14:42:36",
"ip": "192.168.0.1"
},
{
"contact_type": "email",
"contact": "[email protected]",
"campaign_type": "bulk",
"event": "unsubscribe",
"channel": "unsubscribe_page",
"datetime": "2020-09-23 14:43:36",
"ip": "192.168.2.27"
},
{
"contact_type": "email",
"contact": "[email protected]",
"campaign_type": "bulk",
"event": "hard_bounced",
"channel": "email_processing",
"datetime": "2020-09-23 14:43:36",
"ip": "192.168.2.27"
},
{
"contact_type": "sms",
"contact": "+19990009999",
"campaign_type": "transactional",
"event": "subscribe",
"channel": "crm",
"datetime": "2020-09-25 14:43:36",
"ip": "192.168.2.27"
}
]
Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key. |
shop_secret | String | true | Secret API key. Can be sent as header X-Shop-Secret . |
event | String | false | Filter by event. |
channel | String | false | Filter by channel. |
from | String | false | Date from in YYYY-MM-DD format. Default value: 1 day ago. |
to | String | false | Date to in YYYY-MM-DD format. Default value: current date. |
String | false | Find only logs with specified email. | |
phone | String | false | Find only logs with specified phone. |
offset | Integer | false | Offset from the beginning of the selected dataset. Min: 0. |
limit | Integer | false | Limit of the returned dataset size. Max: 20000. |
Response properties
Parameter | Type | Description |
---|---|---|
contact_type | String | Type of contact: sms , email , mpush , wpush |
contact | String | Contact value |
campaign_type | String | Type of campaigns: bulk , chain , transactional , everything |
event | String | Type of event: subscribe , unsubscribe , hard_bounced , complained , blacklisted |
channel | String | Channel of event: api , js_sdk , unsubscribe_page , email_processing , etc |
datetime | String | Date and time in YYYY-MM-DD H:i:s format |
ip | String | IP from where request was received. Can be empty for some kinds of channel parameter. |
Event descriptions:
Event | Description |
---|---|
subscribe | User is subscribed for messages (email, sms) |
unsubscribe | User is unsubscribed |
hard_bounced | User's contact is hard bounced (not existing email, phone) |
complained | User is complained (FBL). As result: unsubscribed and suppressed |
blacklisted | User is blacklisted |
Channel descriptions
Event | Description |
---|---|
email_feedback_processing | Mailing feedback processing (FBL, bounce worker, automatic unsubscribe) |
api | Log from subscriptions/manage method |
api_callback | Log from subscriptions/callback method |
js_sdk | Event from JS SDK. Reserved |
mobile_sdk | Event from Mobile SDK. Reserved |
push_attributes | Event from event/push_attributes method. Deprecated |
auto_collector | Event from auto_collector service |
popup | Subscription from pop-up |
import | Subscription from audience import |
crm | Subscription management in CRM UI |
bulk_sending | Automatic bounce worker while sending bulk mailing |
transactional_sending | Automatic bounce worker while sending transactional mailing |
unsubscribe_page | User clicked on "unsubscribe" link in email sent by PersonaClick |
resubscribe_page | User clicked on "re-subscribe" link on PersonaClick's "unsubscribe" page |
Triggers
Trigger subscription methods that require explicit user action.
Price drop
# Subscribing
curl --location --request POST 'https://api.personaclick.com/subscriptions/subscribe_for_product_price' \
--header 'Content-Type: application/json' \
--data-raw '{
"shop_id":"SHOP_ID",
"email":"EMAIL",
"phone":"PHONE",
"did":"DeviceID",
"item_id":"11111",
"price": "1000"
}'
# Unsubscribing from specific products
curl --location --request POST 'https://api.personaclick.com/subscriptions/unsubscribe_from_product_price' \
--header 'Content-Type: application/json' \
--data-raw '{
"shop_id":"SHOP_ID",
"email":"EMAIL",
"phone":"PHONE",
"did":"DeviceID",
"item_ids":"11111, 22222, 333333"
}'
# Unsubscribing from all products
curl --location --request POST 'https://api.personaclick.com/subscriptions/unsubscribe_from_product_price' \
--header 'Content-Type: application/json' \
--data-raw '{
"shop_id":"SHOP_ID",
"email":"EMAIL",
"phone":"PHONE",
"did":"DeviceID",
"item_ids":""
}'
// Subscribing
personaclick('subscribe_trigger', 'product_price_decrease', {email: '[email protected]', item: '3323', price: 160});
// Unsubscribing from specific products
personaclick('unsubscribe_trigger', 'product_price_decrease', {email: '[email protected]', item_ids: [3323, 100500, 'ABCDEF']});
// Unsubscribing from all products
personaclick('unsubscribe_trigger', 'product_price_decrease', {email: '[email protected]', item_ids: []});
// Subscribe
sdk.subscribeForPriceDrop(id: "PRODUCT_ID", currentPrice: 333.49);
// Subscribe for specific email
sdk.subscribeForPriceDrop(id: "PRODUCT_ID", currentPrice: 333.49, email: "[email protected]");
// Subscribe for specific phone
sdk.subscribeForPriceDrop(id: "PRODUCT_ID", currentPrice: 333.49, phone: "+19999999999");
// Unsubscribe from price drop event
sdk.unsubscribeForPriceDrop(
itemIds: ["PRODUCT_ID"],
currentPrice: 333.49,
email: "USER_EMAIL",
phone: "USER_PHONE"
)
// Subscribe
sdk.subscribeForPriceDrop("PRODUCT_ID", 333.49)
// Subscribe for a specific email
sdk.subscribeForPriceDrop("PRODUCT_ID", 333.49, "[email protected]")
// Subscribe for a specific phone number
sdk.subscribeForPriceDrop("PRODUCT_ID", 333.49, null, "+19999999999")
// Unsubscribe from specific products
sdk.unsubscribeForPriceDrop(arrayOf("11111", "22222", "33333"))
// Unsubscribe from all products
sdk.unsubscribeForPriceDrop(arrayOf())
// Subscribe
Personaсlick.subscribeForPriceDrop("PRODUCT_ID", 333.49);
// Subscribe for specific email
Personaсlick.subscribeForPriceDrop("PRODUCT_ID", 333.49, "[email protected]");
// Subscribe for specific phone
Personaсlick.subscribeForPriceDrop("PRODUCT_ID", 333.49, null, "+19999999999");
// Unsubscribing from specific products
Personaсlick.unsubscribeForPriceDrop(new String[] {"11111", "22222", "33333"});
// Unsubscribing from all products
Personaсlick.unsubscribeForPriceDrop(new String[] {});
This feature gives the customers an option to choose if they want to receive a notification when the price of the item they want has dropped.
JS SDK syntax
Syntax |
---|
personaclick('subscribe_trigger', 'product_price_decrease', params); |
JS SDK Parameters
Parameter | Type | Requirement | Description |
---|---|---|---|
email* | string | required | Subscriber Email |
phone* | string | required | Subscriber Phone |
did* | string | required | Subscriber Did |
item | number/string | required | The ID of the product to which the user will be subscribed |
price | number/string | required | The current product price |
JS SDK syntax
Syntax |
---|
personaclick('unsubscribe_trigger', 'product_price_decrease', params); |
JS SDK Parameters
Parameter | Type | Requirement | Description |
---|---|---|---|
email* | string | required | Subscriber Email |
phone* | string | required | Subscriber Phone |
did* | string | required | Subscriber Did |
item_ids | array | required | The IDs of the products from which the user will unsubscribe, or an empty array for full unsubscription |
Back in Stock
# Subscribing
curl --location --request POST 'https://api.personaclick.com/subscriptions/subscribe_for_product_available' \
--header 'Content-Type: application/json' \
--data-raw '{
"shop_id":"SHOP_ID",
"email":"EMAIL",
"item_id":"11111",
"phone":"PHONE",
"did":"DeviceID",
"properties": {"fashion_size":"XL", "barcode": "222222"}
}'
# Unsubscribing from specific products
curl --location --request POST 'https://api.personaclick.com/subscriptions/unsubscribe_from_product_available' \
--header 'Content-Type: application/json' \
--data-raw '{
"shop_id":"SHOP_ID",
"email":"EMAIL",
"phone":"PHONE",
"did":"DeviceID",
"item_ids":"11111, 22222, 333333"
}'
# Unsubscribing from all products
curl --location --request POST 'https://api.personaclick.com/subscriptions/unsubscribe_from_product_available' \
--header 'Content-Type: application/json' \
--data-raw '{
"shop_id":"SHOP_ID",
"email":"EMAIL",
"phone":"PHONE",
"did":"DeviceID",
"item_ids":""
}'
// Subscribing
personaclick('subscribe_trigger', 'product_available', {email: '[email protected]', item: '3323', properties: {fashion_size: "XL", barcode: "222222"}});
// Unsubscribing from specific products
personaclick('unsubscribe_trigger', 'product_available', {email: '[email protected]', item_ids: [3323, 100500, 'ABCDEF']});
// Unsubscribing from all products
personaclick('unsubscribe_trigger', 'product_available', {email: '[email protected]', item_ids: []});
// Subscribe
sdk.subscribeForBackInStock(id: "PRODUCT_ID");
// Subscribe for specific email
sdk.subscribeForBackInStock(id: "PRODUCT_ID", email: "[email protected]");
// Subscribe for specific phone
sdk.subscribeForBackInStock(id: "PRODUCT_ID", phone: "+19999999999");
// Subscribe for Back In Stock
sdk.subscribeForBackInStock(id: "PRODUCT_ID", email: "USER_EMAIL", phone: "USER_PHONE", fashionSize: ["SIZE1", "SIZE2"]) { result in
switch result {
case .success:
// Handle success
case .failure(let error):
// Handle failure
}
}
// Unsubscribe for Back In Stock
sdk.unsubscribeForBackInStock(itemIds: ["ITEM_ID1", "ITEM_ID2"], email: "USER_EMAIL", phone: "USER_PHONE") { result in
switch result {
case .success:
// Handle success
case .failure(let error):
// Handle failure
}
}
// Subscribe
sdk.subscribeForBackInStock("PRODUCT_ID")
// Subscribe for a specific email
sdk.subscribeForBackInStock("PRODUCT_ID", "[email protected]")
// Subscribe for a specific phone number
sdk.subscribeForBackInStock("PRODUCT_ID", "+19999999999")
// Subscribe with product size
val properties = JSONObject()
properties.put("fashion_size", "XL")
sdk.subscribeForBackInStock("PRODUCT_ID", "[email protected]", null, properties, null)
// Unsubscribe from specific products
sdk.unsubscribeForBackInStock(arrayOf("11111", "22222", "33333"))
// Unsubscribe from all products
sdk.unsubscribeForBackInStock(arrayOf())
// Subscribe
Personaсlick.subscribeForBackInStock("PRODUCT_ID");
// Subscribe for specific email
Personaсlick.subscribeForBackInStock("PRODUCT_ID", "[email protected]");
// Subscribe for specific phone
Personaсlick.subscribeForBackInStock("PRODUCT_ID", "+19999999999");
// Subscribe with product size
JSONObject properties = new JSONObject();
properties.put("fashion_size", "XL");
Personaсlick.subscribeForBackInStock("PRODUCT_ID", properties, "[email protected]", null, null);
// Unsubscribing from specific products
Personaсlick.unsubscribeForBackInStock(new String[] {"11111", "22222", "33333"});
// Unsubscribing from all products
Personaсlick.unsubscribeForBackInStock(new String[] {});
// Subscribing
PersonaClick.triggers('subscribe_for_product_available', {email: '[email protected]', item: '3323', properties: {fashion_size: "XL"}});
// Unsubscribing from specific products
PersonaClick.triggers('unsubscribe_from_product_available', {email: '[email protected]', item_ids: [3323, 100500, 'ABCDEF']});
// Unsubscribing from all products
PersonaClick.triggers('unsubscribe_from_product_available', {email: '[email protected]', item_ids: []});
//
This feature helps you recover sales lost due to out-of-stock items by giving your customers an option to choose if they want to receive a notification when the item they want is back in stock.
JS SDK syntax
Syntax |
---|
personaclick('subscribe_trigger', 'product_available', params); |
JS SDK Parameters
Parameter | Type | Requirement | Description |
---|---|---|---|
email* | string | required | Subscriber Email |
phone* | string | required | Subscriber Phone |
did* | string | required | Subscriber Did |
item | number/string | required | The ID of the product to which the user will be subscribed |
params | object | optional | Product properties: barcode, fashion_color, fashion_size |
JS SDK syntax
Syntax |
---|
personaclick('unsubscribe_trigger', 'product_available', params); |
JS SDK Parameters
Parameter | Type | Requirement | Description |
---|---|---|---|
email* | string | required | Subscriber Email |
phone* | string | required | Subscriber Phone |
did* | string | required | Subscriber Did |
item_ids | array | required | The IDs of the products from which the user will unsubscribe, or an empty array for full unsubscription |
Transactionals
The method allows you to send transactional messages.
Request transactionals
# Request with JSON
curl --location --request POST 'https://api.personaclick.com/transact' \
--header 'Content-Type: application/json' \
--data-raw '"shop_id":"SHOP_ID", "shop_secret":"SHOP_SECRET", "code":"TRANSACTIONAL_MESSAGE_CODE", "email":"EMAIL", "variables":{"KEY":"VALUE", "KEY_2":"VALUE_2"}}'
# Request with FormData
curl --location --request POST 'https://api.personaclick.com/transact' \
--form 'file_name=@"local_file_path/local_file_name"' \
--form 'file_name_2=@"local_file_path/local_file_name_2"' \
--form 'shop_id="SHOP_ID"' \
--form 'shop_secret="SHOP_SECRET"' \
--form 'code="TRANSACTIONAL_MESSAGE_CODE"' \
--form 'email="EMAIL"' \
--form 'variables[KEY]="VALUE"'
--form 'variables[KEY_2]="VALUE_2"'
// REST API only. See cURL.
// REST API only. See cURL.
// REST API only. See cURL.
// REST API only. See cURL.
// REST API only. See cURL.
HTTP Request
GET https://api.personaclick.com/transact
Query Parameters
Parameter | Required | Description |
---|---|---|
shop_id | true | Your shop id |
shop_secret | true | Your shop secret |
code | true | Your transactional message code |
true | Client's email | |
variables | false | Object with custom data for message |
HTTP Response
HTTP status code | Response body | Explanation |
---|---|---|
200 | {"code": "12345"} | The request was successful. |
4xx (400-499) | {"status": "error", "message": "Error description text"} | The request was unsuccessful. See the reason in the message property of the response body. |
Mobile push tokens
Create new token
curl -d "did=DEVICE_ID&shop_id=SHOPID&token=TOKEN&platform=PLATFORM" https://api.personaclick.com/mobile_push_tokens
sdk.setPushTokenNotification(token: "TOKEN_STRING") { (tokenResponse) in
print("Token set response")
}
sdk.registerManager.setPushTokenNotification(
token = "token",
listener = object : OnApiCallbackListener() {
override fun onSuccess(msg: JSONObject?) {
//
}
}
)
Personaсlick.setPushTokenNotification("token", new Api.OnApiCallbackListener() {
@Override
public void onSuccess(JSONObject msg) {
//
}
});
// When you request permissions to send notifications and receive push token,
// send it to API using this method:
sdk.setPushTokenNotification('NEW_TOKEN');
The above command returns JSON structured like this:
{}
This endpoint creates new token for the user, identified by did
parameter.
HTTP Request
POST https://api.personaclick.com/mobile_push_tokens
Query Parameters
Parameter | Required | Description |
---|---|---|
did | true | Device ID. You get it from init method in SDK. |
platform | true | Identifies platform: ios for APNs or android for Firebase |
token | true | Unique mobile push token from iOS or Android. |
shop_id | true | Your API key |
Sending mobile push notifications
// Simple init
sdk.initPush();
//onClick listener
sdk.initPush(onClickCallback);
// onReceivetive listener
sdk.initPush(false, onReceiveCallback);
// you can use different callback for notification, when app is in background.
sdk.initPush(false, onReceiveCallback, onBackgroundReceiveCallback);
// If onBackgroundReceiveCallback not specified, used onReceiveCallback listener.
// onClickCallback params
{
"bigPictureUrl": "MESSAGE_IMAGE",
"channelId": "personaclick-push",
"data": {
"id": "MESSAGE_ID",
"type": "MESSAGE_TYPE"
},
"foreground": true,
"id": "MESSAGE_ID",
"largeIconUrl": "MESSAGE_ICON",
"message": "MESSAGE_BODY",
"title": "MESSAGE_TITLE",
"userInteraction": true
}
// onReceiveCallBack, onBackgroundReceiveCallback params
{
"data": {
"action_urls": "[]",
"actions": "[]",
"body": "MESSAGE_BODY",
"icon": "MESSAGE_ICON",
"id": "MESSAGE_ID",
"image": "MESSAGE_IMAGE",
"title": "MESSAGE_TITLE",
"type": "MESSAGE_TYPE"
},
"from": "MESSAGE_FROM",
"messageId": "FMC_MESSAGE_ID",
"sentTime": TIMESTAMP,
"ttl": TTL_VALUE
}
Default payload structure
For iOS
{
"aps": {
"alert": {
"title": "...",
"subtitle": "...",
"body": "...",
"badge": 1
},
"mutable-content": 1
},
"image_url": "...",
"event": {
"type": "...",
"uri": "..."
},
"src": {
"type": "...",
"id": "..."
}
}
For Android
{
"title": "...",
"body": "...",
"icon": "...",
"type": "...",
"id": "...",
"actions": "[{\"action\": "\b0\", \"title\": \"...\"}, ...]",
"action_urls": "[...]",
"image": "...",
"event": "{\"type\": \"...\", \"uri\": \"...\"}"
}
Android request example with analytics_label parameter
{
"to": "string",
"notification": {
"title": "Analitics message",
"body": "message contains analitytics label",
"sound": "default"
},
"data": {
"analytics_label": "example analytics label"
}
}
Parameter | Required | Description |
---|---|---|
aps.alert.title | true | The title of the notification. Apple Watch displays this string in the short look notification interface. Specify a string that is quickly understood by the user. |
aps.alert.subtitle | true | Additional information that explains the purpose of the notification. |
aps.alert.body | true | The content of the alert message. |
aps.alert.badge | true | The number to display in a badge on your app’s icon. Specify 0 to remove the current badge, if any. |
aps.mutable-content | true | Always 1 for iOS. |
image_url | false | Link to image/icon. |
event | false | Optional object with additional data. |
event.type | true | Type of the notification: web , category , product , custom . |
event.uri | true | Resource identificator depending on the type of event. See examples below. |
src | true | Information about a campaign (source of the message). |
src.type | true | Type of a campaign: bulk , chain , transactional . |
src.id | true | Type of a campaign. String. |
analytics_label | true | It's value is equals message |
Basic message
For iOS
{
"aps": {
"alert": {
"title": "Welcome aboard!",
"subtitle": "Greeting message.",
"body": "Hey, it's nice to know you're with us now. Check new updates in our application.",
"badge": 1
},
"mutable-content": 1
},
"image_url": "...",
"src": {
"type": "bulk",
"id": "33631"
}
}
For Android
{
"title": "Welcome aboard!",
"body": "Hey, it's nice to know you're with us now. Check new updates in our application.",
"icon": "...",
"type": "bulk",
"id": "33631"
}
This kind of message can be used to attract attention and open home screen of the application.
Open web link
For iOS
{
"aps": {
"alert": {
"title": "Only today",
"subtitle": "Special Offer",
"body": "This special offer for Dyson products only for you!",
"badge": 1
},
"mutable-content": 1
},
"image_url": "...",
"event": {
"type": "web",
"uri": "https://example.com/landing/promo"
},
"src": {
"type": "bulk",
"id": "XFMjM4VAF4"
}
}
For Android
{
"title": "Only today",
"body": "This special offer for Dyson products only for you!",
"icon": "...",
"type": "bulk",
"id": "XFMjM4VAF4",
"event": "{\"type\": \"web\", \"uri\": \"https://example.com/landing/promo\"}"
}
Usually used for promo campaigns when final action is to open some URL in web view.
Open category
For iOS
{
"aps": {
"alert": {
"title": "Black Friday!",
"subtitle": "Discount",
"body": "Check our big sale from this category",
"badge": 1
},
"mutable-content": 1
},
"image_url": "...",
"event": {
"type": "category",
"uri": "BFRIDAY_CATEGORY_ID"
},
"src": {
"type": "chain",
"id": "72CONd54uF"
}
}
For Android
{
"title": "Black Friday!",
"body": "Check our big sale from this category",
"icon": "...",
"type": "chain",
"id": "72CONd54uF",
"event": "{\"type\": \"category\", \"uri\": \"BFRIDAY_CATEGORY_ID\"}"
}
Suitable to open specific category by it's ID. For example for bulk messages about discounts.
Open product
For iOS
{
"aps": {
"alert": {
"title": "...",
"subtitle": "...",
"body": "...",
"badge": 1
},
"mutable-content": 1
},
"image_url": "...",
"event": {
"type": "product",
"uri": "PRODUCT123"
},
"src": {
"type": "chain",
"id": "ugLxQ7KrnL"
}
}
For Android
{
"title": "...",
"body": "...",
"icon": "...",
"type": "chain",
"id": "ugLxQ7KrnL",
"event": "{\"type\": \"product\", \"uri\": \"PRODUCT123\"}"
}
Suitable to open specific product by it's ID. For example for triggered messages.
Open custom page
For iOS
{
"aps": {
"alert": {
"title": "...",
"subtitle": "...",
"body": "...",
"badge": 1
},
"mutable-content": 1
},
"image_url": "...",
"event": {
"type": "custom",
"uri": "order/status/36",
"payload": {}
},
"src": {
"type": "transactional",
"id": "order_delivered"
}
}
For Android
{
"title": "...",
"body": "...",
"type": "transactional",
"id": "order_delivered",
"event": "{\"type\": \"custom\", \"uri\": \"order/status/36\", \"payload\": {}}"
}
Can be used to open any resource by custom data. For example for transactional messages to show order status.
Custom push notifications
No implementation needed
No implementation needed
No implementation needed
No implementaion needed
No implementaion needed
No implementaion needed
A custom notification will work if both of the following criteria are met.
First, the platform checks if attach_notification
is enabled.
The second condition is a custom action on click, which must be set up beforehand.
Once these two conditions are satisfied, the notification
array will be sent to FCM.
The notification
array includes a special parameter for Android called click_action
.
An application developer needs to configure click_action
inside the AndroidManifest.
To link click_action
with a specific activity, the developer must use an intent-filter
. Example:
<activity android:name=".DetailActivity">
<intent-filter>
<action android:name="com.example.app.ACTION_OPEN_DETAIL" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
User's profile
Endpoints are used to work with user's profile.
Save profile settings
curl -d "shop_id=SHOPID&shop_secret=SHOP_SECRET&email=EMAIL&fieldname=FIELDVALUE" https://api.personaclick.com/profile/set
personaclick('profile', 'set', {
"email": "[email protected]",
"id": "123456789",
"loyalty_id": "987654321",
"phone": "19991005000",
"first_name": "Jane",
"last_name": "Smith",
"location": "sdsdfsdfsdf",
"kids": [
{"gender": "m", "birthday": "2017-06-04"},
{"gender": "f", "birthday": "2014-02-10"},
{"gender": "m", "birthday": "2014-03-17"}
]
});
//An example of using custom fields by type
personaclick('profile', 'set', {
"string": "sdsdfsdfsdf",
"int": 123,
"float": 123.12,
"list_element": ["first", "second"],
"json": {"key": "val", "key2": "val2"},
"date": "2022-08-26"
});
// The iOS SDK profile can work with any type of array, as well as with objects.
sdk.setProfileData(
userEmail: "YOUR_EMAIL",
userPhone: "YOUR_PHONE",
userLoyaltyId: "YOUR_LOYALTY_ID",
birthday: Date(),
age: 30,
firstName: "YOUR_NAME",
lastName: "YOUR_LAST_NAME",
location: "YOUR_LOCATION",
gender: .male,
fbID: "YOUR_FB_ID",
vkID: "YOUR_VK_ID",
telegramId: "YOUR_TG_ID",
loyaltyCardLocation: "LOYALTY_CARD_LOCATION",
loyaltyStatus: "LOYALTY_SATUS",
loyaltyBonuses: 100,
loyaltyBonusesToNextLevel: 200,
boughtSomething: true,
userId: "YOUR_USER_ID",
customProperties: customProperties
)
// Examples of arrays
let stringArray = ["item1", "item2", "item3"]
let intArray = [1, 2, 3, 4, 5]
let floatArray: [Float] = [1.1, 2.2, 3.3]
let boolArray = [true, false, true]
let dateArray = [Date(),Date(),Date()]
// Object example
let object: [String: Any] = [
"stringKey": "stringValue",
"intKey": 123,
"floatKey": 45.67,
"boolKey": true,
"dateKey": Date(),
"arrayKey": [1, 2, 3],
"nestedObjectKey": [
"nestedStringKey": "nestedValue",
"nestedIntKey": 456
]
]
// Custom properties example
let customProperties: [String: Any] = [
"stringArray": stringArray,
"intArray": intArray,
"floatArray": floatArray,
"boolArray": boolArray,
"dateArray": dateArray,
"customObject": object
]
// Create a map of parameters
val params = hashMapOf(
"email" to "[email protected]"
)
// Use the SDK to update the profile
sdk.profile(params)
// With callback
sdk.profile(params, object : OnApiCallbackListener() {
override fun onSuccess(response: JSONObject?) {
Log.i(TAG, "Response: ${response.toString()}")
}
})
HashMap<String, String> params = new HashMap<>();
params.put("email", "[email protected]");
Personaсlick.profile(params);
//With callback
Personaсlick.profile(params, new Api.OnApiCallbackListener() {
@Override
public void onSuccess(JSONObject response) {
Log.i(TAG, "Response: " + response.toString());
}
});
const params = {
id: 100500,
email: "[email protected]",
phone: "4400114527199",
first_name: "John",
last_name: "Doe",
birthday: "1990-03-11",
age: 31,
gender: "m",
location: "NY",
bought_something: true,
loyalty_id: "000001234567",
loyalty_card_location: "NY",
loyalty_status: "5% discount",
loyalty_bonuses: 1123,
loyalty_bonuses_to_next_level: 1877,
fb_id: "000000000354677",
vk_id: "vk031845",
telegram_id: "0125762968357835",
kids: [
{gender: "m", birthday: "2001-04-12"},
{gender: "f", birthday: "2015-07-28"}
],
auto: [
{brand: "Nissan", model: "Qashqai", vds: "TM7N243E4G0BJG978"}
]
};
sdk.setProfile(params);
This method overrides profile's settings.
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Your API secret key |
did* | String | true | Device ID |
email* | String | true | User's email |
phone* | String | true | User's phone number |
Default properties
You can update any standard profile property. All standard properties are listed here:
Parameter | Type | Description |
---|---|---|
loyalty_id | String | User's loyalty program ID |
id | String | User ID in your platform |
fb_id | String | User's Facebook ID |
vk_id | String | User's VK ID |
telegram_id | String | User's Telegram ID |
loyalty_card_location | String | Location ID where user's loyalty card was issued |
loyalty_status | String | User's loyalty program status |
loyalty_bonuses | Integer | User's bonuses amount |
loyalty_bonuses_to_next_level | Integer | User's bonuses amount left for the next level |
gender | String | User's gender: m or f |
location | String | User's location code |
first_name | String | User's first name |
last_name | String | User's last name |
age | Integer | User's age in years |
birthday | Date | User's birthday in SQL format: YYYY-MM-DD |
bought_something | Bool | User bought something ever |
kids | Array | List of kids (see below) |
auto | Array | List of auto vehicles (see below) |
Kid object properties:
Parameter | Type | Description |
---|---|---|
gender | String | Kid's gender: m or f |
birthday | Date | Kid's birthday in SQL format: YYYY-MM-DD |
Auto object properties:
Parameter | Type | Description |
---|---|---|
brand | String | Vehicle brand |
model | String | Vehicle model |
vds | String | Vehicle VDS/VIN number |
Custom properties
Additionally you can update any custom property, you've created in CRM.
Read profile info
# Using email as user identifier
curl https://api.personaclick.com/profile?email=...&shop_id=...&shop_secret=...
# Using phone as user identifier
curl https://api.personaclick.com/profile?phone=...&shop_id=...&shop_secret=...
personaclick('profile', 'get', function(profile) {
// Here you can use all properties of profile's object
console.log(profile.gender);
console.log(profile.fashion.sizes.shoe);
},
// Use `true`, to work in single page sites.
// Default - `false`
false
);
REST method returns this JSON structure
{
"first_name": "...",
"last_name": "...",
"email": "...",
"phone": "...",
"fb_id": "...",
"vk_id": "...",
"telegram_id": "...",
"loyalty_id": "...",
"loyalty_card_location": "...",
"loyalty_status": "...",
"loyalty_bonuses": "...",
"loyalty_bonuses_to_next_level": "...",
"gender": "...",
"location": "...",
"age": "...",
"birthday": "...",
"bought_something": "...",
"tags": [
"...",
"..."
],
"custom_properties": {
"prop_key_1": "prop_value",
"prop_key_2": "prop_value"
},
"additional_phones": [],
"additional_emails": [],
"additional_loyalty_ids": [],
"orders": [
{
"id": "...",
"value": "...",
"status": "...",
"items": [
{
"id": "...",
"price": "...",
"name": "...",
"quantity": "..."
},
{
"id": "...",
"price": "...",
"name": "...",
"quantity": "..."
}
]
}
]
}
JS SDK method returns simplified anonymous structure to prevent data stealing
{
"fashion_sizes": ["..."],
"gender": "m or f",
"cosmetic_hair": ["..."],
"allergy": "bool",
"cosmetic_skin": ["..."],
"cosmetic_perfume": ["..."],
"compatibility": null,
"vds": null,
"jewelry": null,
"realty": ["..."],
"children": ["..."],
"child_gender": "m or f",
"pets": ["..."],
"income_level": "cheap"
}
You can read profile info from CRM using API or SDK.
In case of using REST API (when using email or phone number as user ID), you must provide secret key to the method.
Force change email
curl -d "shop_id=SHOPID&shop_secret=SHOP_SECRET&new_email=NEW_EMAIL&old_email=OLD_EMAIL" https://api.personaclick.com/profile/force_change_email
// Not supported
// Not supported
// Not supported
// Not supported
// Not supported
Force change email of user with old_email
to new_email
. If a user with new_email
exists, removes email from that user.
If user with old_email
is not found, returns 404.
It's S2S method.
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Your API secret key |
new_email | String | true | User's new email |
old_email | String | true | User's current email |
i_understand_what_i_am_doing | String | true | Must present with any true value (true , "true" , 1 , yes , believe me I know what I am doing , etc). |
Force change phone
curl -d "shop_id=SHOPID&shop_secret=SHOP_SECRET&new_phone=NEW_PHONE&old_phone=OLD_PHONE" https://api.personaclick.com/profile/force_change_phone
// Not supported
// Not supported
// Not supported
// Not supported
// Not supported
Force change phone of user with old_phone
to new_phone
. If a user with new_phone
exists, removes phone from that user.
If user with old_phone
is not found, returns 404.
It's S2S method.
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Your API secret key |
new_phone | String | true | User's new phone |
old_phone | String | true | User's current phone |
i_understand_what_i_am_doing | String | true | Must present with any true value (true , "true" , 1 , yes , believe me I know what I am doing , etc). |
Audience
This section allows to manage users, their subscriptions and segments.
Import users
curl -i -X POST -H "Content-Type: application/json" --data-binary "@data.json" https://api.personaclick.com/import/audience
# data.json
{
"shop_id": "1234567890",
"shop_secret": "0987654321",
"segment_id": "123",
"audience": [
{
"email": "[email protected]",
"loyalty_id": "123454321",
"phone": "19991005000",
"id": "998877",
"fb_id": "",
"vk_id": "",
"telegram_id": "",
"loyalty_card_location": "",
"loyalty_status": "VIP",
"loyalty_bonuses": 3000,
"loyalty_bonuses_to_next_level": 70000,
"gender": "",
"location": "",
"first_name": "Jane",
"last_name": "Smith",
"age": "",
"birthday": "",
"bought_something": true,
"email_bulk": true,
"email_chain": true,
"email_transactional": true,
"sms_bulk": true,
"sms_chain": true,
"sms_transactional": true,
"mobile_token": "TOKEN",
"mobile_token_platform": "PLATFORM",
"auto": [
{
"brand": "Mini",
"model": "Countryman",
"vds": "1234567"
},
{
"brand": "Toyota",
"model": "Corolla",
"vds": "987655431"
}
],
"kids": [
{
"birthday": "2014-06-03",
"gender": "f"
},
{
"birthday": "2017-04-01",
"gender": "m"
}
],
},
{...},
{...},
]
}
// No implementation is needed in JS SDK
// No implementation is needed in iOS SDK
// No implementation is needed in Android SDK
// No implementation is needed in Android SDK
Upload audience to database. You can upload users to the default segment or put it in the specific segment. At the same time you can subscribe or unsubscribe users from any kind of email campaigns.
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Your API secret key |
segment_id | Integer | false | Segment ID |
audience | Array | true | Array of user data objects (see below) |
Audience element properties
You can update any standard profile property. All standard properties are listed here:
Parameter | Type | Description |
---|---|---|
email* | String | User's email |
phone* | String | User's phone number |
loyalty_id | String | User's loyalty program ID |
id | String | User ID in your platform |
fb_id | String | User's Facebook ID |
vk_id | String | User's VK ID |
telegram_id | String | User's Telegram ID |
loyalty_card_location | String | Location ID where user's loyalty card was issued |
loyalty_status | String | User's loyalty program status |
loyalty_bonuses | Integer | User's bonuses amount |
loyalty_bonuses_to_next_level | Integer | User's bonuses amount left for the next level |
gender | String | User's gender: m or f |
location | String | User's location code |
first_name | String | User's first name |
middle_name | String | User's middle name |
last_name | String | User's last name |
age | Integer | User's age in years |
birthday | Date | User's birthday in SQL format: YYYY-MM-DD |
bought_something | Bool | User bought something ever |
kids | Array | List of kids (see below) |
auto | Array | List of auto vehicles (see below) |
email_bulk | Boolean | Subscribe user to email bulk campaigns |
email_chain | Boolean | Subscribe user to email drip/trigger campaigns |
email_transactional | Boolean | Subscribe user to email transactional campaigns |
sms_bulk | Boolean | Subscribe user to SMS bulk campaigns |
sms_chain | Boolean | Subscribe user to SMS drip/trigger campaigns |
sms_transactional | Boolean | Subscribe user to SMS transactional campaigns |
mobile_token | String | Unique mobile push token from iOS or Android |
mobile_token_platform | String | Identifies platform: ios for APNs or android for Firebase |
Kid object properties:
Parameter | Type | Description |
---|---|---|
gender | String | Kid's gender: m or f |
birthday | Date | Kid's birthday in SQL format: YYYY-MM-DD |
Auto object properties:
Parameter | Type | Description |
---|---|---|
brand | String | Vehicle brand |
model | String | Vehicle model |
vds | String | Vehicle VDS/VIN number |
Custom properties
Additionally you can update any custom property, you've created in CRM.
Import suppressed emails
curl -i -X POST -H "Content-Type: application/json" --data-binary "@data.json" https://api.personaclick.com/import/suppressed
# data.json
{
"shop_id": "1234567890",
"shop_secret": "0987654321",
"audience": [
{ "email": "[email protected]" },
{ "email": "[email protected]" },
]
}
// No implementation is needed in JS SDK
// No implementation is needed in iOS SDK
// No implementation is needed in Android SDK
// No implementation is needed in Android SDK
Upload suppressed emails to database. All emails from this list will be unsubscribed from emails and marked as suppressed.
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Your API secret key |
audience | Array | true | Array of user data objects (see below) |
Audience element properties
Parameter | Type | Description |
---|---|---|
String | User's email |
CRM
This section collects CRM-related methods.
Bulk search by attribute
curl -i -X POST -H "Content-Type: application/json" --data-binary "@data.json" https://api.personaclick.com/crm/search/bulk
# data.json
{
"shop_id": "1234567890",
"shop_secret": "0987654321",
"by": "loyalty_id",
"ids": ["L01", "L02"]
}
// No implementation is needed in JS SDK
// No implementation is needed in iOS SDK
// No implementation is needed in Android SDK
// No implementation is needed in Android SDK
Response structure
[
{
"email": "[email protected]",
"external_id": "1",
"phone": "11111111111",
"first_name": null,
"last_name": null,
"gender": null,
"age": null,
"birthday": null,
"location": null,
"email_bulk": true,
"email_chain": true,
"email_transactional": true,
"web_push": true,
"mobile_push": null,
"sms_bulk": null,
"sms_chain": null,
"sms_transactional": null,
"loyalty_id": "L01",
"loyalty_location": null,
"loyalty_status": null,
"loyalty_bonuses": 300,
"loyalty_bonuses_to_next_level": null,
"created_date": null,
"device": null
},
{
"email": "[email protected]",
"external_id": "1",
"phone": null,
"first_name": "Thomas",
"last_name": "Anderson",
"gender": "m",
"age": null,
"birthday": "1971-09-11",
"location": null,
"email_bulk": true,
"email_chain": true,
"email_transactional": true,
"web_push": true,
"mobile_push": null,
"sms_bulk": null,
"sms_chain": null,
"sms_transactional": null,
"loyalty_id": "L02",
"loyalty_location": null,
"loyalty_status": null,
"loyalty_bonuses": 0,
"loyalty_bonuses_to_next_level": null,
"created_date": null,
"device": null
}
]
Methods tries to find a collection of users by list of identifiers. Identifiers can be: email, phone, loyalty_id.
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Your API secret key |
by | String | true | Type of identifier. See below. |
ids | Array | true | Array of identifiers |
Supported identifiers
Identifier | Description | Restrictions |
---|---|---|
loyalty_id | Loyalty ID | No restrictions |
birthday | Birthday | Format: YYYY-MM-DD . Processing only 5 valid dates. Other dates are skipped |
Segments
The endpoint is used to put or remove user to/from static segment.
Add user to a segment
# Using all possible identifiers
curl -d "shop_id=SHOPID&shop_secret=SHOP_SECRET&email=EMAIL&phone=PHONE&segment_id=SEGMENT_ID" https://api.personaclick.com/segments/add
# With phone only
curl -d "shop_id=SHOPID&shop_secret=SHOP_SECRET&phone=PHONE&segment_id=SEGMENT_ID" https://api.personaclick.com/segments/add
# With email only
curl -d "shop_id=SHOPID&shop_secret=SHOP_SECRET&email=EMAIL&segment_id=SEGMENT_ID" https://api.personaclick.com/segments/add
// Using all possible identifiers
personaclick('segment', 'add', {
"email": "[email protected]",
"phone": "+10000000000",
"segment_id": "SEGMENT_ID"
});
// With phone only
personaclick('segment', 'add', {
"phone": "+10000000000",
"segment_id": "SEGMENT_ID"
});
// With email only
personaclick('segment', 'add', {
"email": "[email protected]",
"segment_id": "SEGMENT_ID"
});
// Without any contacts: `did` is used automatically
personaclick('segment', 'add', {
"segment_id": "SEGMENT_ID"
});
// By `did` only
sdk.addToSegment(segmentId: "333")
// With a email (`did` will be switched to the owner of the email)
sdk.addToSegment(segmentId: "333", email: "[email protected]")
// With a phone number (`did` will be switched to the owner of the phone number)
sdk.addToSegment(segmentId: "333", phone: "+10000000000")
// With both (`did` will be switched to the owner of primary contact)
sdk.addToSegment(segmentId: "333", email: "[email protected]", phone: "+10000000000")
// By `did` only
Personaсlick.addToSegment("333", null, null);
// With a email (`did` will be switched to the owner of the email)
Personaсlick.addToSegment("333", "[email protected]", null);
// With a phone number (`did` will be switched to the owner of the phone number)
Personaсlick.addToSegment("333", null, "+10000000000");
// With both (`did` will be switched to the owner of primary contact)
Personaсlick.addToSegment("333", "[email protected]", "+10000000000");
// By `did` only
Personaсlick.addToSegment("333", null, null);
// With a email (`did` will be switched to the owner of the email)
Personaсlick.addToSegment("333", "[email protected]", null);
// With a phone number (`did` will be switched to the owner of the phone number)
Personaсlick.addToSegment("333", null, "+10000000000");
// With both (`did` will be switched to the owner of primary contact)
Personaсlick.addToSegment("333", "[email protected]", "+10000000000");
// Using all possible identifiers
sdk.segments('add', {
"email": "[email protected]",
"phone": "+10000000000",
"segment_id": "SEGMENT_ID"
});
// With phone only
sdk.segments('add', {
"phone": "+10000000000",
"segment_id": "SEGMENT_ID"
});
// With email only
sdk.segments('add', {
"email": "[email protected]",
"segment_id": "SEGMENT_ID"
});
// Without any contacts: `did` is used automatically
sdk.segments('add', {
"segment_id": "SEGMENT_ID"
});
This method adds user to a specific static segment.
POST https://api.personaclick.com/segments/add
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Your API secret key |
did* | String | User's device ID. Only for JS/iOS/Android SDK | |
email* | String | User's email | |
phone* | String | User's phone number | |
segment_id | String | Segment ID |
Remove user from a segment
# Using all possible identifiers
curl -d "shop_id=SHOPID&shop_secret=SHOP_SECRET&email=EMAIL&phone=PHONE&segment_id=SEGMENT_ID" https://api.personaclick.com/segments/remove
# With phone only
curl -d "shop_id=SHOPID&shop_secret=SHOP_SECRET&phone=PHONE&segment_id=SEGMENT_ID" https://api.personaclick.com/segments/remove
# With email only
curl -d "shop_id=SHOPID&shop_secret=SHOP_SECRET&email=EMAIL&segment_id=SEGMENT_ID" https://api.personaclick.com/segments/remove
// Using all possible identifiers
personaclick('segment', 'remove', {
"email": "[email protected]",
"phone": "+10000000000",
"segment_id": "SEGMENT_ID"
});
// With phone only
personaclick('segment', 'remove', {
"phone": "+10000000000",
"segment_id": "SEGMENT_ID"
});
// With email only
personaclick('segment', 'remove', {
"email": "[email protected]",
"segment_id": "SEGMENT_ID"
});
// Without any contacts: `did` is used automatically
personaclick('segment', 'remove', {
"segment_id": "SEGMENT_ID"
});
// By `did` only
sdk.removeFromSegment(segmentId: "333")
// With a email (`did` will be switched to the owner of the email)
sdk.removeFromSegment(segmentId: "333", email: "[email protected]")
// With a phone number (`did` will be switched to the owner of the phone number)
sdk.removeFromSegment(segmentId: "333", phone: "+10000000000")
// With both (`did` will be switched to the owner of primary contact)
sdk.removeFromSegment(segmentId: "333", email: "[email protected]", phone: "+10000000000")
// By `did` only
Personaсlick.removeFromSegment("333", null, null);
// With a email (`did` will be switched to the owner of the email)
Personaсlick.removeFromSegment("333", "[email protected]", null);
// With a phone number (`did` will be switched to the owner of the phone number)
Personaсlick.removeFromSegment("333", null, "+10000000000");
// With both (`did` will be switched to the owner of primary contact)
Personaсlick.removeFromSegment("333", "[email protected]", "+10000000000");
// By `did` only
Personaсlick.removeFromSegment("333", null, null);
// With a email (`did` will be switched to the owner of the email)
Personaсlick.removeFromSegment("333", "[email protected]", null);
// With a phone number (`did` will be switched to the owner of the phone number)
Personaсlick.removeFromSegment("333", null, "+10000000000");
// With both (`did` will be switched to the owner of primary contact)
Personaсlick.removeFromSegment("333", "[email protected]", "+10000000000");
// Using all possible identifiers
sdk.segments('remove', {
"email": "[email protected]",
"phone": "+10000000000",
"segment_id": "SEGMENT_ID"
});
// With phone only
sdk.segments('remove', {
"phone": "+10000000000",
"segment_id": "SEGMENT_ID"
});
// With email only
sdk.segments('remove', {
"email": "[email protected]",
"segment_id": "SEGMENT_ID"
});
// Without any contacts: `did` is used automatically
sdk.segments('remove', {
"segment_id": "SEGMENT_ID"
});
This method removes user from a specific static segment.
POST https://api.personaclick.com/segments/remove
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Your API secret key |
did* | String | User's device ID. Only for JS/iOS/Android SDK | |
email* | String | User's email | |
phone* | String | User's phone number | |
segment_id | String | Segment ID |
Get user segments
# Using all possible identifiers
curl "shop_id=SHOPID&shop_secret=SHOP_SECRET&email=EMAIL&phone=PHONE" https://api.personaclick.com/segments/get
# With phone only
curl "shop_id=SHOPID&shop_secret=SHOP_SECRET&phone=PHONE" https://api.personaclick.com/segments/get
# With email only
curl "shop_id=SHOPID&shop_secret=SHOP_SECRET&email=EMAIL" https://api.personaclick.com/segments/get
// Using all possible identifiers
personaclick('segment', 'get', function(segments) {
// segments (type: array of objects)
// each object has the following properties:
// "id" as Segment ID
// "type" as Segment Type ("dynamic", "static")
});
sdk->getCurrentSegment()
sdk.getCurrentSegment(object: OnApiCallbackListener() {
override fun onSuccess(response: JSONArray) {
// segments (type: array of objects)
}
})
Personaсlick.getCurrentSegment(new Api.OnApiCallbackListener() {
@Override
public void onSuccess(JSONArray segments) {
// segments (type: array of objects)
}
});
// Using all possible identifiers
sdk.segments('get').then(res => {
// segments (type: array of objects)
// each object has the following properties:
// "id" as Segment ID
// "type" as Segment Type ("dynamic", "static")
});
Response structure
[
{
"id": 313,
"type": "static"
},
{
"id": 314,
"type": "dynamic"
}
]
The method returns an array of segments of the current user.
GET https://api.personaclick.com/segments/get
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Your API secret key |
did* | String | User's device ID. Only for JS/iOS/Android SDK | |
email* | String | User's email | |
phone* | String | User's phone number |
Check if a user is in a segment
# Using all possible identifiers
curl "shop_id=SHOPID&shop_secret=SHOP_SECRET&email=EMAIL&phone=PHONE" https://api.personaclick.com/segments/includes
# With phone only
curl "shop_id=SHOPID&shop_secret=SHOP_SECRET&phone=PHONE" https://api.personaclick.com/segments/includes
# With email only
curl "shop_id=SHOPID&shop_secret=SHOP_SECRET&email=EMAIL" https://api.personaclick.com/segments/includes
// Not implemented
// Not implemented
// Not implemented
// Not implemented
Response structure
true
The method returns TRUE|FALSE if a user identified by any identifier is included in a segment.
GET https://api.personaclick.com/segments/includes
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Your API secret key |
String | true* | User's email | |
phone | String | true* | User's phone number |
segment_id | Integer | true | Segment ID |
Orders
This section describes how to import orders, change its' statuses, structure and other.
TEST
Import orders
curl -i -X POST -H "Content-Type: application/json" --data-binary "@data.json" https://api.personaclick.com/sync/orders
# data.json
{
"shop_id": "DvLWN2ZTMZ",
"shop_secret": "EIxTuot8sj",
"orders": [
{
"id": "yKsvZbWpCL",
"status": "Delivered",
"channel": "website",
"date": 1602338740,
"offline": false,
"email": "[email protected]",
"phone": "+15554443322",
"loyalty_id": "000-33-444-111",
"location_id": "7701123",
"promocode": "vxawxSi9Uy",
"delivery_type": "courier",
"delivery_address": "Rouse st, 13",
"delivery_date": "2021-12-21",
"delivery_time": "15:00",
"tax_free": true,
"bank_issuer": "Sberbank",
"bank_pos_processor": "apex",
"bank_loyalty_program": "miles&smiles",
"bank_total_installment": 4,
"payment_card_provider": "mastercard"
"gift_package":true,
"value": {
"total": 200.13,
},
"payment_structure": {
"cash": 190,
"bonuses": 15,
"delivery": 20,
"discount": 24.87
},
"items": [
{
"id": "ITEM-ID-1",
"price": 205,
"quantity": 1,
"status": "cancelled",
"original_price": 230,
"discount_product": 30,
"discount_coupon": 10,
"discount_bonuses": 20,
"delivery_company": "ups",
"barcode_id": "195204003541",
"line_id": "195204003541-22323443-123434",
"cancel_reason": "over size",
},
}
...
]
},
...
]
}
If a request contains orders with IDs which are already saved in our database, statuses and structure of this orders will be updated.
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Your API secret key |
orders | Array | true | List of orders. See description below. |
Description of orders
objects:
Parameter | Type | Required | Description |
---|---|---|---|
id | String | true | Order ID |
status | String | true | Order's status |
channel | String | true | Channel where order was updated |
date | Integer | true | Date and time when order status changed |
offline | Boolean | false | Flags orders as offline. Default false . |
String | true* | User's email | |
phone | String | true* | User's phone |
loyalty_id | String | true* | User's loyalty ID |
location_id | String | true* | User's location (city) ID |
promocode | String | false | Promo code used in the order |
delivery_type | String | false | Delivery type |
delivery_address | String | false | Destination address for CRM |
delivery_date | Date | false | Planned delivery date. Format: "YYYY-MM-DD" |
delivery_time | Time | false | Planned delivery time. Format: "HH:MM" |
payment_type | String | false | Payment type. Can by any string value. Ex: cash, card, wire. |
tax_free | Boolean | false | Tax free |
bank_issuer | String | false | Bank issuer |
bank_pos_processor | String | false | Bank POS processor |
bank_loyalty_program | String | false | Bank loyalty program |
bank_total_installment | Integer | false | Bank total installment |
payment_card_provider | String | false | Payment card provider |
gift_package | Boolean | false | Gift packaged |
value | Object | true | Describes order's value parts. See below. |
payment_structure | Object | false | Describes order's payment_structure parts. See below. |
items* | Array | true | Describes order's products. See below. |
Description of value
object:
Parameter | Type | Required | Description |
---|---|---|---|
total | Numeric | true | Order's total value |
Description of payment_structure
object:
Parameter | Type | Required | Description |
---|---|---|---|
cash | Numeric | false | Describes how much of order's value was paid by real money. |
bonuses | Numeric | false | Describes how much of order's value was paid by bonuses. |
delivery | Numeric | false | Describes price of order's delivery |
discount | Numeric | false | Describes discount value of the order. |
Description of items
objects:
Parameter | Type | Required | Description |
---|---|---|---|
id | String | true | ID of purchased product |
price | Numeric | true | Price of 1 unit of purchased product |
quantity | Integer | true | Quantity of mentioned products in the order |
status | String | false | Item status, Can by only: created, invoiced, shipped, delivered, cancelled, refunded |
original_price | Numeric | false | Original item price |
discount_product | Numeric | false | Discount item |
discount_coupon | Numeric | false | Discount item coupon |
discount_bonuses | Numeric | false | Discount item bonuses |
delivery_company | String | false | Delivery item company |
barcode | String | false | Item barcode |
line_id | String | false | Unique identifier of the item position in the order on the store's side |
cancel_reason | String | false | Cancel reason |
Send cancelled orders
You can change order's status to "Cancelled". Order status must linked with our system status. Just send new request with the same order ID and order will be updated.
curl -i -X POST -H "Content-Type: application/json" --data-binary "@data.json" https://api.personaclick.com/sync/orders
# data.json
{
"shop_id": "DvLWN2ZTMZ",
"shop_secret": "EIxTuot8sj",
"orders": [
{
"id": "yKsvZbWpCL",
"status": "Cancelled"
},
...
]
}
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Your API secret key |
orders | Array | true | List of orders. See description below. |
Description of orders
objects:
Parameter | Type | Required | Description |
---|---|---|---|
id | String | true | Order ID |
status | String | true | Order's status |
Get users last order products
curl https://api.personaclick.com/orders/last_for_user?shop_id=SHOP_ID&did=DID&sid=SEANCE_ID
If a request fetches user's last purchase and returns list of purchased products. If there was not purchases, empty array is returned.
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
did | String | true | Users device ID |
sid | String | true | Users session ID |
Get user's orders
curl https://api.personaclick.com/orders/by_user?shop_id=SHOP_ID&shop_secret=SHOP_SECRET&did=DID&date_from=YYYY-MM-DD
// Not supported
// Not supported
// Not supported
// Not supported
// Not supported
Returns a list of user's orders (ascending by date and internal ID). User is identified by did
, email
, phone
, loyalty_id
or external_id
.
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Your API secret key |
did | String | false | User's device ID |
String | false | User's email | |
phone | String | false | User's phone |
loyalty_id | String | false | User's loyalty ID |
external_id | String | false | User's external ID |
date_from | Date | false | Date in YYYY-MM-DD format |
Custom orders
//TODO
//TODO
//TODO
// Example of setting custom order parameters
class CustomOrderParameters {
// Method to set parameters
fun set(name: String, value: Any): CustomOrderParameters {
// implementation here
return this
}
}
// Creating an instance of CustomOrderParameters and setting various types of parameters
val orderParams = CustomOrderParameters()
// for String
orderParams.set("tour_class", "lux")
// for int
orderParams.set("rooms", 5)
// for double
orderParams.set("change", 5.5)
// for boolean
orderParams.set("booked", true)
// value in parameters can be String, int, double, boolean
public CustomOrderParameters set(@NonNull String name, @NonNull String value) {
// for String
.set("tour_class", "lux")
// for int
.set("rooms", 5)
// for double
.set("change", 5.5)
// for boolean
.set("booked", true)
}
//TODO
Promo codes
Service provides endpoints for promo codes management.
List of promo codes lists
curl https://api.personaclick.com/promo_codes?shop_id=SHOPID&shop_secret=SHOP_SECRET
The above command returns JSON structured like this:
[
{
"id": 3184,
"name": "Abandoned cart trigger discount codes",
"available": 3744
}
]
This method returns list of existing promo codes lists with count of available promo codes in each list.
HTTP Request
GET https://api.personaclick.com/promo_codes
Query Parameters
Parameter | Required | Type | Description |
---|---|---|---|
shop_id | true | string | Your API key |
shop_secret | true | string | Your API secret key |
active | false | integer | Return only lists with at least 1 free code (value 1 ) |
exclude | false | string | Comma separated list of IDs of lists to exclude |
include | false | string | Comma separated list of IDs of lists to include in result (excludes others) |
offset | false | integer | Offset for pagination. Default: 0 |
limit | false | integer | Limit for pagination. Default: 1000 |
Errors
When promo secret key is wrong, method returns 403 error.
Upload promo codes
Headers
Content-type: application/json
Body example
{
"shop_id": "...",
"shop_secret": "...",
"id": "...",
"codes": [ "code1", "code2", "code3" ]
}
Request example
curl --header "Content-Type: application/json" \
--request POST \
--data-binary "@data.json" \
https://api.personaclick.com/promo_codes
Method uploads list of unique promo codes to the selected list. All non-unique promo codes will be excluded.
HTTP Request
POST https://api.personaclick.com/promo_codes
Content-Type: application/json
Query Parameters
Parameter | Required | Description |
---|---|---|
shop_id | true | Your API key |
shop_secret | true | Your API secret key |
id | true | Promo codes list ID |
codes | true | List of promo codes |
Delete not sent promo codes
Headers
Content-type: application/json
Body example
{
"shop_id": "...",
"shop_secret": "...",
"id": "...",
}
Request example
curl --header "Content-Type: application/json" \
--request DELETE \
--data-binary "@data.json" \
https://api.personaclick.com/promo_codes/purge
Method deletes promo codes from the list which were not sent to any user. It's useful to clean up time sensitive codes.
HTTP Request
DELETE https://api.personaclick.com/promo_codes/purge
Content-Type: application/json
Query Parameters
Parameter | Required | Description |
---|---|---|
shop_id | true | Your API key |
shop_secret | true | Your API secret key |
id | true | Promo codes list ID |
Errors
When promo codes list is not found, method returns 404 error.
Fetch promo code
curl https://api.personaclick.com/promo_codes/fetch?did=DEVICE_ID&shop_id=SHOPID&id=PROMOCODE_LIST_ID
personaclick("get_promo_code", {id: PROMOCODE_LIST_ID}, success_callback, error_callback);
The above command returns JSON structured like this:
{"code": "UNIQUE_CODE"}
Method provides service for unique promo codes fetching.
Note: unique promo codes are limited. Store fetched promo code during user's session.
HTTP Request
GET https://api.personaclick.com/promo_codes/fetch
Query Parameters
Parameter | Required | Description |
---|---|---|
did | true | Device ID. You get it from init method in SDK. |
shop_id | true | Your API key |
id | true | Promo codes list ID |
sid | false | Temporary user session ID |
Errors
When promo codes list is empty, method returns 404 error.
Bonuses
Service provides endpoints for bonuses management.
Import bonuses status
Headers
Method: POST
Content-type: application/json
Body example
{
"shop_id":"...",
"shop_secret":"...",
"bonuses": [
{
"email": "...",
"phone": "...",
"loyalty_id": "...",
"current_status": "...",
"total_balance": ...,
"total_used": ...,
"total_burned": ...,
"total_cancelled": ...,
"total_inactive": ...,
"total_rewarded": ...,
"event": "...",
"order_id": "...",
"bonus_status": "...",
"amount_changed": "...",
"activated_at": "...",
"expiration": "...",
"activity": "...",
"balance": ...
}, ...
]
}
Request example
curl --header "Content-Type: application/json" \
--request POST \
--data-binary "@data.json" \
https://api.personaclick.com/import/bonuses
Method uploads current bonuses status.
HTTP Request
POST https://api.personaclick.com/import/bonuses
Content-Type: application/json
Query Parameters
Parameter | Required | Description |
---|---|---|
shop_id | true | Your API key |
shop_secret | true | Your API secret key |
email* | true | Promo codes list ID |
phone* | true | List of promo codes |
loyalty_id* | true | List of promo codes |
Properties
Parameter | Type | Description |
---|---|---|
current_status | String | Current status |
total_balance | Float | Total balance |
total_used | Float | Total used |
total_burned | Float | Total burned out |
total_cancelled | Float | Total cancelled |
total_inactive | Float | Total inactive |
total_rewarded | Float | Total rewarded |
purchase_date | Date | Date in format YYYY-MM-DD HH:MM:SS |
event | String | Status change event |
order_id | String | Order ID |
bonus_status | String | Status of bonuses |
amount_changed | String | Amount of bonus changes |
activated_at | Date | Date in format YYYY-MM-DD HH:MM:SS |
expiration | Date | Date in format YYYY-MM-DD HH:MM:SS |
activity | String | The action that changed the balance |
balance | Float | Current bonuses balance |
Errors
Loyalty program
Service provides endpoints for loyalty program management.
Join loyalty program
Headers
Content-type: application/json
Body example
{
"shop_id": "...",
"shop_secret": "...",
"phone": "...",
"email": "...",
"first_name": "...",
"last_name": "...",
"gender": "...",
"birthday": "..."
}
Request example
curl --header "Content-Type: application/json" \
--request POST \
--data-binary "@data.json" \
https://api.personaclick.com/loyalty/members/join
// S2S only
// S2S only
// S2S only
// S2S only
// S2S only
The above command returns JSON structured like this:
{
"success": true,
"data": {
"message": "Member is registered successfully",
"identifier": "..."
}
}
HTTP Request
POST https://api.personaclick.com/loyalty/members/join
Method to register a user as a member of loyalty program. Server-to-server integration method only.
Query Parameters
Parameter | Required | Description |
---|---|---|
shop_id | true | Your API key |
shop_secret | true | Your API secret key |
email* | true | User's email |
phone* | true | User's phone number |
first_name | optional | Customer's first name |
last_name | optional | Customer's last name |
gender | optional | Customer's gender: m or f |
birthday | optional | Customer's birthday (format: YYYY-MM-DD |
Get balance
Request example
curl 'https://api.personaclick.com/loyalty/basic/balance?shop_id=SHOP_ID&shop_secret=SHOP_SECRET&phone=PHONE&order_total=ORDER_TOTAL'
The above command returns JSON structured like this:
{
"confirmed": 123,
"pending": 456,
"expiring": 789,
"expire_in": "2022-12-12 23:59:59 UTC",
"available_in_order": 100, // How many bonuses can be spent in this purchase
"payable_amount": 50 // How much it will in currency if exchange rate is not 1:1
}
Method return current bonuses balance.
HTTP Request
GET https://api.personaclick.com/loyalty/basic/balance
Query Parameters
Parameter | Required | Description |
---|---|---|
shop_id | true | Your API key |
shop_secret | true | Your API secret key |
email* | true | User's email |
phone* | true | User's phone number |
expire_in | optional | Bonuses expiration date (DD-MM-YYYY) |
order_total | optional | Order total |
API response
Name | Type | Description |
---|---|---|
confirmed | Int | Available bonuses |
pending | Int | Pending bonuses |
expiring | Int | Bonuses that will be expired |
expire_in | Datetime | Expiring period |
available_in_order | Int | Available bonuses for use in the order |
Get SMS code
Request example
curl 'https://api.personaclick.com/loyalty/basic/init_bonus_usage?shop_id=SHOP_ID&shop_secret=SHOP_SECRET&phone=PHONE&bonus_points=BONUS_POINTS'
The above command returns JSON structured like this:
{
"status": "success",
"sms_code": 123456
}
Method return SMS code.
HTTP Request
GET https://api.personaclick.com/loyalty/basic/init_bonus_usage
Query Parameters
Parameter | Required | Description |
---|---|---|
shop_id | true | Your API key |
shop_secret | true | Your API secret key |
email* | true | User's email |
phone* | true | User's phone number |
bonus_points | true | Bonuses, which client wants to validate |
API response
Name | Type | Description |
---|---|---|
sms_code | Int | SMS code |
Validate SMS code
Request example
curl --location --request POST 'https://api.personaclick.com/loyalty/basic/use_bonus_points?phone=PHONE&shop_id=SHOP_ID&shop_secret=SHOP_SECRET&bonus_points=BONUS_POINTS&confirm_code=true&sms_code=SMS_CODE'
The above command returns JSON structured like this:
{
"confirmation": "success",
"confirmed": 123456
}
Method validate SMS code.
HTTP Request
POST https://api.personaclick.com/loyalty/basic/use_bonus_points
Query Parameters
Parameter | Required | Description |
---|---|---|
shop_id | true | Your API key |
shop_secret | true | Your API secret key |
email* | true | User's email |
phone* | true | User's phone number |
bonus_points | true | Bonuses, which client wants to validate |
confirm_code | true | Param for validate |
sms_code | true | SMS code |
API response
Name | Type | Description |
---|---|---|
confirmation | String | Response message |
confirmed | int | Validated bonuses |
Decrease bonuses
Request example
curl --location --request POST 'https://api.personaclick.com/loyalty/basic/use_bonus_points_confirmed?phone=PHONE&shop_id=SHOP_ID&shop_secret=SHOP_SECRET&bonus_points=BONUS_POINTS&sms_code=SMS_CODE'
The above command returns JSON structured like this:
{
"confirmation": "success",
"confirmed": 123456
}
Method decrease bonuses.
HTTP Request
POST https://api.personaclick.com/loyalty/basic/use_bonus_points_confirmed
Query Parameters
Parameter | Required | Description |
---|---|---|
shop_id | true | Your API key |
shop_secret | true | Your API secret key |
email* | true | User's email |
phone* | true | User's phone number |
bonus_points | true | Bonuses, which client wants to validate |
sms_code | true | SMS code |
API response
Name | Type | Description |
---|---|---|
status | String | Response status |
confirmed | int | Validated bonuses |
Decrease bonuses without SMS code
Request example
curl --location --request POST 'https://api.personaclick.com/loyalty/basic/use_bonus_points?phone=PHONE&shop_id=SHOP_ID&shop_secret=SHOP_SECRET&bonus_points=BONUS_POINTS'
The above command returns JSON structured like this:
{
"confirmation": "success",
"confirmed": 123456
}
Method decrease bonuses without SMS code.
HTTP Request
POST https://api.personaclick.com/loyalty/basic/use_bonus_points
Query Parameters
Parameter | Required | Description |
---|---|---|
shop_id | true | Your API key |
shop_secret | true | Your API secret key |
email* | true | User's email |
phone* | true | User's phone number |
bonus_points | true | Bonuses, which client wants to validate |
API response
Name | Type | Description |
---|---|---|
status | String | Response status |
confirmed | int | Validated bonuses |
Increase bonuses
Request example
curl --location --request POST 'https://api.personaclick.com/loyalty/basic/event_bonus?phone=PHONE&shop_id=SHOP_ID&shop_secret=SHOP_SECRET&event=EVENT&amount=AMOUNT'
The above command returns JSON structured like this:
{
"status": "success"
}
Method increase bonuses. This method is used to increase user bonuses that aren't related to an order. It can be any action, for example, registration on the site. Bonuses added by this method have activated status and can be used immediately
HTTP Request
POST https://api.personaclick.com/loyalty/basic/event_bonus
Query Parameters
Parameter | Required | Description |
---|---|---|
shop_id | true | Your API key |
shop_secret | true | Your API secret key |
email* | true | User's email |
phone* | true | User's phone number |
event | true | A unique event code that's used once for a user to award bonuses for an action. For example, "registration". |
amount | true | Bonuses amount |
API response
Name | Type | Description |
---|---|---|
status | String | Response status |
Net Promoter Score
Endpoints is used to work with NPS service.
Glossary:
- Process category: separate process you which quality you want to measure. Examples:
Delivery of online purchase
,Delivery of offline purchase
,Online checkout quality
,Customer service
, etc. - Channel: channel where review was received from. Examples:
website
,ios_application
,pos
,callcenter
,android_application
.
NPS categories
This endpoints returns a list of active categories. Categories list can be customized on NPS settings page in backoffice.
Note: if you provide any of user identifiers (see query params table), questions and "thank you" messages can be personalized.
curl https://api.personaclick.com/nps/categories?shop_id=SHOPID
personaclick('nps', 'categories', success, failure);
// Not described yet
// Not described yet
// Not described yet
The above command returns JSON structured like this:
[
{
"id": 1,
"code": "website",
"name": "Online checkout quality",
"promoter_question": "Which features do you value/use the most?",
"passive_question": "How can we improve your experience?",
"detractor_question": "What was missing or disappointing in your experience with us?",
"promoter_success": "Thanks for your feedback, Mr. John Smith. It’s great to hear that you’re a fan of our product. Your feedback helps us discover new opportunities to improve and make sure you have the best possible experience.",
"passive_success": "Thanks for your feedback. Our goal is to create the best possible product, and your thoughts, ideas, and suggestions play a major role in helping us identify opportunities to improve.",
"detractor_success": "Thanks for your feedback. We highly value all ideas and suggestions from our customers, whether they’re positive or critical. In the future, our team might reach out to you to learn more about how we can further improve our services so that it exceeds your expectations."
},
{
"id": 3,
"code": "delivery",
"name": "Delivery quality survey",
"promoter_question": "Which features do you value/use the most?",
"passive_question": "How can we improve your experience?",
"detractor_question": "What was missing or disappointing in your experience with us?",
"promoter_success": "Thanks for your feedback, Mr. John Smith. It’s great to hear that you’re a fan of our product. Your feedback helps us discover new opportunities to improve and make sure you have the best possible experience.",
"passive_success": "Thanks for your feedback. Our goal is to create the best possible product, and your thoughts, ideas, and suggestions play a major role in helping us identify opportunities to improve.",
"detractor_success": "Thanks for your feedback. We highly value all ideas and suggestions from our customers, whether they’re positive or critical. In the future, our team might reach out to you to learn more about how we can further improve our services so that it exceeds your expectations."
}
]
HTTP Request
GET https://api.personaclick.com/nps/categories
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key. JS SDK handles it automatically. |
NPS channels
Get list of available channels, from which NPS review can be created. Channels list can be customized on NPS settings page in backoffice.
curl https://api.personaclick.com/nps/channels?shop_id=SHOPID
personaclick('nps', 'channels', success, failure);
// Not described yet
// Not described yet
// Not described yet
The above command returns JSON structured like this:
[
{
"id": 1,
"code": "website",
"name": "Online checkout quality"
},
{
"id": 2,
"code": "ios_app",
"name": "iOS mobile app"
},
{
"id": 3,
"code": "ios_app",
"name": "iOS mobile app"
},
{
"id": 4,
"code": "pos",
"name": "POS terminal"
}
]
HTTP Request
GET https://api.personaclick.com/nps/channels
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key. JS SDK handles it automatically. |
NPS reviews
Get list of published NPS reviews. Limited to 1000 reviews per request.
curl https://api.personaclick.com/nps/reviews?shop_id=SHOPID&shop_secret=SECRET
// Not needed. See cURL.
// Not needed. See cURL.
// Not needed. See cURL.
// Not needed. See cURL.
The above command returns JSON structured like this:
[
{
"id": 1,
"channel": "email",
"category": "delivery",
"rate": 7,
"comment": "Lorem ipsum",
"client_id": 1515915625535836508,
"email": "[email protected]",
"phone": "79876543210",
"created_at": "2023-07-21T02:35:06.374Z"
},
{
"id": 2,
"channel": "popup",
"category": "checkout",
"rate": 9,
"comment": null,
"client_id": 1515915625535836508,
"email": "[email protected]",
"phone": "79876543210",
"created_at": "2023-07-21T02:35:06.374Z"
}
]
HTTP Request
GET https://api.personaclick.com/nps/reviews
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key. |
shop_secret | String | true | Your API secret key. |
date_from | String | false | Filter by date: start date. |
date_to | String | false | Filter by date: end date. |
channel | String | false | Channel code. |
category | String | false | Category code. |
Save review
// Not allowed
// Full form
personaclick("nps", "review", {
channel: "channel_code",
category: "category_code",
rate: 7,
comment: "Some comment"
}, success, failure);
// Without comment
personaclick("nps", "review", {
channel: "channel_code",
category: "category_code",
rate: 10
}, success, failure);
// Basic usage
sdk.review(rate: 3, channel: "ios_app", category: "checkout") { _ in
print("Review is posted")
}
// Rate order
sdk.review(rate: 6, channel: "ios_app", category: "checkout", order_id: "ORDER-3341") { _ in
print("Review is posted")
}
// With comment
sdk.review(rate: 9, channel: "ios_app", category: "checkout", comment: "Nice application, thank you!") { _ in
print("Review is posted")
}
// With comment and order_id
sdk.review(rate: 10, channel: "ios_app", category: "checkout", order_id: "ORDER-3341", comment: "Nice application, thank you!") { _ in
print("Review is posted")
}
// Not described yet
// Not described yet
Create an NPS review for the specific survey and user. To identify user you can use one of the listed identifiers:
- device ID - for web and mobile apps. This ID is used automatically by our SDK.
- email - any channel.
- phone - any channel.
- loyalty ID - any channel, usually POS.
- order ID - any channel, usually POS.
If there is existing review from the same user, channel, category and date, it will be updated instead of creating new one.
HTTP Request
POST https://api.personaclick.com/nps/create
Query Parameters
Response on success:
{
"status": "success"
}
Response on failure:
{
"status": "error",
"payload": {
"message": "error message"
}
}
One of the listed user identifiers is required: did
, email
, phone
, order_id
.
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Your secret API key |
did | String | false | Device ID of the user. SDK handles it automatically. |
sid | true | Temporary user session ID. Required when sending NPS with did identifier. |
|
String | false | User's email | |
phone | String | false | User's phone |
loyalty_id | String | false | User's loyalty ID |
order_id | String | false | Order ID, related to the current survey |
channel | String | true | NPS channel code |
category | String | true | NPS process category code |
rate | Integer | true | Score of the rated process: 1..10 |
comment | String | false | Optional answer to the follow-up question |
SMS messaging
Section describes how to send SMS messages
Transactional SMS
curl -i -X POST -H "Content-Type: application/json" --data-binary "@data.json" https://api.personaclick.com/sms/transactional
# data.json
{
"shop_id": "DvLWN2ZTMZ",
"shop_secret": "EIxTuot8sj",
"code": "...",
"phone": "...",
"variables": {
"url": "https://mydomain.com/page/1",
"variable_1": "value_1",
"variable_2": "value_2",
...
}
}
// REST API only. See cURL.
// REST API only. See cURL.
// REST API only. See cURL.
// REST API only. See cURL.
Requirements
Endpoint: GET https://api.personaclick.com/sms/transactional
Content type: application/json
Data format: JSON body
.
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Your API secret key |
code | String | true | Campaign unique identifier |
phone | String | true | User's phone number |
variables | Object | true | Object of key-pair variables for template parser. See example. |
Multi-messaging
Method of multi-channel notifications, when the platform automatically chooses the cheapest and more efficient way to deliver transactional message to a recipient.
Supported channels:
- web push
- mobile push
- sms
Initial tasks
Before sending campaign you have to setup it:
- Prepare transactional email template
- Prepare transactional web/mobile push template
- Prepare transactional SMS template
- Create multi-channel campaign and select created templates for every channel you want to use in the campaign.
- Done.
In templates you can use variables and operators to customize final content. Template engine - Liquid.
Sending message
curl -i -X POST -H "Content-Type: application/json" --data-binary "@data.json" https://api.personaclick.com/transact
# data.json
{
"shop_id": "DvLWN2ZTMZ",
"shop_secret": "EIxTuot8sj",
"email": "...",
"phone": "...",
"code": "...",
"variables": {
"first_name": "John",
"last_name": "Connor",
"promocode": "IDDQD",
"variable_1": "value_1",
"variable_2": "value_2",
...
}
}
// REST API only. See cURL.
// REST API only. See cURL.
// REST API only. See cURL.
When sending a message, you must to send:
- API credentials
- One or several user identifiers: email, phone, loyalty_id (more is better)
- Multi-channel campaign ID
- Variables object
Requirements
Endpoint: GET https://api.personaclick.com/transact
Content type: application/json
Data format: JSON body
.
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Your API secret key |
email* | String | true | User's email |
phone* | String | true | User's phone number |
code | String | true | Multi-channel campaign unique code |
send_everywhere | Boolean | false | Send to all channels, except SMS. Default false |
variables | Object | true | Object of key-pair variables for template parser. See example |
- One of identifiers must present in request: email or phone. It's used to identify user.
URL shortener
This service provides functionality to make shortened URLs and generate QR codes for an URL.
Create short URL
Headers
Content-type: application/json
Body example
{
"shop_id": "...",
"shop_secret": "...",
"links": [
{
"url": "https://example.com/page/1/?utm_source=source...",
},
{
"url": "https://example.com/page/2/?utm_source=source...",
"lifetime": 60
},
{
"url": "https://example.com/page/3/?utm_source=source...",
"code": "a",
"lifetime": 10
}
]
}
Request example
curl --header "Content-Type: application/json" \
--request POST \
--data '{"shop_id":"...","shop_secret":"...","links":[{"url":"https://example.com/page/1"},{"url":"https://example.com/page/1","code":"a"}]}' \
https://api.personaclick.com/url/create
Response example:
[
{
"source": "https://example.com/page/1",
"url": "https://personaclick.dev/x27FyAlR"
},
{
"source": "https://example.com/page/2",
"url": "https://personaclick.dev/a"
}
]
The endpoint allows to create 1 to N shortened URLs. Use batch request to shorten hundreds of URLs at once.
HTTP Request
Method | Endpoint | Content-type |
---|---|---|
POST | https://api.personaclick.com/url/create | application/json |
Query Parameters
This is JSON request. All data must be send as JSON body. Do not forget to set Content-type: application/json
.
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Your secret API key |
links | Array | true | List of URLs to shorten. At least 1 element must present. |
url | String | true | Source URL to shorted. Must be present in each element if list array. |
lifetime | Integer | false | Number of days shortened link to be alive. Link will be deleted after this number of days. Min value: 1 . Max value: 90 . Default value: 30 . Try not to use large numbers, because number of unique shortened URLs is limited. |
code | String | false | Use code property to manually create links with specified URL. Keep in mind: every time you set code manually, it overrides previous link with the same code. |
domain | String | false | Custom domain name for URL shortener. Must be whitelisted with support team before usage. |
Products and catalog
Service is used to manage products and categories.
Request product list
# Basic
curl https://api.personaclick.com/products?shop_id=...&did=...&sid=...
# Filter by brands
curl https://api.personaclick.com/products?shop_id=...&did=...&sid=...&brands=BRAND_1,BRAND_2
# Filter by categories
curl https://api.personaclick.com/products?shop_id=...&did=...&sid=...&categories=CATEGORY_1,CATEGORY_2
# Filter by locations
curl https://api.personaclick.com/products?shop_id=...&did=...&sid=...&locations=LOCATION_1,LOCATION_2
# Filter by merchants
curl https://api.personaclick.com/products?shop_id=...&did=...&sid=...&merchants=MERCHANT_1,MERCHANT_2
# Filter by params
curl https://api.personaclick.com/products?shop_id=...&did=...&sid=...&filters={"PARAM_NAME_1": ["PARAM_VALUE_1", "PARAM_VALUE_2"], "PARAM_NAME_2": ["PARAM_VALUE_1", "PARAM_VALUE_2"]}
# Filter by true|false params. Send boolean params as string
curl https://api.personaclick.com/products?shop_id=...&did=...&sid=...&filters={"PARAM_NAME_1": ["true"], "PARAM_NAME_2": ["false"]}
// No implementation. See CURL
sdk.getProductsList(
brands: String?,
merchants: String?,
categories: String?,
locations: String?,
limit: Int?,
page: Int?,
filters: [String : Any]?
) {
Result<ProductsListResponse,
SDKError> in //productsListResponse in // Result response
}
// No implementation. See CURL
// No implementation. See CURL
HTTP Request
GET https://api.personaclick.com/products
If the request lacks a category, request has no parameters, or contains empty parameters, the response won't include any filters
Query Parameters
Parameter | Required | Description |
---|---|---|
did | true | Device ID. You get it from init method in SDK. |
shop_id | true | Your API key |
sid | true | Temporary user session ID |
limit | false | Limit of results |
page | false | Page of results |
locations | false | Comma separated list of locations IDs |
brands | false | Comma separated list of brands to filter |
merchants | false | Comma separated list of merchants to filter |
categories | false | Comma separated list of categories to filter |
filters | false | Optional escaped JSON string with filter parameters. For example: {"bluetooth":["yes"],"offers":["15% cashback"],"weight":["1.6"]} |
filters_search_by | false | Available options for filter: name, quantity, popularity |
API response
Name | Type | Description |
---|---|---|
brands | array | Array with information about brands. Each object has the following properties: |
* name – brand name (string) | ||
* picture – brand picture (string) | ||
filters | array | Array with information about filters. Each object has the following properties: |
* filter – fitler object. Has the following properties: | ||
* count – total count of products whith this parameters (number) | ||
* values – array of values (object). Has the following properties: | ||
* value – value label. (string) | ||
* count – cont of products whith this parameter (number) | ||
price_range | object | Min and max price of products. Has the following properties: |
* min – min price (number) | ||
* max – max price (number) | ||
products | array | Array with information about products. Each object has the following properties: |
* brand – product brand (string) | ||
* currency – product currency (string, corresponds to the currency of the personal account in PersonaClick, or a custom value specified in the shop settings in the personal account) | ||
* id – product ID (string) | ||
* is_new – product property (boolean, default - null) | ||
* name – product name (string) | ||
* old_price – product old price (string, default - 0) | ||
* picture – product's picture URL in the PersonaClick storage (string) | ||
* price – product price (number) | ||
* price_formatted – product price with currency (string) | ||
* url – product URL (string) | ||
Additional properties. If a parameter "extended" is passed in the request | ||
* barcode – product barcode (string) | ||
* categories – product categories (array). Has the following properties: | ||
* id – category id (string) | ||
* name – category name (string) | ||
* parent – parent category id (string) | ||
* params – array with information about params. Each object has the following properties: | ||
* key – param name (string) | ||
* values – array of values (array) | ||
products_total | number | Total count of products |
Get product info
curl https://api.personaclick.com/products/get?shop_id=...&item_id=...
// No implementation. See CURL
// No implementation. See CURL
// No implementation. See CURL
// No implementation. See CURL
REST method returns this JSON structure
{
"name": "...",
"description": "...",
"price": "...",
"currency": "...",
"url": "...",
"picture": "..."
}
Returns basic product info.
GET https://api.personaclick.com/products/get
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
item_id | String | true | Product ID |
Response details
Parameter | Type | Description |
---|---|---|
name | String | Product name |
description | String | Product description |
price | String | Product price |
currency | String | Currency |
url | String | URL |
picture | String | Picture |
Get product stats
curl https://api.personaclick.com/products/counters?shop_id=...&item=...
personaclick('products', 'counters', ITEM, success, error)
// No implementation. See CURL
// No implementation. See CURL
// No implementation. See CURL
REST method returns this JSON structure
{
"daily": {
"view": 123,
"cart": 456,
"purchase": 789
},
"now": {
"view": 123,
"cart": 456,
"purchase": 789
}
}
Returns basic product info.
GET https://api.personaclick.com/products/counters
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
item | String | true | Product ID |
Response details
Parameter | Type | Description |
---|---|---|
daily | Object | Returns "view", "cart", "purchase" for 24 hours |
now | Object | Returns "view", "cart", "purchase" for 15 minutes |
Get subscriptions for products in stock
curl https://api.personaclick.com/products/subscribers/stock?shop_id=...&shop_secret=...
// No implementation. See CURL
// No implementation. See CURL
// No implementation. See CURL
// No implementation. See CURL
REST method returns this JSON structure
[
{
"id": "ID1",
"barcode": "BC101",
"quantity": 337,
"date": "2020-01-12",
"contacts": [
"[email protected]",
"[email protected]"
]
},
{
"id": "ID2",
"barcode": "BC102",
"quantity": 13,
"date": "2020-08-11",
"contacts": [
"[email protected]",
"[email protected]"
]
}
]
Returns list of products and a number of subscribers for each product in stock.
GET https://api.personaclick.com/products/subscribers/stock
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Shop secret key |
Response details
Parameter | Type | Description |
---|---|---|
id | String | Product ID |
barcode | String | Product barcode |
quantity | Integer | Number of products that have subscribers |
date | String | Date of the last subscription |
contacts | String | Array with contact details |
Get subscriptions for products price drop
curl https://api.personaclick.com/products/subscribers/price?shop_id=...&shop_secret=...
// No implementation. See CURL
// No implementation. See CURL
// No implementation. See CURL
// No implementation. See CURL
REST method returns this JSON structure
[
{
"id": "ID1",
"barcode": "BC101",
"quantity": 337,
"date": "2020-01-12",
"contacts": [
"[email protected]",
"[email protected]"
]
},
{
"id": "ID2",
"barcode": "BC102",
"quantity": 13,
"date": "2020-08-11",
"contacts": [
"[email protected]",
"[email protected]"
]
}
]
Returns list of products and a number of subscribers for each product's price drop.
GET https://api.personaclick.com/products/subscribers/price
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Shop secret key |
Response details
Parameter | Type | Description |
---|---|---|
id | String | Product ID |
barcode | String | Product barcode |
quantity | Integer | Number of products that have subscribers |
date | String | Date of the last subscription |
contacts | String | Array with contact details |
Get status of subscription for "Back in Stock" trigger
// No implementation. See JavaScript
personaclick("check_trigger", "product_price_decrease", params, success, error);
sdk.subscribeForBackInStock(
id: "PRODUCT_ID",
email: "USER_EMAIL",
phone: "USER_PHONE",
fashionSize: "PRODUCT_SIZE",
fashionColor: "PRODUCT_COLOR",
barcode: "PRODUCT_BARCODE"
)
// No implementation. See JavaScript
// No implementation. See JavaScript
API method returns this boolean status
Returns boolean status of subscription.
GET https://api.personaclick.com/products/check_product_available_subscription
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
item_id | string/number | true | Product ID |
shop_secret | string | true | Shop secret |
shop_id | string | true | Shop ID |
did* | string | false | Device ID |
external_id* | string | false | External ID |
email* | string | false | Email for subscription checking |
phone* | string | false | Phone for subscription checking |
loyalty_id* | string | false | Loyalty ID for subscription checking |
telegram_id* | string | false | Telegram ID for subscription checking |
Get status of subscription for product price drop
// No implementation. See JavaScript
personaclick("check_trigger", "product_available", params, success, error);
// No implementation. See JavaScript
// No implementation. See JavaScript
// No implementation. See JavaScript
API method returns this boolean status
Returns boolean status of subscription.
GET https://api.personaclick.com/products/check_price_drop_subscription
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
item_id | string/number | true | Product ID |
shop_secret | string | true | Shop secret |
shop_id | string | true | Shop ID |
did* | string | false | Device ID |
external_id* | string | false | External ID |
email* | string | false | Email for subscription checking |
phone* | string | false | Phone for subscription checking |
loyalty_id* | string | false | Loyalty ID for subscription checking |
telegram_id* | string | false | Telegram ID for subscription checking |
List not widgetable products
curl https://api.personaclick.com/products/not_widgetable?shop_id=...&shop_secret=...
// No implementation. See shell
// No implementation. See shell
// No implementation. See shell
// No implementation. See shell
API method returns a list like this:
{
status: 'success',
data: {
total: number of widgetable products,
items: [
{
uniqid: String,
price: Float | Null,
name: String,
url: String,
image_url: String,
image_downloading_error: String (image loading error description),
},
]
}
}
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Shop secret key |
Returns a list of avaiable
and not ignored
products which are not widgetable
: can't be displayed in search, recommendations and messages due to missing one of mandatory parameters (name
, price
, url
or image_url
) or failed to fetch product's photo during import operation.
GET https://api.personaclick.com/products/not_widgetable
Get client's shopping cart
Shopping cart can be fetched with did
(device ID) parameter only.
# By did
curl 'https://api.personaclick.com/products/cart?did=DEVICE_ID&shop_id=SHOP_ID'
function success ({ data }) {
console.log(data.items.length);
});
function failure (error) {
console.error(error);
})
window.personaclick('cart', 'get', success, failure);
// Not implemented yet.
// Not implemented yet.
sdk.getProductsFromCart { result in
switch result {
case .success(let items):
print("cart items: \n \(items)")
case .failure(let error):
print("error: \(error)")
}
}
cart() {
return new Promise((resolve, reject) => {
this.push((() => {
try {
request('products/cart', {
params: {
shop_id: this.shop_id,
},
}).then( res => {
resolve(res)
});
} catch (error) {
reject(error)
}
}));
})
}
HTTP Request
GET https://api.personaclick.com/products/cart
Query Parameters
Parameter | Required | Description |
---|---|---|
shop_id | true | Your API key |
did | true | Device ID |
API response
Returns {"status": "success", "data": { "items": [ {"uniqid": "SKU_1", "quantity": 1}, {"uniqid": "SKU_2", "quantity": 3} ] }}
JSON object.
Clear client's shopping cart
# By phone number
curl --location --request DELETE 'https://api.personaclick.com/products/cart/clear?phone=PHONE&shop_id=SHOP_ID&shop_secret=SHOP_SECRET'
# By phone email
curl --location --request DELETE 'https://api.personaclick.com/products/cart/clear?email=EMAIL&shop_id=SHOP_ID&shop_secret=SHOP_SECRET'
# By loyalty_id
curl --location --request DELETE 'https://api.personaclick.com/products/cart/clear?loyalty_id=LOYALTY_ID&shop_id=SHOP_ID&shop_secret=SHOP_SECRET'
# By external_id
curl --location --request DELETE 'https://api.personaclick.com/products/cart/clear?external_id=EXTERNAL_ID&shop_id=SHOP_ID&shop_secret=SHOP_SECRET'
# By telegram_id
curl --location --request DELETE 'https://api.personaclick.com/products/cart/clear?telegram_id=TELEGRAM_ID&shop_id=SHOP_ID&shop_secret=SHOP_SECRET'
// No implementation. See CURL
// No implementation. See CURL
// No implementation. See CURL
HTTP Request
DELETE https://api.personaclick.com/products/cart/clear
Query Parameters
Parameter | Required | Description |
---|---|---|
shop_id | true | Your API key |
shop_secret | true | Your API secret key |
email* | false | User's email |
phone* | false | User's phone number |
loyalty_id* | false | User's loyalty_id |
external_id* | false | User's external_id |
telegram_id* | false | User's telegram_id |
API response
Returns {"status": "success"}
JSON object.
Categories
Service provides access to categories endpoint.
Request categories
curl https://api.personaclick.com/products/categories
HTTP Request
GET https://api.personaclick.com/products/categories
Query Parameters
Parameter | Required | Description |
---|---|---|
shop_id | true | Your API key |
shop_secret | true | Your Secret key |
depth | false | (0 - root categories, 1 - root and first level of childs, etc.) |
exclude | false | An array of categories to exclude from the response |
only_discount | false | Boolean. Only categories with discount products. |
locations | false | String. Comma separated list of locations IDs |
Response example
[
{
"id": 19,
"external_id": "482",
"name": "Jewelry",
"url": "https://demo.site.com/categories/jewelry",
"parent_id": null,
"parent_external_id": null,
"children": [
{
"id": 31,
"external_id": "483",
"name": "Rings",
"url": "https://demo.site.com/categories/rings",
"parent_id": 19,
"parent_external_id": "482",
"children": []
}
]
},
{
"id": 4,
"external_id": "479",
"name": "Baby & Kids",
"url": "https://demo.site.com/categories/baby",
"parent_id": null,
"parent_external_id": null,
"children": [
{
"id": 9,
"external_id": "480",
"name": "Clothing Sets",
"url": "https://demo.site.com/categories/baby-kids-clothing-sets",
"parent_id": 4,
"parent_external_id": "479",
"children": []
}
]
}
]
Categories cashing
The following request parameters are cached: shop_id
, categories
, locations
, brands
, merchants
, filters_search_by
, category_limit
, available
, price_min
, price_max
, sort_by
, sort_dir
, limit
, page
, offset
.
Cache duration is 60 seconds.
If JSON filters are included in the request, it will not be cached.
Dynamic filter guide for category
Request
curl https://api.personaclick.com/category/{%category_id%}
HTTP Request
GET https://api.personaclick.com/category/{%category_id%}
Query Parameters
Parameter | Required | Description |
---|---|---|
did | true | Device ID. You get it from init method in SDK. |
shop_id | true | Your API key |
sid | true | Temporary user session ID |
limit | false | Limit of results |
page | false | Page of results |
locations | false | Comma separated list of locations IDs |
brands | false | Comma separated list of brands to filter |
filters | false | Optional escaped JSON string with filter parameters. For example: {"bluetooth":["yes"],"offers":["15% cashback"],"weight":["1.6"]} |
API response
Name | Type | Description |
---|---|---|
brands | array | Array with information about brands. Each object has the following properties: |
* name – brand name (string) | ||
* picture – brand picture (string) | ||
filters | array | Array with information about filters. Each object has the following properties: |
* filter – fitler object. Has the following properties: | ||
* count – total count of products whith this parameters (number) | ||
* values – array of values (object). Has the following properties: | ||
* value – value label. (string) | ||
* count – cont of products whith this parameter (number) | ||
price_range | object | Min and max price of products. Has the following properties: |
* min – min price (number) | ||
* max – max price (number) | ||
products | array | Array with information about products. Each object has the following properties: |
* brand – product brand (string) | ||
* currency – product currency (string, corresponds to the currency of the personal account in PersonaClick, or a custom value specified in the shop settings in the personal account) | ||
* id – product ID (string) | ||
* is_new – product property (boolean, default - null) | ||
* name – product name (string) | ||
* old_price – product old price (string, default - 0) | ||
* picture – product's picture URL in the PersonaClick storage (string) | ||
* price – product price (number) | ||
* price_formatted – product price with currency (string) | ||
* url – product URL (string) | ||
Additional properties. If a parameter "extended" is passed in the request | ||
* barcode – product barcode (string) | ||
* categories – product categories (array). Has the following properties: | ||
* id – category id (string) | ||
* name – category name (string) | ||
* parent – parent category id (string) | ||
* params – array with information about params. Each object has the following properties: | ||
* key – param name (string) | ||
* values – array of values (array) | ||
products_total | number | Total count of products |
Notifications center
Section describes the notifications center endpoints.
Return all messages sent to a user
curl https://api.personaclick.com/notifications?shop_id=...&shop_secret=...&email=...&date_from=YYYY-MM-DD&type=trigger&channel=mobile_push
curl https://api.personaclick.com/notifications?shop_id=...&shop_secret=...&phone=...&date_from=YYYY-MM-DD&type=trigger,transactional&channel=mobile_push,sms
curl https://api.personaclick.com/notifications?shop_id=...&shop_secret=...&loyalty_id=...&date_from=YYYY-MM-DD&type=bulk,trigger,transactional&channel=mobile_push
curl https://api.personaclick.com/notifications?shop_id=...&shop_secret=...&external_id=...&date_from=YYYY-MM-DD&type=bulk,trigger,transactional&channel=mobile_push,email,web_push
Response format:
{
"status": "success",
"payload": {
"messages": [
{
"type": "trigger",
"campaign_id": ...,
"code": "...",
"date": "2023-07-06",
"sent_at": "2023-07-06T14:25:21.000Z",
"subject": "...",
"body": "...",
"url": "...",
"icon": "...",
"picture": "...",
"statistics": {
"opened": true,
"clicked": false,
"hard_bounced": false,
"soft_bounced": false,
"complained": false,
"unsubscribed": false,
"purchased": false
}
}, ...
]
}
}
// REST API only. See cURL.
sdk.getAllNotifications(
type: String,
phone: String?,
email: String?,
userExternalId: String?,
userLoyaltyId: String?,
channel: String?,
limit: Int?,
page: Int?,
dateFrom: String?
) {
Result<UserPayloadResponse, SDKError> in // Result response
}
// REST API only. See cURL.
// REST API only. See cURL.
// REST API only. See cURL.
Requirements
Endpoint: GET https://api.personaclick.com/notifications
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Your API secret key |
phone* | String | true | User's phone number |
email* | String | true | User's email |
loyalty_id* | String | true | User's loyalty ID |
external_id* | String | true | User's external ID |
date_from | String | true | Date in YYYY-MM-DD format. Selects all messages from this date to the current day. Choose date not older than 2 weeks ago, otherwise it will slowdown everything drammatically. |
type | String | true | Comma-separated list of message types: bulk, trigger, transactional, chain. Types chain and trigger considered as identical. Choose wisely: every type slows down performance of the method. Use only required types of messages. |
channel | String | true | Comma-separated list of message channels: email, sms, web_push, mobile_push, telegram, WhatsApp. Choose wisely: every channel slows down performance of the method. Use only required channels. |
page | Integer | false | Page for pagination. Default: 1. Min: 1. |
limit | Integer | false | Limit of recordings per page. Default: 20. Min: 1. Max: 50. |
Message status notification
curl https://api.personaclick.com/notifications/:code
Response format:
{"200"}
// REST API only. See cURL.
// REST API only. See cURL.
// REST API only. See cURL.
// REST API only. See cURL.
// REST API only. See cURL.
Endpoint: GET https://api.personaclick.com/notifications/:code
The 'code' part is contained in the response from GET https://api.personaclick.com/transact
.
Chats
Section describes how to save external chats' logs.
Save chat log
curl -i -X POST -H "Content-Type: application/json" --data-binary "@data.json" https://api.personaclick.com/chat_reports
# data.json for email
{
"shop_id": "DvLWN2ZTMZ",
"shop_secret": "EIxTuot8sj",
"platform": "...",
"code": "...",
"email": "...",
"data": {...}
}
# data.json for phone
{
"shop_id": "DvLWN2ZTMZ",
"shop_secret": "EIxTuot8sj",
"code": "...",
"platform": "...",
"phone": "...",
"data": {...}
}
// REST API only. See cURL.
// REST API only. See cURL.
// REST API only. See cURL.
// REST API only. See cURL.
Requirements
Endpoint: POST https://api.personaclick.com/chat_reports
Content type: form-data
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Your API secret key |
code | String | true | Conversation unique code |
platform | String | true | Platform code. Supported: livetex |
phone* | String | true | User's phone number |
email* | String | true | User's email |
data | Object | true | Conversation raw data as stringified JSON object |
Communications
Section describes how to save, read or edit external communication's logs.
Save communication log
curl -i -X POST -H "Content-Type: application/json" --data-binary "@data.json" https://api.personaclick.com/crm/client_calls
# data.json for phone
{
"shop_id": "DvLWN2ZTMZ",
"shop_secret": "EIxTuot8sj",
"phone": "...",
"channel": "...",
"event": "...",
"location_id": "...",
"call_type": "...",
"call_theme": "...",
"comment": "...",
"author_type": "...",
"status": "..."
}
# data.json for email
{
"shop_id": "DvLWN2ZTMZ",
"shop_secret": "EIxTuot8sj",
"email": "...",
"channel": "...",
"event": "...",
"location_id": "...",
"call_type": "...",
"call_theme": "...",
"comment": "...",
"author_type": "...",
"status": "..."
}
# data.json for did
{
"shop_id": "DvLWN2ZTMZ",
"shop_secret": "EIxTuot8sj",
"did": "...",
"channel": "...",
"event": "...",
"location_id": "...",
"call_type": "...",
"call_theme": "...",
"comment": "...",
"author_type": "...",
"status": "..."
}
// REST API only. See cURL.
// REST API only. See cURL.
// REST API only. See cURL.
// REST API only. See cURL.
// REST API only. See cURL.
Requirements
Endpoint: POST https://api.personaclick.com/crm/client_calls
Content type: application/json
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Your API secret key |
phone* | String | true | User's phone number |
email* | String | true | User's email |
did* | String | true | User's did |
channel | String | true | Сommunication's channel |
event | String | true | Сommunication's event |
location_id | String | true | Client's location id |
call_type | String | true | Сommunication's type |
call_theme | String | true | Сommunication's theme |
subject_appeal | String | true | Сommunication's subtheme |
comment | String | true | Сommunication's comment |
author_type | String | true | Сommunication's author |
status | String | true | Сommunication's status in external system |
Read communication log
The query returns the last 20 communications as an array with items sorted by time
# Using phone as user identifier
curl https://api.personaclick.com/crm/client_calls?&shop_id=...&shop_secret=...phone=...
# Using email as user identifier
curl https://api.personaclick.com/crm/client_calls?&shop_id=...&shop_secret=...email=...
# Using did as user identifier
curl https://api.personaclick.com/crm/client_calls?&shop_id=...&shop_secret=...did=...
// REST API only. See cURL.
// REST API only. See cURL.
// REST API only. See cURL.
// REST API only. See cURL.
// REST API only. See cURL.
Requirements
Endpoint: GET https://api.personaclick.com/crm/client_calls
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Your API secret key |
phone* | String | true | User's phone number |
email* | String | true | User's email |
did* | String | true | User's did |
Edit communication log
The query returns the last 20 communications as an array with items sorted by time
# Using phone as user identifier
curl https://api.personaclick.com/crm/client_calls/ID?&shop_id=...&shop_secret=...phone=...
# Using email as user identifier
curl https://api.personaclick.com/crm/client_calls/ID?&shop_id=...&shop_secret=...email=...
# Using did as user identifier
curl https://api.personaclick.com/crm/client_calls/ID?&shop_id=...&shop_secret=...did=...
// REST API only. See cURL.
// REST API only. See cURL.
// REST API only. See cURL.
// REST API only. See cURL.
// REST API only. See cURL.
Requirements
Endpoint: PATCH https://api.personaclick.com/crm/client_calls
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
shop_secret | String | true | Your API secret key |
phone* | String | true | User's phone number |
email* | String | true | User's email |
did* | String | true | User's did |
ID | String | true | Communication's id |
channel | String | true | Сommunication's channel |
event | String | true | Сommunication's event |
location_id | String | true | Client's location id |
call_type | String | true | Сommunication's type |
call_theme | String | true | Сommunication's theme |
subject_appeal | String | true | Сommunication's subtheme |
comment | String | true | Сommunication's comment |
author_type | String | true | Сommunication's author |
status | String | true | Сommunication's status in external system |
Reputation
Endpoints are used to work with shop's reputation.
Get reviews
curl -d "shop_id=SHOPID&count=COUNT&offset=OFFSET" https://api.personaclick.com/reputation/shop
// No implementation is needed in JS SDK
// No implementation is needed in iOS SDK
// No implementation is needed in Android SDK
// No implementation is needed in Android SDK
// No implementation is needed in React Native SDK
This method overrides profile's settings.
Query Parameters
Parameter | Type | Required | Description |
---|---|---|---|
shop_id | String | true | Your API key |
count | String | false | Number of reviews |
offset | String | false | Offset of reviews |
Stories
Section describes how to use Stories
Stories initialization
// Manual initialization by inserting this code into the layout
<com.personalization.stories.views.StoriesView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:code="STORY BLOCK CODE" />
val storiesView = findViewById<StoriesView>(R.id.story_view)
sdk.initializeStoriesView(storiesView)
// Programmatic initialization
val storiesView = StoriesView(this, "STORY BLOCK CODE")
findViewById<ViewGroup>(R.id.stories).addView(storiesView)
sdk.initializeStoriesView(storiesView)
// Set item click listener:
val storiesView = findViewById<StoriesView>(R.id.stories_view)
storiesView.itemClickListener = object : OnLinkClickListener {
override fun onClick(url: String): Boolean {
// return true if need to opening using the SDK
return false
}
override fun onClick(product: Product): Boolean {
// return true if need to opening using the SDK
return false
}
}
// Manual initialization by inserting this code into the layout
<com.personalizatio.stories.views.StoriesView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:code="STORY BLOCK CODE" />
StoriesView storiesView = findViewById(R.id.story_view);
Personaсlick.initializeStoriesView(storiesView);
// Programmatic initialization
StoriesView storiesView = new StoriesView(this, "STORY BLOCK CODE");
((ViewGroup) findViewById(R.id.stories)).addView(storiesView);
Personaсlick.initializeStoriesView(storiesView);
Show stories block on request
No implementation. See SDK.
// The 'start_stories' command is used to start story campaign programmatically (e.g. on button click)
// The second argument is the ID of the stories block.
personaclick('start_stories', 'ID of the stories block')
// To display stories using code, you must have a stories view with any code added and initialized.
// Therefore, to display stories, you need to complete two steps.
// Step 1: Adding and initializing a stories view with a code.
// Follow the instructions in the Stories initialization section.
// If you already have an initialized stories view, skip Step 1.
// 2 step: Show stories by code:
sdk.showStories(CODE)
// To display stories using code, you must have a stories view with any code added and initialized.
// Therefore, to display stories, you need to complete two steps.
// Step 1: Adding and initializing a stories view with a code.
// Follow the instructions in the Stories initialization section.
// If you already have an initialized stories view, skip Step 1.
// 2 step: Show stories by code:
Personaсlick.showStories(CODE);
// Stories block is initialized
@IBOutlet private weak var storiesCollectionView: StoriesView!
private func loadStoriesViewBlock() {
if let globalSDK = globalSDK {
// sdk receives an instance of globalSDK with personalization data and methods
// mainVC receives an instance of type UIViewController; it is used for the configure method
// code - string ID to choose a specific block of stories
storiesCollectionView.configure(sdk: globalSDK, mainVC: self, code: "STORIES_CODE")
}
// collectionView(_:didSelectItemAt:) is called when an element has been chosen (e.g., a button is clicked)
public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
showStoriesByUserClick(at: indexPath.row)
// indexPath.row is the index of the chosen element
// showStoriesByUserClick tries to get a story from the stories array, and then renders it
}
After initializing the SDK, you can request a block of stories. To start initialization, follow the instructions in the Stories initialization section.
Font setup
// Register the font family for Stories block first.
sdk.configuration().stories.registerFont(fileName: "Museo900", fileExtension: FontExtension.ttf.rawValue)
// You can customize font family, font size, colour's, icon size or any other view parameters of the Stories block to suit your app design.
// Each parameter is individual and may not be set - in this case default value's of SDK will be used.
sdk.configuration().stories.setStoriesBlock(fontName: "Museo",
fontSize: 15.0,
textColor: "#5ec169",
textColorDarkMode: "#5ec169",
backgroundColor: "#ffffff",
backgroundColorDarkMode: "#000000",
iconSize: 76,
iconBorderWidth: 2.3,
iconMarginX: 18,
iconMarginBottom: 8,
iconNotViewedBorderColor: "#fd7c50",
iconNotViewedBorderColorDarkMode: "#fd7c50",
iconViewedBorderColor: "#fdc2a1",
iconViewedBorderColorDarkMode: "#fdc2a1",
iconViewedTransparency: 1.0,
iconAnimatedLoaderColor: "#5ec169",
iconPlaceholderColor: "#d6d6d6",
iconPlaceholderColorDarkMode: "#d6d6d6",
iconDisplayFormatSquare: false,
labelWidth: 76,
pinColor: "#fd7c50",
pinColorDarkMode: "#fd7c50",
closeIconColor: "#5ec169")
// Set font family and font size for Default button on Story slide.
// Set font color and background color for Default button on Story slide.
sdk.configuration().stories.setSlideDefaultButton(fontName: "Museo",
fontSize: 17.0,
textColor: "#ffffff",
backgroundColor: "#5ec169",
textColorDarkMode: "#000000",
backgroundColorDarkMode: "#ffffff",
cornerRadius: 5)
// Set font family and font size for Products button on Story slide.
// Set font color and background color for Products button on Story slide.
sdk.configuration().stories.setSlideProductsButton(fontName: "Museo",
fontSize: 17.0,
textColor: "#ffffff",
backgroundColor: "#5ec169",
textColorDarkMode: "#000000",
backgroundColorDarkMode: "#ffffff",
cornerRadius: 5)
// Set the font family for the Products Card detailed view.
sdk.configuration().stories.setProductsCard(fontName: "Museo")
// Set the font family, font size, colour's for Banner with Promocode view.
sdk.configuration().stories.setPromocodeCard(productBannerFontName: "Museo",
productTitleFontSize: 16.0,
productTitleTextColor: "#5ec169",
productTitleTextColorDarkMode: "#5ec169",
productBannerOldPriceSectionFontColor: "#5ec169",
productBannerPriceSectionFontColor: "#5ec169",
productBannerPriceSectionBackgroundColor: "#ffffff",
productBannerPromocodeSectionFontColor: "#ff0000",
productBannerPromocodeSectionBackgroundColor: "#5ec169",
productBannerDiscountSectionBackgroundColor: "#5ec169",
productBannerPromocodeCopyToClipboardMessage: "Copied")
// Setup Stories block autoreload settings.
sdk.configuration().stories.storiesSlideReloadManually = false
sdk.configuration().stories.storiesSlideReloadTimeoutInterval = 10
sdk.configuration().stories.storiesSlideReloadIndicatorDisabled = false
sdk.configuration().stories.storiesSlideReloadIndicatorBackgroundColor = "#ffffff"
sdk.configuration().stories.storiesSlideReloadIndicatorSize = 76.0
sdk.configuration().stories.storiesSlideReloadIndicatorBorderLineWidth = 3
sdk.configuration().stories.storiesSlideReloadIndicatorSegmentCount = 9
sdk.configuration().stories.storiesSlideReloadIndicatorAnimationDuration = 1
sdk.configuration().stories.storiesSlideReloadIndicatorRotationDuration = 17
// Setup Stories Alert popup connection settings.
sdk.configuration().stories.storiesSlideReloadPopupMessageError = "Failed to retrieve data. Please check your connection and try again."
sdk.configuration().stories.storiesSlideReloadPopupMessageFontSize = 17.0
sdk.configuration().stories.storiesSlideReloadPopupMessageFontWeight = .medium
sdk.configuration().stories.storiesSlideReloadPopupMessageDisplayTime = 4
sdk.configuration().stories.storiesSlideReloadPopupPositionY = 120 //default constant
// Setup Stories Stories block text label characters wrapping settings.
sdk.configuration().stories.storiesBlockNumberOfLines = 2
sdk.configuration().stories.storiesBlockCharWrapping = false
sdk.configuration().stories.storiesBlockCharCountWrap = 15
// Initialization by adding code into layout
<com.personalization.stories.views.StoriesView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:code="STORY BLOCK CODE" />
val storiesView = findViewById<StoriesView>(R.id.stories_view)
sdk.initializeStoriesView(storiesView)
//Font setup
val stories = findViewById<StoriesView>(R.id.story_view)
stories.settings.apply {
label_font_size = 16
label_font_family = Typeface.SERIF
button_font_family = Typeface.MONOSPACE
products_button_font_family = Typeface.DEFAULT_BOLD
}
StoriesView stories = findViewById(R.id.story_view);
stories.settings.label_font_size = 16;
stories.settings.label_font_family = Typeface.SERIF;
stories.settings.button_font_family = Typeface.MONOSPACE;
stories.settings.products_button_font_family = Typeface.DEFAULT_BOLD;
After initializing the SDK, you can set the desired style configuration for the fonts and buttons of the Stories block.
Before a font can be used, it must be registered with your app. Add the font file to your xCode project. You must specify a file name with .ttf or .otf extension. Сall the following method after SDK initialization for font registration
Stories Text Block
not supported
// TextBlock is initializing form StoriesElement object and clipsToBounds parameter, it's default value is true
// configurable parameters: textColor,cornerRadius,clipsToBounds,backgroundColor,yOffset
init(from textBlockObject: StoriesElement)
// Define font family names
public struct FontConstants {
public static let monospaced = "Menlo"
public static let serif = "Georgia"
public static let sansSerif = "Arial"
}
// Define layout constants for TextBlockView
public static let leftAnchorOffsetConstant: CGFloat = 5
public static let rightAnchorOffsetConstant: CGFloat = -5
public static let topAnchorOffsetConstant: CGFloat = 2
public static let bottomAnchorOffsetConstant: CGFloat = -2
// Define protocol for text configuration
protocol TBTextConfigurable {
var text: NSAttributedString { get }
var textAlignment: NSTextAlignment { get }
}
// Implement TBTextConfigurable protocol
public struct TBTextConfiguration: TBTextConfigurable
// Initialize TBTextConfiguration using StoriesElement
init(from textBlockObject: StoriesElement)
// Initialize TBFontConfiguration using StoriesElement
init(from textBlockObject: StoriesElement)
// Get UIFont based on type, size, bold, and italic properties
private static func getFont(for fontType: FontType, isBold: Bool = false, isItalic: Bool = false, fontSize: CGFloat) -> UIFont
// Define protocol for appearance configuration
protocol TBAppearanceConfigurable {
var textColor: UIColor { get }
var cornerRadius: CGFloat { get }
var clipsToBounds: Bool { get }
var backgroundColor: UIColor { get }
var yOffset: CGFloat { get }
}
// Implement TBAppearanceConfigurable protocol
public struct TBAppearanceConfiguration: TBAppearanceConfigurable
// Initialize TBAppearanceConfiguration using StoriesElement
init(from textBlockObject: StoriesElement, clipsToBounds: Bool = true)
// Initialize StoriesElement with JSON dictionary
public init(json: [String: Any])
// Define properties of StoriesElement
public var link: String?
public var deeplinkIos: String?
let uID: String?
let fontType: FontType?
let fontSize: Double?
let textItalic: Bool?
let textBackgroundColorOpacity: String?
let textBackgroundColor: String?
let textColor: String?
let textInput: String?
let textAlignment: TextAlignment?
let textLineSpacing: Double?
let yOffset: Double?
let type: ElementType
let color: String?
let title, linkIos: String?
let textBold: Bool?
let background: String?
let cornerRadius: Int
let labels: Labels?
let products: [StoriesProduct]?
let product: StoriesPromoCodeElement?
// TextBlock is initializing based on JSON object it received
Available SDK Configuration options
You can use both the font family in the title and its direct name, for example with the "-Regular" suffix. The color must be transmitted in hex format, for example "#FFFFFF”. Any parameter in any method is optional, you can use both together and separately in combination with other parameters.
Displayed price
No implementation needed
No implementation needed
No implementation needed
No implementaion needed
No implementaion needed
No implementaion needed
The following parameters can be present or absent in the database:
Parameter | Presence in the DB | Description |
---|---|---|
price | always | Product's price |
old_price | not always | Product's old price |
price_with_promocode | not always | Product's price with a promo code |
Depending on which parameters are present in the DB, when the slide is requested, the following scenarios are possible:
- If the
old_price
parameter is present in the DB, the crossed-out price displayed on the slide is theold_price
- If the
old_price
parameter is not in the DB, the crossed-out price displayed on the slide is theprice
- If the
price_with_promocode
parameter is present in the DB, the price value displayed on the slide isprice_with_promocode
- If the
price_with_promocode
parameter is not in the DB, the price value displayed on the slide is theprice
Note: Two prices are displayed on the slide: the actual price and the old price, which is visually crossed out.
Utilities
Methods and helpers for finetune tasks.
Get current A/B segment
# No code implementation
//TBD
sdk->getCurrentSegment()
sdk.getSegment()
Personaсlick.getSegment()
// TBD
Returns user's segment for recommender blocks A/B-tests.
Errors
The PersonaClick API uses the following error codes:
Error Code | Meaning |
---|---|
400 | Bad Request -- Your request is invalid. |
401 | Unauthorized -- Your API key is wrong. |
403 | Forbidden -- The method is for internal use only or you don't have secret key to access it. |
404 | Not Found -- The specified object could not be found. |
405 | Method Not Allowed -- You tried to access with an invalid method. |
406 | Not Acceptable -- You requested a format that isn't json. |
429 | Too Many Requests -- You're sending too many requests. |
500 | Internal Server Error -- We had a problem with our server. Try again later. |
503 | Service Unavailable -- We're temporarily offline for maintenance. Please try again later. |