Docs GamifyEngine
Trang chủ > SDK kết nối Home > Connection SDK

SDK kết nối Connection SDK

SDK dùng để kết nối từ ứng dụng của bạn tới GamifyEngine: khởi tạo client, gửi sự kiện (track event), truy vấn điểm/tier khi cần.

Để bắn event (tracking) có hiệu lực, bạn phải cấu hình Event Type trước trên Client Admin. Luồng đúng:

  1. Cấu hình Event Type (Client Admin → Event Types): khai báo tên event (vd. deposit_made, purchase) và event_data_schema (các field, kiểu dữ liệu) nếu cần validate.
  2. Bắn event từ app/SDK: gửi đúng event_type (trùng tên đã khai báo) và event_data khớp với schema đã config.
  3. Nếu event_type chưa tồn tại hoặc event_data sai với schema (thiếu field bắt buộc, sai kiểu) → Engine trả lỗi; event không được xử lý và không cộng điểm.

→ Xem chi tiết và cấu hình: Event Types (Cấu hình).

Sơ đồ luồng: Config Event Type → Bắn event → Validate

Sơ đồ dưới đây mô tả thứ tự bắt buộc: cấu hình event type trước, sau đó mới gửi event đúng event_typeevent_data. Data không khớp config sẽ bị từ chối.

flowchart LR
  A["1. Client Admin
Config Event Type
(name, event_data_schema)"] B["2. App / SDK
track(event_type, event_data)"] C["3. Engine
Validate theo event_data_schema"] D["OK → Rule cộng điểm"] E["Data sai → Lỗi"] A --> B --> C C --> D C --> E style D fill:#00d4aa22,stroke:#00d4aa,color:#00d4aa style E fill:#ef444422,stroke:#ef4444,color:#ef4444

event_type chưa config hoặc event_data không khớp schema → Engine trả lỗi, không xử lý.

Giá trị cho đối tác (use case)

Mọi hành động của user (nạp tiền, đăng nhập, mua hàng, …) có thể tự động quy ra điểm nhờ rule bạn cấu hình trên Client Admin. SDK chỉ cần gửi một sự kiện (vd. deposit_made) — hệ thống tự cộng điểm, không cần backend của bạn tính toán hay gọi từng API. Bạn tập trung nghiệp vụ; GamifyEngine lo phần điểm, hạng, nhiệm vụ.

Tích hợp từng bước (cho Developer)

  1. Lấy apiBaseUrl và apiKey

    Từ Client Admin → API Keys hoặc từ backend (trả theo session). API Key nên do backend cấp, không hardcode trên frontend.

  2. Load SDK (script hoặc npm) và gọi init

    GamifyEngine.init({ apiBaseUrl, apiKey }) — một lần khi app/trang load (sau khi có apiKey).

  3. Cấu hình Event Type trước (Client Admin → Event Types)

    Khai báo tên event và schema event_data. Chỉ event_type đã khai báo và data đúng schema mới được Engine chấp nhận.

  4. Gọi track khi có hành động

    GamifyEngine.track('tên_sự_kiện', { ...data }) — ví dụ khi user nạp tiền: track('deposit_made', { amount: 100 }). tên_sự_kiệndata phải khớp với Event Type đã config, nếu không sẽ lỗi.

Khởi tạo (ví dụ):

// Sau khi có apiKey (từ backend/session)
GamifyEngine.init({
  apiBaseUrl: 'https://api.gamifyengine.com',
  apiKey: 'YOUR_API_KEY'
});

// Gửi sự kiện (track event) — rule trên Client Admin sẽ xử lý và cộng điểm
GamifyEngine.track('deposit_made', { amount: 100, currency: 'VND' });

Ví dụ event_dataevent_data_schema đầy đủ (deposit_made, purchase): xem Event Types — Ví dụ event_data_schema.

Rules & track event

Rule cấu hình trên Client Admin (ví dụ: khi event deposit_made và điều kiện thỏa thì cộng điểm) sẽ được áp dụng tự động khi bạn gọi track. Tên sự kiện và payload cần khớp với rule đã tạo trong Client Admin.

Tích hợp frontend

Tên chính thức của SDK là GamifyEngine. Load script từ CDN hoặc cài qua npm (URL CDN và tên package do bên vận hành cung cấp; hoặc dùng code mẫu trong nodejs.zip). Gọi setConfig hoặc init với apiBaseUrlapiKey (nên lấy từ backend theo session). Sau đó gọi track('tên_sự_kiện', data) mỗi khi có hành động cần ghi nhận. API Key không nên hardcode trên frontend.

Kết nối theo ngôn ngữ (backend)

Dưới đây là hướng dẫn và code ví dụ theo từng nền tảng: Node.js, Java, Python. Luồng chung: lấy apiBaseUrl + apiKey → Identify user (externalId → userId) → gửi event (user_id, event_type, event_data).

Node.js

Có hai cách tích hợp:

  • Cách 1 — SDK trực tiếp trên frontend: Load SDK, gọi GamifyEngine.init({ apiBaseUrl, apiKey }) rồi GamifyEngine.track('event_type', payload). API Key nên do backend trả về theo session.
  • Cách 2 — Qua backend (khuyến nghị): Frontend gọi API của bạn (vd. POST /api/fire-event), backend Node.js xác định user (Identify) rồi gửi sự kiện lên Gamify — backend Node.js vẫn có thể bắn event qua SDK (vd. dùng nodejs.zip hoặc package tương ứng). Ứng dụng demo demo-app dùng cách này.

Tải code mẫu Node.js:

  • demo-app.zip — ứng dụng demo đầy đủ (frontend React + backend Node).
  • nodejs.zip — source SDK / tích hợp Node.js (backend).

Ví dụ 1 — Frontend gửi event qua backend (React, từ demo-app)

Trong demo-app, tab Event Simulator gọi API backend với externalId, eventTypepayload. Backend sẽ Identify user rồi gửi event lên Gamify.

// Gửi event từ frontend (user đã chọn, ví dụ externalId = 'demo-alice')
async function fireEvent() {
  const res = await fetch('/api/fire-event', {
    method:  'POST',
    headers: { 'Content-Type': 'application/json' },
    body:    JSON.stringify({
      externalId: user?.id,        // id user trên hệ thống của bạn
      eventType:  'purchase.completed',
      payload:    { order_id: 'ORD-001', total_amount: 999, item_count: 1 },
    }),
  });
  const data = await res.json();
  // data chứa kết quả từ Gamify (userId, ...)
}

Ví dụ 2 — Backend nhận request và gửi event lên Gamify (Node, từ demo-app)

Backend nhận externalId, eventType, payload. Bước 1: gọi Identify (tạo/lấy user) để có userId. Bước 2: gửi event với user_id, event_type, event_data. Chi tiết endpoint và header do bên vận hành GamifyEngine cung cấp.

// (Đoạn logic chính từ demo-app server)
// 1) Identify user → lấy userId (UUID)
const identRes = await fetch(`${GAMIFY_API_URL}/v1/users?tenant=...`, {
  method:  'POST',
  headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${GAMIFY_API_KEY}` },
  body:    JSON.stringify({ externalId }),
});
const { data: userData } = await identRes.json();
const userId = userData?.id;

// 2) Gửi event
await fetch(`${GAMIFY_API_URL}/v1/events?tenant=...`, {
  method:  'POST',
  headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${GAMIFY_API_KEY}` },
  body:    JSON.stringify({
    user_id:    userId,
    event_type: eventType,
    event_data: payload || {},
    source:     'demo-app',
  }),
});

Ví dụ 3 — Mount Widget (từ demo-app)

Demo-app mount Widget với apiBaseUrl, apiKey, externalId lấy từ config (backend). Khi đổi user, unmount rồi mount lại với externalId mới.

// config từ /api/config (backend trả về gamifyApiUrl, gamifyApiKey, demoUsers)
useEffect(() => {
  if (!config || !user) return;
  const instance = globalThis.GamifyWidget.mount({
    apiBaseUrl:  config.gamifyApiUrl,
    apiKey:      config.gamifyApiKey,
    externalId:  user.id,
    tenant:      config.gamifyTenant || undefined,
    theme:       'cyberpunk',
    fabPosition: 'right-bottom',
    showToasts:  true,
  });
  return () => instance?.unmount?.();
}, [user?.id, config]);

Java

Backend Java (Spring Boot, Jakarta EE, hoặc plain Java) kết nối GamifyEngine: (1) Gọi Identify với externalId để lấy userId. (2) Gửi event với user_id, event_type, event_data. Dùng HTTP client (Java 11+ HttpClient, RestTemplate, hoặc WebClient), header Authorization: Bearer <API_KEY>. Base URL và endpoint do bên vận hành cung cấp.

// Ví dụ cấu trúc (Java 11+ HttpClient) — thay BASE_URL, API_KEY, tenant theo môi trường
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class GamifyClient {
    private final String baseUrl;
    private final String apiKey;
    private final String tenant;
    private final HttpClient http = HttpClient.newHttpClient();

    public GamifyClient(String baseUrl, String apiKey, String tenant) {
        this.baseUrl = baseUrl;
        this.apiKey = apiKey;
        this.tenant = tenant;
    }

    public String identify(String externalId) throws Exception {
        var body = String.format("{\"externalId\":\"%s\"}", externalId);
        var req = HttpRequest.newBuilder()
            .uri(URI.create(baseUrl + "/v1/users?tenant=" + tenant))
            .header("Content-Type", "application/json")
            .header("Authorization", "Bearer " + apiKey)
            .POST(HttpRequest.BodyPublishers.ofString(body))
            .build();
        var res = http.send(req, HttpResponse.BodyHandlers.ofString());
        // Parse JSON response → data.id (userId)
        return parseUserId(res.body());
    }

    public void trackEvent(String userId, String eventType, String eventDataJson) throws Exception {
        var body = String.format(
            "{\"user_id\":\"%s\",\"event_type\":\"%s\",\"event_data\":%s,\"source\":\"java\"}",
            userId, eventType, eventDataJson != null ? eventDataJson : "{}");
        var req = HttpRequest.newBuilder()
            .uri(URI.create(baseUrl + "/v1/events?tenant=" + tenant))
            .header("Content-Type", "application/json")
            .header("Authorization", "Bearer " + apiKey)
            .POST(HttpRequest.BodyPublishers.ofString(body))
            .build();
        http.send(req, HttpResponse.BodyHandlers.ofString());
    }
}

Python

Backend Python (Django, FastAPI, Flask, hoặc script) kết nối GamifyEngine: (1) Gọi Identify với external_id để lấy user_id. (2) Gửi event với user_id, event_type, event_data. Dùng requests hoặc httpx, header Authorization: Bearer <API_KEY>. Base URL và endpoint do bên vận hành cung cấp.

# Ví dụ (Python 3, thư viện requests) — thay BASE_URL, API_KEY, tenant theo môi trường
import requests

class GamifyClient:
    def __init__(self, base_url: str, api_key: str, tenant: str = ""):
        self.base_url = base_url.rstrip("/")
        self.api_key = api_key
        self.tenant = tenant
        self.session = requests.Session()
        self.session.headers["Authorization"] = f"Bearer {api_key}"
        self.session.headers["Content-Type"] = "application/json"

    def identify(self, external_id: str) -> str:
        url = f"{self.base_url}/v1/users"
        if self.tenant:
            url += f"?tenant={self.tenant}"
        r = self.session.post(url, json={"externalId": external_id})
        r.raise_for_status()
        return r.json()["data"]["id"]  # userId

    def track_event(self, user_id: str, event_type: str, event_data: dict = None):
        url = f"{self.base_url}/v1/events"
        if self.tenant:
            url += f"?tenant={self.tenant}"
        body = {
            "user_id": user_id,
            "event_type": event_type,
            "event_data": event_data or {},
            "source": "python",
        }
        r = self.session.post(url, json=body)
        r.raise_for_status()

# Sử dụng
client = GamifyClient("https://api.example.com", "YOUR_API_KEY", "my-tenant")
user_id = client.identify("user-123")
client.track_event(user_id, "purchase.completed", {"order_id": "ORD-001", "amount": 999})

SDK và Widget có thể dùng chung: Widget hiển thị UI; SDK dùng để track event từ trang host.

The SDK connects your app to GamifyEngine: initialize client, send events (track), and query points/tier as needed.

For tracking events to work, you must configure Event Types first in Client Admin. Correct flow:

  1. Configure Event Type (Client Admin → Event Types): define the event name (e.g. deposit_made, purchase) and event_data_schema (fields and types) if you want validation.
  2. Send events from app/SDK: use the same event_type (as configured) and event_data that matches the schema.
  3. If the event_type does not exist or event_data does not match the schema (missing required field, wrong type) → Engine returns an error; the event is not processed and no points are awarded.

→ Details and configuration: Event Types (Configuration).

Flow: Config Event Type → Send event → Validate

The diagram below shows the required order: configure the event type first, then send events with the correct event_type and event_data. Data that does not match the config is rejected.

flowchart LR
  A["1. Client Admin
Config Event Type
(name, event_data_schema)"] B["2. App / SDK
track(event_type, event_data)"] C["3. Engine
Validate against event_data_schema"] D["OK → Rule award points"] E["Data invalid → Error"] A --> B --> C C --> D C --> E style D fill:#00d4aa22,stroke:#00d4aa,color:#00d4aa style E fill:#ef444422,stroke:#ef4444,color:#ef4444

event_type not configured or event_data does not match schema → Engine returns error, no processing.

Value for partners (use case)

Every user action (deposit, login, purchase, …) can automatically become points via rules you configure in Client Admin. The SDK only sends one event (e.g. deposit_made) — the system awards points; your backend doesn’t compute or call APIs. You focus on business logic; GamifyEngine handles points, tiers, and missions.

Step-by-step integration (for developers)

  1. Get apiBaseUrl and apiKey

    From Client Admin → API Keys or from your backend (per session). Prefer issuing the key from the backend; don’t hardcode on the frontend.

  2. Load SDK (script or npm) and call init

    GamifyEngine.init({ apiBaseUrl, apiKey }) — once when the app/page loads (after you have the apiKey).

  3. Configure Event Type first (Client Admin → Event Types)

    Define the event name and event_data schema. Only declared event_types and data matching the schema are accepted by the Engine.

  4. Call track when an action happens

    GamifyEngine.track('event_name', { ...data }) — e.g. on deposit: track('deposit_made', { amount: 100 }). event_name and data must match the configured Event Type, otherwise the request will fail.

Initialization (example):

// After obtaining apiKey (from backend/session)
GamifyEngine.init({
  apiBaseUrl: 'https://api.gamifyengine.com',
  apiKey: 'YOUR_API_KEY'
});

// Send event (track) — rules in Client Admin will process and award points
GamifyEngine.track('deposit_made', { amount: 100, currency: 'VND' });

Full event_data and event_data_schema examples (deposit_made, purchase): see Event Types — Example event_data_schema.

Rules & track event

Rules configured in Client Admin (e.g. when event deposit_made matches conditions, award points) apply automatically when you call track. Event name and payload must match the rule created in Client Admin.

Frontend integration

The official SDK name is GamifyEngine. Load the script from CDN or install via npm (CDN URL and package name are provided by the operator; or use the sample code in nodejs.zip). Call setConfig or init with apiBaseUrl and apiKey (prefer from backend per session). Then call track('event_name', data) whenever an action should be recorded. Do not hardcode API Key on the frontend.

Connection by language (backend)

Below are guides and code examples per platform: Node.js, Java, Python. Common flow: get apiBaseUrl + apiKey → Identify user (externalId → userId) → send event (user_id, event_type, event_data).

Node.js

Two integration options:

  • Option 1 — SDK directly on frontend: Load SDK, call GamifyEngine.init({ apiBaseUrl, apiKey }) then GamifyEngine.track('event_type', payload). Prefer having the backend return the API Key per session.
  • Option 2 — Via backend (recommended): Frontend calls your API (e.g. POST /api/fire-event); the Node.js backend identifies the user (Identify) and sends the event to Gamify — the Node.js backend can still fire events via the SDK (e.g. using nodejs.zip or the corresponding package). The demo-app uses this approach.

Download Node.js sample code:

  • demo-app.zip — full demo app (React frontend + Node backend).
  • nodejs.zip — SDK / Node.js integration source (backend).

Example 1 — Frontend sending event via backend (React, from demo-app)

In demo-app, the Event Simulator tab calls the backend API with externalId, eventType, and payload. The backend then identifies the user and sends the event to Gamify.

// Send event from frontend (user selected, e.g. externalId = 'demo-alice')
async function fireEvent() {
  const res = await fetch('/api/fire-event', {
    method:  'POST',
    headers: { 'Content-Type': 'application/json' },
    body:    JSON.stringify({
      externalId: user?.id,        // your system's user id
      eventType:  'purchase.completed',
      payload:    { order_id: 'ORD-001', total_amount: 999, item_count: 1 },
    }),
  });
  const data = await res.json();
  // data contains result from Gamify (userId, ...)
}

Example 2 — Backend receiving request and sending event to Gamify (Node, from demo-app)

The backend receives externalId, eventType, payload. Step 1: call Identify (create or get user) to obtain userId. Step 2: send the event with user_id, event_type, event_data. Exact endpoints and headers are provided by the GamifyEngine operator.

// (Core logic from demo-app server)
// 1) Identify user → get userId (UUID)
const identRes = await fetch(`${GAMIFY_API_URL}/v1/users?tenant=...`, {
  method:  'POST',
  headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${GAMIFY_API_KEY}` },
  body:    JSON.stringify({ externalId }),
});
const { data: userData } = await identRes.json();
const userId = userData?.id;

// 2) Send event
await fetch(`${GAMIFY_API_URL}/v1/events?tenant=...`, {
  method:  'POST',
  headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${GAMIFY_API_KEY}` },
  body:    JSON.stringify({
    user_id:    userId,
    event_type: eventType,
    event_data: payload || {},
    source:     'demo-app',
  }),
});

Example 3 — Mount Widget (from demo-app)

Demo-app mounts the Widget with apiBaseUrl, apiKey, and externalId from config (backend). When the user changes, it unmounts and mounts again with the new externalId.

// config from /api/config (backend returns gamifyApiUrl, gamifyApiKey, demoUsers)
useEffect(() => {
  if (!config || !user) return;
  const instance = globalThis.GamifyWidget.mount({
    apiBaseUrl:  config.gamifyApiUrl,
    apiKey:      config.gamifyApiKey,
    externalId:  user.id,
    tenant:      config.gamifyTenant || undefined,
    theme:       'cyberpunk',
    fabPosition: 'right-bottom',
    showToasts:  true,
  });
  return () => instance?.unmount?.();
}, [user?.id, config]);

Java

A Java backend (Spring Boot, Jakarta EE, or plain Java) connects to GamifyEngine: (1) Call Identify with externalId to get userId. (2) Send the event with user_id, event_type, event_data. Use an HTTP client (Java 11+ HttpClient, RestTemplate, or WebClient) with header Authorization: Bearer <API_KEY>. Base URL and endpoints are provided by the operator.

// Example structure (Java 11+ HttpClient) — replace BASE_URL, API_KEY, tenant per environment
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class GamifyClient {
    private final String baseUrl;
    private final String apiKey;
    private final String tenant;
    private final HttpClient http = HttpClient.newHttpClient();

    public GamifyClient(String baseUrl, String apiKey, String tenant) {
        this.baseUrl = baseUrl;
        this.apiKey = apiKey;
        this.tenant = tenant;
    }

    public String identify(String externalId) throws Exception {
        var body = String.format("{\"externalId\":\"%s\"}", externalId);
        var req = HttpRequest.newBuilder()
            .uri(URI.create(baseUrl + "/v1/users?tenant=" + tenant))
            .header("Content-Type", "application/json")
            .header("Authorization", "Bearer " + apiKey)
            .POST(HttpRequest.BodyPublishers.ofString(body))
            .build();
        var res = http.send(req, HttpResponse.BodyHandlers.ofString());
        return parseUserId(res.body());  // parse data.id
    }

    public void trackEvent(String userId, String eventType, String eventDataJson) throws Exception {
        var body = String.format(
            "{\"user_id\":\"%s\",\"event_type\":\"%s\",\"event_data\":%s,\"source\":\"java\"}",
            userId, eventType, eventDataJson != null ? eventDataJson : "{}");
        var req = HttpRequest.newBuilder()
            .uri(URI.create(baseUrl + "/v1/events?tenant=" + tenant))
            .header("Content-Type", "application/json")
            .header("Authorization", "Bearer " + apiKey)
            .POST(HttpRequest.BodyPublishers.ofString(body))
            .build();
        http.send(req, HttpResponse.BodyHandlers.ofString());
    }
}

Python

A Python backend (Django, FastAPI, Flask, or script) connects to GamifyEngine: (1) Call Identify with external_id to get user_id. (2) Send the event with user_id, event_type, event_data. Use requests or httpx with header Authorization: Bearer <API_KEY>. Base URL and endpoints are provided by the operator.

# Example (Python 3, requests) — replace BASE_URL, API_KEY, tenant per environment
import requests

class GamifyClient:
    def __init__(self, base_url: str, api_key: str, tenant: str = ""):
        self.base_url = base_url.rstrip("/")
        self.api_key = api_key
        self.tenant = tenant
        self.session = requests.Session()
        self.session.headers["Authorization"] = f"Bearer {api_key}"
        self.session.headers["Content-Type"] = "application/json"

    def identify(self, external_id: str) -> str:
        url = f"{self.base_url}/v1/users"
        if self.tenant:
            url += f"?tenant={self.tenant}"
        r = self.session.post(url, json={"externalId": external_id})
        r.raise_for_status()
        return r.json()["data"]["id"]

    def track_event(self, user_id: str, event_type: str, event_data: dict = None):
        url = f"{self.base_url}/v1/events"
        if self.tenant:
            url += f"?tenant={self.tenant}"
        body = {
            "user_id": user_id,
            "event_type": event_type,
            "event_data": event_data or {},
            "source": "python",
        }
        r = self.session.post(url, json=body)
        r.raise_for_status()

# Usage
client = GamifyClient("https://api.example.com", "YOUR_API_KEY", "my-tenant")
user_id = client.identify("user-123")
client.track_event(user_id, "purchase.completed", {"order_id": "ORD-001", "amount": 999})

SDK and Widget can be used together: Widget for UI; SDK to track events from the host page.