NAV
cURL JavaScript iOS Android Kotlin Android Java React Native

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:

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:+'
}

// 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

// If your application uses Dagger for dependency injection, don't delete Dagger dependencies.
// If you use Dagger, its dependencies and the kapt plugin must remain in your gradle files.
// The structure for such a project should look similar to the example below:

plugins {
    id 'kotlin-kapt'
}

dependencies {
    implementation 'com.rees46:rees46-sdk:+'
    implementation 'com.google.dagger:dagger:DAGGER_VERSION'
    kapt 'com.google.dagger:dagger-compiler:DAGGER_COMPILER_VERSION'
}
// 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
r46('init', 'SHOP_ID', 'STREAM', success, failure, options, isSpa);

// Cookie-less Mode
const options = {
  cookieless: false
};

r46('init', 'SHOP_ID', 'STREAM', success, failure, options);

// Control of device ID
// If you use any external device management system
// your own device ID can be assigned the to client.
const options = {
  did: 'example'
};

r46('init', 'SHOP_ID', 'STREAM', success, failure, options);

// SPA support mode
// The default value of the isSpa parameter is false.
// The client's session ID is checked during the tracking process.
// The check starts only if isSpa parameter is true.
// If the session ID has expired, a new one will be requested from the server.
const isSpa = true;

r46('init', 'SHOP_ID', 'STREAM', success, failure, options, isSpa);

import PersonaClick
var sdk = createPersonalizationSDK(shopId: "SHOP_ID", stream: "ios",  userEmail: "[email protected]", userPhone: "String", userLoyaltyId: "String", apiDomain: "String", enableLogs: Bool, autoSendPushToken: Bool)
private lateinit var sdk: SDK

override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  sdk = SDK()

  sdk.initialize(
    context = applicationContext,
    shopId = SHOP_ID,
    apiUrl = API_URL,
    tag = TAG,
    notificationType = NOTIFICATION_TYPE,
    notificationId = NOTIFICATION_ID,
    autoSendPushToken = ... Optional parameter for initialization with token automatic sending flag
  )
}
private personaclick personaclick;

@Override
public void onCreate() {
  super.onCreate();
    rees46 = personaclick.initialize(getApplicationContext(), SHOP_ID, API_DOMAIN);
}

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:

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:

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 params = Params().apply {
  put(
    Params.Item(YOUR_ITEM_ID).apply {
    set(Params.Item.COLUMN.AMOUNT, YOUR_AMOUNT)
    set(Params.Item.COLUMN.PRICE, YOUR_PRICE)
    }
  )
  put(Params.Parameter.ORDER_ID, YOUR_ORDER_ID)
  put(Params.Parameter.ORDER_PRICE, YOUR_ORDER_PRICE)
  put(Params.Parameter.DELIVERY_ADDRESS, YOUR_DELIVERY_ADDRESS)
  put(Params.RecommendedBy(Params.RecommendedBy.TYPE.RECOMMENDATION, YOUR_RECCOMENDATION_CODE))
 }
sdk.trackEventManager.track(
  event = TrackEvent.PURCHASE,
  params = params,
  listener = object : OnApiCallbackListener() {

    // Handle a successful response with a JSON array
    override fun onSuccess(response: JSONArray) {
      super.onSuccess(response)
      // You can process the JSON array here, for example, a list of items
    }

    // Handle a successful response with a JSON object
    override fun onSuccess(response: JSONObject?) {
      super.onSuccess(response)
      // You can process the JSON object here, for example, order details
    }

    // Handle an error response
    override fun onError(code: Int, msg: String?) {
      super.onError(code, msg)
      // Handle the error based on the code and message
    }
  }
)
Params purchase = new Params();

purchase
  .put(new Params.Item(YOUR_ITEM_ID)
    .set(Params.Item.COLUMN.AMOUNT, YOUR_ITEM_AMOUNT)
    .set(Params.Item.COLUMN.PRICE, YOUR_ITEM_PRICE))
    .put(Params.Parameter.ORDER_ID, YOUR_ORDER_ID)
    .put(Params.Parameter.ORDER_PRICE, YOUR_ORDER_PRICE)
    .put(Params.Parameter.DELIVERY_ADDRESS, YOUR_DELIVERY_ADDRESS)
    .put(new Params.RecommendedBy(Params.RecommendedBy.TYPE.RECOMMENDATION, YOUR_RECOMMENDATION_CODE));

REES46.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.
email 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, YOUR_ITEM_ID)

// Full wish tracking

val fullWish = Params().apply {
  put(Params.Item(YOUR_FIRST_ITEM_ID))
  put(Params.Parameter.FULL_WISH, true)
  put(Params.Item(YOUR_SECOND_ITEM_ID))
}

sdk.trackEventManager.track(Params.TrackEvent.WISH, fullWish)
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, YOUR_ITEM_ID)
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(YOUR_EVENT_NAME)

// Tracking with additional parameters
sdk.trackEventManager.customTrack(
  event = YOUR_EVENT_NAME,
  category = YOUR_EVENT_CATEGORY,
  label = YOUR_EVENT_LABEL,
  value = YOUR_EVENT_VALUE
)
// 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 checks if the event-based rule is true, tracking clicks, views, etc.

// Events tracking depends on rules that were configured during stories creation.

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.

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,
  });
}
// No implementation
// No implementation
// No implementation
// No implementation

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, YOUR_ITEM_ID)
  // category filtration
  put(Params.Parameter.CATEGORY, YOUR_CATEGORY_ID)
}

 // get recommendation with product ids
sdk.recommendationManager.getRecommendation(RECOMMEDATION_CODE, params) { response ->
  Log.i(TAG, "Get recommendation response: $response")
}

// get recommendation with products info
sdk.recommendationManager.getExtendedRecommendation(RECOMMEDATION_CODE, params) { response ->
  Log.i(TAG, "Get extended recommendation response: $response")
}
val params = Params().apply {
  put(Params.Parameter.EXTENDED, true)
  put(Params.Parameter.ITEM, YOUR_ITEM_ID)
  put(Params.Parameter.CATEGORY, YOUR_CATEGORY_ID)
}

personaclick.recommend(
  YOUR_RECOMMENDER_CODE,
  params, object : Api.OnApiCallbackListener() {
    override fun onSuccess(response: JSONObject) {
      Log.i(TAG, "Recommender response: $response")
    }
  }
)

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.

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);
  });

// Blank request search
sdk.searchBlank()
// The request is sent to the endpoint 'search/blank'.
.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)
* group_id - id of the group with aggregated products (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
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, price_margin
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
email 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
brand_limit false This parameter allows limiting the number of brands aggregated in the response. The default limit is 1000

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)
* group_id - id of the group with aggregated products (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.
email 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.
email 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.
email 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.
email 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.
email 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.
email 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.
email 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 for a specific email
sdk.subscribeForPriceDrop(YOUR_PRODUCT_ID, YOUR_PRICE)

// Subscribe for a specific email
sdk.subscribeForPriceDrop(YOUR_PRODUCT_ID, YOUR_PRICE, YOUR_EMAIL)

// Subscribe for a specific phone number
sdk.subscribeForPriceDrop(YOUR_PRODUCT_ID, YOUR_PRICE, null, YOUR_PHONE_NUMBER)

// Unsubscribe from specific products
sdk.unsubscribeForPriceDrop(arrayOf(YOUR_PRODUCT_ID_1, YOUR_PRODUCT_ID_2, YOUR_PRODUCT_ID_3))

// Unsubscribe from all products
sdk.unsubscribeForPriceDrop(arrayOf())

// Subscribe
personaclick.subscribeForPriceDrop(YOUR_PRODUCT_ID, YOUR_PRICE);

// Subscribe for specific email
personaclick.subscribeForPriceDrop(YOUR_PRODUCT_ID, YOUR_PRICE, YOUR_EMAIL);

// Subscribe for specific phone
personaclick.subscribeForPriceDrop(YOUR_PRODUCT_ID, YOUR_PRICE, null, YOUR_PHONE_NUMBER);

// Unsubscribing from specific products
personaclick.unsubscribeForPriceDrop(arrayOf<String>(YOUR_PRODUCT_ID_1, YOUR_PRODUCT_ID_2, YOUR_PRODUCT_ID_3));

// Unsubscribing from all products
personaclick.unsubscribeForPriceDrop(arrayOf<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(YOUR_PRODUCT_ID)

// Subscribe for a specific email
sdk.subscribeForBackInStock(YOUR_PRODUCT_ID, YOUR_EMAIL)

// Subscribe for a specific phone number
sdk.subscribeForBackInStock(YOUR_PRODUCT_ID, YOUR_PHONE_NUMBER)

// Subscribe with product size
val properties = JSONObject()
  properties.put("fashion_size", YOUR_FASHION_SIZE)
  sdk.subscribeForBackInStock(YOUR_PRODUCT_ID, YOUR_EMAIL, null, properties, null)

// Unsubscribe from specific products
sdk.unsubscribeForBackInStock(arrayOf(YOUR_PRODUCT_ID_1, YOUR_PRODUCT_ID_2, YOUR_PRODUCT_ID_3))

// 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
email 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.

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
// notification object example
{
  "title": "notice",
  "body": "notice text",
  "click_action": "ACTION_VIEW",
  "sound": "default"
}

// notification object example
{
  "title": "notice",
  "body": "notice text",
  "click_action": "ACTION_VIEW",
  "sound": "default"
}

No implementaion needed

A custom notification will work if both of the following criteria are met:

The platform checks if attach_notification is enabled.

The second condition is the existence of the android_notification_payload object.

Once these two conditions are satisfied, the notification object will be sent to FCM for delivery to Android devices.

The notification object may include 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.

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 YOUR_EMAIL
)

// 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")
      }
   }
)

  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
email 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
sdk.addToSegment(YOUR_DID, null, null)

// With an email (`did` will be switched to the owner of the email)
sdk.addToSegment(YOUR_DID, YOUR_EMAIL, null)

// With a phone number (`did` will be switched to the owner of the phone number)
sdk.addToSegment(YOUR_DID, null, YOUR_PHONE_NUMBER)

// With both (`did` will be switched to the owner of primary contact)
sdk.addToSegment(YOUR_DID, YOUR_EMAIL, YOUR_PHONE_NUMBER)
// 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
sdk.removeFromSegment(YOUR_DID, null, null)

// With an email (`did` will be switched to the owner of the email)
sdk.removeFromSegment(YOUR_DID, YOUR_EMAIL, null)

// With a phone number (`did` will be switched to the owner of the phone number)
sdk.removeFromSegment(YOUR_DID, null, YOUR_PHONE_NUMBER)

// With both (`did` will be switched to the owner of primary contact)
sdk.removeFromSegment(YOUR_DID, YOUR_EMAIL, YOUR_PHONE_NUMBER)
// 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
email String true* User's email
phone String true* User's phone number
segment_id Integer true Segment ID
external_id String true* Segment ID
loyalty_id String true* Loyalty ID
telegram_id String true* Telegram 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",
      "external_id": "777_777",
      "telegram_id": "123456",
      "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.
email String true* User's email
phone String true* User's phone
external_id String true* External ID
telegram_id String true* Telegram ID
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
email 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.

Delete promocodes

curl --header "Content-Type: application/json"
  --request DELETE
  --data '{
    "shop_id": "SHOP_ID",
    "shop_secret": "SHOP_SECRET",
    "promo_code_list_id": "1",
    "codes": ["code1", "code2"]
  }'
  https://api.personaclick.com/promo_codes/delete


// Not implemented
// Not implemented
// Not implemented
// Not implemented
// Not implemented

DELETE https://api.personaclick.com/promo_codes/delete

Query Parameters

Parameter Type Required Description
promo_code_list_Id String true Id of the list with promo codes
codes Array true An array with promo codes

Response parameters

Parameter Type Description
delete_count Integer Number of deleted promo codes
not_found_count Integer Number of promo codes that were not found

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:

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:

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.
email 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:

Initial tasks

Before sending campaign you have to setup it:

  1. Prepare transactional email template
  2. Prepare transactional web/mobile push template
  3. Prepare transactional SMS template
  4. Create multi-channel campaign and select created templates for every channel you want to use in the campaign.
  5. 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:

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"]}

# Filter by price_margin
curl -X POST https://api.personaclick.com/products \
  -H "Content-Type: application/json" \
  -d '{
    "shop_id": "...",
    "did": "...",
    "sid": "...",
    "sort_by": "price_margin",
    "sort_dir": "desc"
  }'
// The method requires the command as the first argument, followed by the request parameters.
// Next, provide callback functions: first, the function to be called upon success, and then the one for handling failures.
personaclick('products', { limit: 5, categories: '313' }, success, error);
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
}
// sdk.productsManager requests a product list from the API with the following parameters:
// brands, merchants, categories, locations, limit, page, filters
// Example:

sdk.productsManager.getProductsList(
  brands = PRODUCTS_BRANDS,
  merchants = PRODUCTS_MERCHANTS,
  categories = PRODUCTS_CATEGORIES,
  locations = PRODUCTS_LOCATIONS,
  limit = PRODUCTS_LIMIT,
  page = PRODUCTS_PAGE,
  filters = PRODUCTS_FILTERS,
  listener = object : OnApiCallbackListener() {
    override fun onSuccess(response: JSONObject?) {
      super.onSuccess(response)
      // Handle your response
    }

    override fun onError(code: Int, msg: String?) {
      super.onError(code, msg)
      // Handle errors
    }
  }
)
// 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)
* count - the number of matches (number)
categories array of objects Array contains objects with following fields:
* id - category id (string)
* name - category name (string)
* url - category URL (string)
* url_handle - path to the category (string)
* count - number of products in the category (number)
* parent - parent's category id (string)
* alias - alternate category name (string)
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)
* priority - priority of the filter (number)
* ranges - ranges of numeric values for aggregation results (number)
* values – array of values (object). Has the following properties:
* value – value label (string)
* count – cont of products with 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)
* price – product price (number)
* price_formatted – product price with currency (string)
* price_full_formatted – product price, example: "547.67 $" (string)
* picture – product's picture URL in the PersonaClick storage (string)
* url – product URL (string)
* description – product description (string)
* category_ids – id of categories that product belongs to (array of strings)
* fashion_feature - feature of fashion category, for example "for kids" or "adult" (string)
* fashion_gender - gender of product`s auditory (string)
* sales_rate – number of sales of this product (integer)
* relative_sales_rate – relative share of sales represented in percents (integer)
* image_url - URL to the original image of the product (string)
* image_url_handle – path to the image (string)
* image_url_resized – object with keys represent the size pf image, values are paths to image
* _id – internal id (string)
* group_id - id of the group that has products of the same category aggregated into (string)
* 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
price_ranges array of objects objects contain fields 'to' and 'count' that represent upper limit of the price range and the number of products in range
price_median number median price 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* true User's email
phone* true User's phone number
loyalty_id* true User's loyalty_id
external_id* true User's external_id
telegram_id* true 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"]}
collapse false Boolean. This parameter indicates the aggregation of products under a single group_id. When the collapse parameter in the request is set to false, all products will be returned; otherwise, the products will be aggregated. The default value is true

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)
* group_id - id of the group of aggregated products (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)

storiesView.itemClickListener = object : OnClickListener {

  /**
  * Called when clicking on a regular link or deep link.
  * This function is responsible for defining what happens after the user clicks on the link.
  *
  * If this function returns `false`, the developer must implement their own logic for handling the click.
  * If this function returns `true`, the SDK will handle the processing after the user clicks on the link.
  *
  * @param url URL of the clicked link.
  * @return Boolean indicating whether to let the SDK handle the navigation (true) or handle it manually (false).
  */

  override fun onClick(url: String): Boolean {
    return false
  }

  /**
   * Called when clicking on a product.
   * This function is responsible for defining what happens after the user clicks on a product.
   *
   * If this function returns `false`, the developer must implement their own logic for handling the click.
   * If this function returns `true`, the SDK will handle the processing after the user clicks on the product.
   *
   * @param product The clicked product.
   * @return Boolean indicating whether to let the SDK handle the navigation (true) or handle it manually (false).
   */

  override fun onClick(product: Product): Boolean {
    return false
  }

  /**
   * Called when clicking on a product in a dialog, providing an option to prevent navigation to the browser.
   *
   * This function allows custom handling when the user clicks on a product with an associated URL in a dialog.
   * If this function returns `false`, navigation to the browser will be prevented, and the developer can implement custom behavior.
   * If this function returns `true`, the SDK will proceed to open the URL in the browser.
   *
   * @param product The clicked product, or `null` if not available.
   * @param url The URL associated with the product, or `null` if not available.
   * @return Boolean indicating whether to allow navigation to the browser (true) or handle it manually (false).
   */

  override fun onCloseDialogClick(
    product: Product?,
    url: String?
  ): Boolean {
      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 implementation needed
No implementation 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:

  1. If the old_price parameter is present in the DB, the crossed-out price displayed on the slide is the old_price
  2. If the old_price parameter is not in the DB, the crossed-out price displayed on the slide is the price
  3. If the price_with_promocode parameter is present in the DB, the price value displayed on the slide is price_with_promocode
  4. If theprice_with_promocode parameter is not in the DB, the price value displayed on the slide is the price

Note: Two prices are displayed on the slide: the actual price and the old price, which is visually crossed out.

Promocode message settings

No implementation needed
// You can change the message text a user will see after they've successfully copied the promocode. To set your own text, add it as a data-promocode-copy-text value.
<div class="rees46-stories" data-code="fea48d09f60e56a9eae9a2e1838e95e8" data-promocode-copy-text="promocode copied"></div>
No implementation yet
No implementation yet
No implementation yet
No implementation needed

Setting up the text for a message that the user will see after successfully copying the promocode can be done by changing the default text in the data-promocode-copy-text attribute.

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.