Getting Started
Complete tutorial for integrating the Analytics SDK into your server
This guide will walk you through integrating the Stacked Analytics SDK into your server application from installation to tracking your first event.
Installation
Install the SDK via npm:
npm install @pixels-online/pixels-analytics-node-sdkInstall the SDK via Go modules:
go get github.com/pixels-online/pixels-analytics-go-sdkStep-by-Step Integration
Initialize the SDK
Initialize the Analytics SDK using your credentials from the dashboard.
Single Instance
You should have a single instance of the SDK in your server application, for example in a services/analytics file.
import PixelsAnalytics from "@pixels-online/pixels-analytics-node-sdk";
const analytics = new PixelsAnalytics({
apiKey: process.env.PIXELS_API_KEY!,
clientId: process.env.PIXELS_CLIENT_ID!,
env: "test", // 'test' | 'live' | 'staging' | 'dev'
});
export default analytics;package main
import (
"context"
"log"
"os"
pixels "github.com/pixels-online/pixels-analytics-go-sdk"
)
func main() {
config := pixels.Config{
APIKey: os.Getenv("PIXELS_API_KEY"),
ClientID: os.Getenv("PIXELS_CLIENT_ID"),
Env: "test", // "test" or "live"
}
analytics, err := pixels.New(config)
if err != nil {
log.Fatalf("Failed to create analytics client: %v", err)
}
defer analytics.Close() // Ensure graceful shutdown
ctx := context.Background()
// Use analytics...
}Environment Recommendation
Always use test environment during development and live for production.
Track Your First Event
Track a player sign-in event:
// Track player sign-in
analytics.signIn("player-123", {
username: "CoolPlayer",
extra: { platform: "steam" },
});// Track player sign-in
err := analytics.SignIn(ctx, "player-123", pixels.SignInParams{
Username: stringPtr("CoolPlayer"),
Extra: map[string]interface{}{
"platform": "steam",
},
})
if err != nil {
log.Printf("Error tracking sign-in: %v", err)
}
// Helper function for optional strings
func stringPtr(s string) *string {
return &s
}Automatic Batching
Events are automatically batched and sent to the server. You don't need to manually flush unless you want immediate sending.
Track Currency Transactions
Track when players earn or spend currency:
// Track currency transaction
const txId = analytics.spendCurrency("player-123", {
currency_id: "gold",
currency_amount: 100,
context: "weapon_upgrade",
to_kind: "store",
to_id: "blacksmith",
});
console.log("Transaction ID:", txId);// Track currency transaction
txID, err := analytics.SpendCurrency(ctx, "player-123", pixels.SpendCurrencyParams{
CurrencyID: "gold",
CurrencyAmount: 100.0,
Context: stringPtr("weapon_upgrade"),
ToKind: stringPtr("store"),
ToID: stringPtr("blacksmith"),
})
if err != nil {
log.Printf("Error tracking currency spend: %v", err)
} else {
log.Printf("Transaction ID: %s", txID)
}Track Item Gains
Track when players gain items, optionally linking to a currency transaction:
// Track item gained (linked to currency transaction)
analytics.gainItem("player-123", {
item_id: "legendary_sword",
item_amount: 1,
tx_id: txId, // Link to previous transaction
context: "weapon_upgrade",
});// Track item gained (linked to currency transaction)
err = analytics.GainItem(ctx, "player-123", pixels.GainItemParams{
ItemID: "legendary_sword",
ItemAmount: 1,
TxID: stringPtr(txID), // Link to previous transaction
Context: stringPtr("weapon_upgrade"),
})
if err != nil {
log.Printf("Error tracking item gain: %v", err)
}Track Player Snapshots
Send a complete snapshot of the player's current state. This is crucial for offer targeting.
analytics.playerSnapshot("player-123", {
username: "CoolPlayer",
trust_score: 85,
currencies: [
{ id: "gold", balance: 1500, in: 5000, out: 3500 },
{ id: "gems", balance: 50 },
],
levels: [
{ skill_id: "combat", level_value: 15 },
{ skill_id: "crafting", level_value: 10 },
],
achievements: [
{ id: "first_boss", count: 1 },
{ id: "pvp_wins", count: 25 },
],
extra: {
guild_id: "warriors_123",
premium_member: true,
},
});trustScore := 85
err = analytics.PlayerSnapshot(ctx, "player-123", pixels.SnapshotParams{
Username: stringPtr("CoolPlayer"),
TrustScore: &trustScore,
Currencies: []pixels.CurrencySnapshot{
{ID: "gold", Balance: 1500, In: floatPtr(5000.0), Out: floatPtr(3500.0)},
{ID: "gems", Balance: 50},
},
Levels: []pixels.LevelSnapshot{
{SkillID: "combat", LevelValue: 15},
{SkillID: "crafting", LevelValue: 10},
},
Achievements: []pixels.AchievementSnapshot{
{ID: "first_boss", Count: intPtr(1)},
{ID: "pvp_wins", Count: intPtr(25)},
},
Extra: map[string]interface{}{
"guild_id": "warriors_123",
"premium_member": true,
},
})
if err != nil {
log.Printf("Error tracking snapshot: %v", err)
}
// Helper functions for optional parameters
func intPtr(i int) *int {
return &i
}
func floatPtr(f float64) *float64 {
return &f
}Best Practice
Send player snapshots regularly (e.g., on login, after significant changes) to keep Stacked's user profiles up-to-date.
Create JWT Endpoint for Client SDKs
If you're using the Client SDK, create an endpoint to generate JWT tokens:
// Express endpoint example
app.post('/api/stacked-token', async (req, res) => {
const playerId = req.user.id; // Your user ID from session/auth
try {
const token = await analytics.signJwt({ playerId });
res.json({ token });
} catch (error) {
res.status(500).json({ error: 'Failed to generate token' });
}
});// HTTP handler example
func stackedTokenHandler(w http.ResponseWriter, r *http.Request) {
playerID := getPlayerIDFromSession(r) // Your auth logic
token, err := analytics.SignJwt(r.Context(), playerID)
if err != nil {
http.Error(w, "Failed to generate token", http.StatusInternalServerError)
return
}
json.NewEncoder(w).Encode(map[string]string{
"token": token,
})
}Security Warning
Never expose API keys in client-side code. Always generate JWT tokens server-side using the Analytics SDK.
Next Steps
Now that you have the SDK integrated, explore:
- Configuration - Learn about all SDK configuration options
- Event Tracking - Complete guide to tracking all event types
- API Types - Full type reference for all SDK methods
Common Patterns
Login Flow
// 1. User signs in
analytics.signIn("player-123", {
username: "CoolPlayer",
});
// 2. Send current snapshot
analytics.playerSnapshot("player-123", {
// ... current user state
});// 1. User signs in
err := analytics.SignIn(ctx, "player-123", pixels.SignInParams{
Username: stringPtr("CoolPlayer"),
})
// 2. Send current snapshot
err = analytics.PlayerSnapshot(ctx, "player-123", pixels.SnapshotParams{
// ... current user state
})Purchase Flow
// 1. User spends currency
const txId = analytics.spendCurrency("player-123", {
currency_id: "gold",
currency_amount: 100,
context: "item_purchase",
});
// 2. User gains item
analytics.gainItem("player-123", {
item_id: "sword_01",
item_amount: 1,
tx_id: txId, // Link to currency transaction
context: "item_purchase",
});// 1. User spends currency
txID, err := analytics.SpendCurrency(ctx, "player-123", pixels.SpendCurrencyParams{
CurrencyID: "gold",
CurrencyAmount: 100.0,
Context: stringPtr("item_purchase"),
})
// 2. User gains item
err = analytics.GainItem(ctx, "player-123", pixels.GainItemParams{
ItemID: "sword_01",
ItemAmount: 1,
TxID: stringPtr(txID), // Link to currency transaction
Context: stringPtr("item_purchase"),
})
Stacked