Running Your First Experiment
Now that your SDK is set up and you have a context, you're ready to run an experiment. Here's what that looks like from your code's perspective:
- Check the variant to find out which experience this user should see
- Render the right experience based on that variant (or use variables to make it flexible)
- Track goals to measure whether the experiment is working
- Send the data to ABsmartly's collector
Once the context is ready, all treatment() calls are resolved locally with no
additional network requests. Any experiment that isn't running will return 0
(Variant A, the control group).
Steps 1 and 3 are all you need for a basic experiment. Step 2 (variables) and Step 4 (manual event flushing) are useful but not required for your first test.
Step 1: Check which variant the user is in
The treatment() method is how you find out which variant a user has been assigned to.
It returns a number that maps to the variants you see in the Web Console:
| Number | Web Console name | Meaning |
|---|---|---|
0 | Variant A | Control (the baseline experience) |
1 | Variant B | First treatment |
2 | Variant C | Second treatment |
3 | Variant D | Third treatment |
| ... | ... | ... |
Calling treatment() also records an exposure, which tells ABsmartly that this user
actually saw the experiment. This is how ABsmartly knows to include them in the
statistical analysis.
Use an if/else block to branch your code based on the variant:
- Javascript
- Python3
- React
- Swift
- Vue2
- Vue3
- Java
- Go
- .NET
- PHP
- Ruby
- Flutter/Dart
const treatment = context.treatment("homepage_banner_experiment");
if (treatment === 1) {
showBanner("Check out our latest deals!");
} else {
showBanner("Welcome back!");
}
treatment = context.get_treatment("homepage_banner_experiment")
if treatment == 1:
show_banner("Check out our latest deals!")
else:
show_banner("Welcome back!")
const { variant } = useTreatment("homepage_banner_experiment");
if (variant === 1) {
return <Banner text="Check out our latest deals!" />;
}
return <Banner text="Welcome back!" />;
Alternative: declarative component patterns
The React SDK also provides component-based approaches. The Treatment and
TreatmentVariant components let you declare variants without conditional logic.
You can pass variant letters ("A", "B") or numbers:
return (
<Treatment name="experiment_name" loadingComponent={<MySpinner />}>
{/* The variant prop can have numbers or letters passed to it */}
<TreatmentVariant variant="A">
{/* Variant 0 */}
<DefaultButton />
</TreatmentVariant>
<TreatmentVariant variant="B">
{/* Variant 1 */}
<ButtonVariant1 />
</TreatmentVariant>
<TreatmentVariant variant="C">
{/* Variant 2 */}
<ButtonVariant2 />
</TreatmentVariant>
</Treatment>
);
For more control, TreatmentFunction gives you the variant as a render prop:
return (
<TreatmentFunction name="experiment_name" loadingComponent={<MySpinner />}>
{({ variant }) =>
variant === 1 ? (
<ButtonVariant1 />
) : variant === 2 ? (
<ButtonVariant2 />
) : (
<DefaultButton />
)
}
</TreatmentFunction>
);
let treatment = context.getTreatment("homepage_banner_experiment")
if treatment == 1 {
showBanner("Check out our latest deals!")
} else {
showBanner("Welcome back!")
}
<treatment name="homepage_banner_experiment">
<template #A>
<banner text="Welcome back!" />
</template>
<template #B>
<banner text="Check out our latest deals!" />
</template>
</treatment>
Alternative slot patterns
By variant index - use slot names #0, #1, #2 to match variant numbers
directly. Each slot receives treatment, ready, and failed as scoped properties:
<treatment name="exp_test_experiment">
<template #0>
<my-button></my-button>
</template>
<template #1="{ treatment }">
<my-button :variant="treatment"></my-button>
</template>
<template #2="{ treatment }">
<my-other-button :variant="treatment"></my-other-button>
</template>
<template #loading>
<my-spinner></my-spinner>
</template>
</treatment>
Default slot only - use a single default slot and handle the branching yourself
with the treatment, ready, and failed scoped properties:
<treatment name="exp_test_experiment">
<template #default="{ treatment, ready, failed }">
<template v-if="ready">
<my-button v-if="treatment == 0"></my-button>
<my-button v-else-if="treatment == 1"></my-button>
<my-other-button v-else-if="treatment == 2"></my-other-button>
</template>
<template v-else><my-spinner></my-spinner></template>
</template>
</treatment>
<treatment name="homepage_banner_experiment">
<template #A>
<banner text="Welcome back!" />
</template>
<template #B>
<banner text="Check out our latest deals!" />
</template>
</treatment>
Alternative slot patterns
By variant index - use slot names #0, #1, #2 to match variant numbers
directly. Each slot receives treatment, ready, and failed as scoped properties:
<treatment name="exp_test_experiment">
<template #0>
<my-button></my-button>
</template>
<template #1="{ treatment }">
<my-button :variant="treatment"></my-button>
</template>
<template #2="{ treatment }">
<my-other-button :variant="treatment"></my-other-button>
</template>
<template #loading>
<my-spinner></my-spinner>
</template>
</treatment>
Default slot only - use a single default slot and handle the branching yourself
with the treatment, ready, and failed scoped properties:
<treatment name="exp_test_experiment">
<template #default="{ treatment, ready, failed }">
<template v-if="ready">
<my-button v-if="treatment == 0"></my-button>
<my-button v-else-if="treatment == 1"></my-button>
<my-other-button v-else-if="treatment == 2"></my-other-button>
</template>
<template v-else><my-spinner></my-spinner></template>
</template>
</treatment>
int treatment = context.getTreatment("homepage_banner_experiment");
if (treatment == 1) {
showBanner("Check out our latest deals!");
} else {
showBanner("Welcome back!");
}
treatment, _ := context.GetTreatment("homepage_banner_experiment")
if treatment == 1 {
showBanner("Check out our latest deals!")
} else {
showBanner("Welcome back!")
}
var treatment = context.GetTreatment("homepage_banner_experiment");
if (treatment == 1) {
ShowBanner("Check out our latest deals!");
} else {
ShowBanner("Welcome back!");
}
$treatment = $context->getTreatment('homepage_banner_experiment');
if ($treatment === 1) {
showBanner('Check out our latest deals!');
} else {
showBanner('Welcome back!');
}
treatment = context.treatment('homepage_banner_experiment')
if treatment == 1
show_banner("Check out our latest deals!")
else
show_banner("Welcome back!")
end
final treatment = await context.getTreatment("homepage_banner_experiment");
if (treatment == 1) {
showBanner("Check out our latest deals!");
} else {
showBanner("Welcome back!");
}
This works well for experiments where the logic change is entirely in your code (show component A vs component B). But if you want the Web Console to control values like colours, copy, or feature flags, read on.
Step 2: Use variables for flexible experiments
Instead of hardcoding what each variant does, you can use treatment variables. These are key-value pairs that you set in the Web Console and pull into your code at runtime.
The benefit: your product team can add new variants or tweak existing ones from the Web Console without anyone touching code.
For example, say you have an experiment to find out what colour of button gets the most
clicks. In the Web Console, you'd add a variable called button.color with value "green"
on Variant B. You don't need to set anything on Variant A - that's what the default value
in your code is for. Then in your code, variableValue() returns the experiment value for
the user's assigned variant, or the default if the experiment isn't running or the user is
in the control group:
- Javascript
- Python3
- React
- Swift
- Vue2
- Vue3
- Java
- Go
- .NET
- PHP
- Ruby
- Flutter/Dart
const buttonColor = context.variableValue("button.color", "blue");
document.getElementById("cta-button").style.backgroundColor = buttonColor;
button_color = context.get_variable_value("button.color", "blue")
render_button(color=button_color)
const { context } = useABSmartly();
const buttonColor = context.variableValue("button.color", "blue");
return <button style={{ backgroundColor: buttonColor }}>Get Started</button>;
let buttonColor = context.getVariableValue("button.color", defaultValue: "blue")
ctaButton.backgroundColor = UIColor(named: buttonColor)
const buttonColor = this.$absmartly.variableValue("button.color", "blue");
this.ctaStyle = { backgroundColor: buttonColor };
const buttonColor = this.$absmartly.variableValue("button.color", "blue");
this.ctaStyle = { backgroundColor: buttonColor };
String buttonColor = (String) context.getVariableValue("button.color", "blue");
ctaButton.setBackgroundColor(Color.parseColor(buttonColor));
buttonColor, _ := context.GetVariableValue("button.color", "blue")
if color, ok := buttonColor.(string); ok {
renderButton(color)
}
var buttonColor = context.GetVariableValue("button.color", "blue");
ctaButton.BackgroundColor = Color.FromName(buttonColor);
$buttonColor = $context->getVariableValue('button.color', 'blue');
echo '<button style="background-color: ' . htmlspecialchars($buttonColor) . '">Get Started</button>';
button_color = context.variable_value('button.color', 'blue')
render_button(color: button_color)
final buttonColor = context.getVariableValue("button.color", "blue");
ctaButton.style = ButtonStyle(backgroundColor: colorFromName(buttonColor));
Step 3: Track goals to measure success
An experiment without goals is like running a test without checking the results. Goals are the actions you want to measure: did the user click the button? Complete a purchase? Sign up for a newsletter?
The track() method records these actions. Each goal corresponds to a goal_name
defined in the Web Console. You can also pass properties to create more granular metrics.
The track() method records user actions. It takes two arguments:
- goal_name: The name of the goal, matching one you've defined in the Web
Console. Any name that doesn't match will be ignored (unless
AUTO_GOAL_CREATIONis enabled on your instance). - properties (optional): Key-value pairs for extra metrics or filtering (e.g., revenue, item category).
- Javascript
- Python3
- React
- Swift
- Vue2
- Vue3
- Java
- Go
- .NET
- PHP
- Ruby
- Flutter/Dart
var properties = {
price: 10000,
category: "5 stars",
free_cancellation: true,
instance_id: 5350,
};
context.track("booking", properties);
context.track("payment", {
"item_count": 1,
"total_amount": 1999.99
})
const { context } = useABSmartly();
const properties = {
price: 10000,
category: "5 stars",
free_cancellation: true,
instance_id: 5350,
};
context.track("booking", properties);
context.track("payment", properties: ["item_count": 1, "total_amount": 1999.99])
var properties = {
price: 10000,
category: "5 stars",
free_cancellation: true,
instance_id: 5350,
};
this.$absmartly.track("booking", properties);
var properties = {
price: 10000,
category: "5 stars",
free_cancellation: true,
instance_id: 5350,
};
this.$absmartly.track("booking", properties);
context.track("payment", Map.of(
"item_count", 1,
"total_amount", 1999.99
));
context.Track("payment", map[string]interface{}{
"item_count": 1,
"total_amount": 1999.99
})
context.Track("payment", new Dictionary<string, object>() {
{ "item_count", 1 },
{ "total_amount", 1999.99}
});
$context->track(
'payment',
(object) ['item_count' => 1, 'total_amount' => 1999.99]
);
context.track(
'payment',
{ item_count: 1, total_amount: 1999.99 }
)
context.track("payment",{
"item_count": 1,
"total_amount": 1999.99
});
- By default, the
goal_namemust match exactly what you defined in the Web Console. Anything else will be ignored. However, if your instance hasAUTO_GOAL_CREATIONenabled, any unseen goals will be automatically created in the Web Console. - Properties are optional but useful for filtering and creating extra metrics.
Step 4: Make sure your data gets sent
Most SDKs batch events and send them to ABsmartly's collector automatically. For most use cases, you don't need to do anything here.
The Javascript SDK running in Node.js, the PHP SDK, and the Ruby SDK do not
auto-publish events. You must call publish() or finalize() explicitly at the end of
each request, or your exposure and goal data will not be sent.
Even with auto-publishing, there are times when you need to guarantee events are sent
before moving on. For example, before a page navigation in a multi-page app, or before
a server sends its response. In those cases, call publish() explicitly:
Using publish() to flush events manually
Call publish() before page navigations, server responses, or any point where
the process might exit before the SDK's auto-flush fires. This ensures exposure
and goal data is sent to the collector before the context is lost.
- Javascript
- Python3
- React
- Swift
- Vue2
- Vue3
- Java
- Go
- .NET
- PHP
- Ruby
- Flutter/Dart
// You can just publish
context.publish();
// or wait for it to finish, so if you want to
// navigate to another page without losing impressions,
// you can do that once the promise resolves.
context.publish().then(function () {
document.location.replace("another_page");
});
Python also provides publish_async() for non-blocking use.
context.publish()
const { context } = useABSmartly();
context.publish().then(() => {
document.location.replace("another_page");
});
context.publish().done {
print("all pending events published")
}
await this.$absmartly.publish().then(() => {
window.location = "https://www.absmartly.com";
});
await this.$absmartly.publish().then(() => {
window.location = "https://www.absmartly.com";
});
Java also provides publishAsync() for non-blocking use.
context.publish();
Go also provides PublishAsync() for non-blocking use.
context.Publish()
.NET also provides PublishAsync() for non-blocking use.
context.Publish();
$context->publish();
context.publish
context.publish();
Putting it all together
Here's a realistic starting point you can copy and adapt. It covers SDK init, context creation, treatment checking, variable usage, goal tracking, and cleanup.
- Javascript
- Python3
- React
- Swift
- Vue2
- Vue3
- Java
- Go
- .NET
- PHP
- Ruby
- Flutter/Dart
const absmartly = require("@absmartly/javascript-sdk");
// Initialize the SDK
const sdk = new absmartly.SDK({
endpoint: "https://your-company.absmartly.io/v1",
apiKey: "YOUR-API-KEY",
environment: "production",
application: "website",
});
// Create a context for this user
const request = {
units: {
user_id: "user-12345",
},
};
const context = sdk.createContext(request);
context.ready().then(() => {
// Check which variant the user is in
const treatment = context.treatment("homepage_banner_experiment");
if (treatment === 1) {
// Variant B: show a personalized banner
showBanner("Welcome back, we have new deals for you!");
} else {
// Variant A (control): show the existing banner
showBanner("Welcome back!");
}
// Use a variable set in the Web Console for more flexibility
const buttonColor = context.variableValue("button.color", "blue");
setButtonColor(buttonColor);
// Track when the user clicks the CTA button
document.getElementById("cta-button").addEventListener("click", () => {
context.track("cta_click", { page: "homepage" });
});
// Track a purchase with revenue data
onPurchaseComplete((order) => {
context.track("purchase", {
revenue: order.total,
item_count: order.items.length,
});
});
});
// When the user leaves or the app shuts down, finalize the context
// to flush any remaining events
window.addEventListener("beforeunload", () => {
context.finalize();
});
from absmartly import ClientConfig, Client, DefaultHTTPClient, DefaultHTTPClientConfig, ABSmartlyConfig, ABSmartly, ContextConfig
# Initialize the SDK
client_config = ClientConfig()
client_config.endpoint = "https://your-company.absmartly.io/v1"
client_config.api_key = "YOUR-API-KEY"
client_config.application = "website"
client_config.environment = "production"
sdk_config = ABSmartlyConfig()
sdk_config.client = Client(client_config, DefaultHTTPClient(DefaultHTTPClientConfig()))
sdk = ABSmartly(sdk_config)
# Create a context for this user
context_config = ContextConfig()
context_config.units = {"user_id": "user-12345"}
context = sdk.create_context(context_config)
context.wait_until_ready()
# Check which variant the user is in
treatment = context.get_treatment("homepage_banner_experiment")
if treatment == 1:
# Variant B: show a personalized banner
show_banner("Welcome back, we have new deals for you!")
else:
# Variant A (control): show the existing banner
show_banner("Welcome back!")
# Use a variable set in the Web Console for more flexibility
button_color = context.get_variable_value("button.color", "blue")
set_button_color(button_color)
# Track when the user completes a key action
context.track("cta_click", {"page": "homepage"})
# Track a purchase with revenue data
context.track("purchase", {
"revenue": 49.99,
"item_count": 3,
})
# Close the context to flush remaining events
context.close()
// This example shows multiple React patterns - pick the one that fits your component
import ABSmartly, {
Treatment,
TreatmentVariant,
useABSmartly,
useTreatment,
} from "@absmartly/react-sdk";
function App() {
const sdkOptions = {
endpoint: "https://your-company.absmartly.io/v1",
apiKey: "YOUR-API-KEY",
environment: "production",
application: "website",
};
const contextOptions = {
units: { user_id: "user-12345" },
};
return (
<ABSmartly sdkOptions={sdkOptions} contextOptions={contextOptions}>
<Homepage />
</ABSmartly>
);
}
function CtaButton({ onClick }) {
const { variant } = useTreatment("cta_color_experiment");
const color = variant === 1 ? "blue" : "green";
return (
<button onClick={onClick} style={{ backgroundColor: color }}>
Get Started
</button>
);
}
function Homepage() {
const { context } = useABSmartly();
const handleCtaClick = () => {
context.track("cta_click", { page: "homepage" });
};
const handlePurchase = (order) => {
context.track("purchase", {
revenue: order.total,
item_count: order.items.length,
});
};
return (
<div>
{/* Option 1: useTreatment hook for programmatic variant logic */}
<CtaButton onClick={handleCtaClick} />
{/* Option 2: Treatment components for declarative variant rendering */}
<Treatment name="homepage_banner_experiment">
<TreatmentVariant variant={0}>
<Banner text="Welcome back!" />
</TreatmentVariant>
<TreatmentVariant variant={1}>
<Banner text="Welcome back, we have new deals for you!" />
</TreatmentVariant>
</Treatment>
</div>
);
}
import ABSmartly
// Initialize the SDK
let clientConfig = ClientConfig(
apiKey: "YOUR-API-KEY",
application: "website",
endpoint: "https://your-company.absmartly.io/v1",
environment: "production"
)
let client = try DefaultClient(config: clientConfig)
let sdkConfig = ABSmartlyConfig.create()
sdkConfig.client = client
let sdk = try ABSmartlySDK(config: sdkConfig)
// Create a context for this user
let contextConfig = ContextConfig()
contextConfig.setUnit(unitType: "user_id", uid: "user-12345")
let context = sdk.createContext(config: contextConfig)
context.waitUntilReady().done { context in
// Check which variant the user is in
let treatment = context.getTreatment("homepage_banner_experiment")
if treatment == 1 {
// Variant B: show a personalized banner
showBanner("Welcome back, we have new deals for you!")
} else {
// Variant A (control): show the existing banner
showBanner("Welcome back!")
}
// Use a variable set in the Web Console for more flexibility
let buttonColor = context.getVariableValue("button.color", defaultValue: "blue")
setButtonColor(buttonColor)
// Track when the user completes a key action
context.track("cta_click", properties: ["page": "homepage"])
// Track a purchase with revenue data
context.track("purchase", properties: [
"revenue": 49.99,
"item_count": 3
])
// Close the context when done to flush remaining events
context.close()
}
// main.js - Initialize the SDK as a Vue plugin
import Vue from "vue";
import App from "./App.vue";
import absmartly from "@absmartly/vue2-sdk";
Vue.use(absmartly.ABSmartlyVue, {
sdkOptions: {
endpoint: "https://your-company.absmartly.io/v1",
apiKey: "YOUR-API-KEY",
environment: "production",
application: "website",
},
context: {
units: { user_id: "user-12345" },
},
attributes: {
user_agent: navigator.userAgent,
},
});
new Vue({ render: (h) => h(App) }).$mount("#app");
// In your component, use treatments and track goals:
//
// <template>
// <div>
// <treatment name="homepage_banner_experiment">
// <template #A> <!-- Variant A (control) -->
// <banner text="Welcome back!" />
// </template>
// <template #B> <!-- Variant B -->
// <banner text="Welcome back, we have new deals for you!" />
// </template>
// </treatment>
//
// <button @click="trackClick">Get Started</button>
// </div>
// </template>
//
// <script>
// export default {
// methods: {
// trackClick() {
// this.$absmartly.track("cta_click", { page: "homepage" });
// },
// },
// beforeDestroy() {
// this.$absmartly.finalize();
// },
// };
// </script>
// main.js - Initialize the SDK as a Vue plugin
import { createApp } from "vue";
import App from "./App.vue";
import absmartly from "@absmartly/vue3-sdk";
const app = createApp(App);
app.use(absmartly.ABSmartlyVue, {
sdkOptions: {
endpoint: "https://your-company.absmartly.io/v1",
apiKey: "YOUR-API-KEY",
environment: "production",
application: "website",
},
context: {
units: { user_id: "user-12345" },
},
attributes: {
user_agent: navigator.userAgent,
},
});
app.mount("#app");
// In your component, use treatments and track goals:
//
// <template>
// <div>
// <treatment name="homepage_banner_experiment">
// <template #A> <!-- Variant A (control) -->
// <banner text="Welcome back!" />
// </template>
// <template #B> <!-- Variant B -->
// <banner text="Welcome back, we have new deals for you!" />
// </template>
// </treatment>
//
// <button @click="trackClick">Get Started</button>
// </div>
// </template>
//
// <script>
// export default {
// methods: {
// trackClick() {
// this.$absmartly.track("cta_click", { page: "homepage" });
// },
// },
// beforeUnmount() {
// this.$absmartly.finalize();
// },
// };
// </script>
import com.absmartly.sdk.*;
import java.util.Map;
public class ExperimentExample {
public static void main(String[] args) {
// Initialize the SDK
final ClientConfig clientConfig = ClientConfig.create()
.setEndpoint("https://your-company.absmartly.io/v1")
.setAPIKey("YOUR-API-KEY")
.setApplication("website")
.setEnvironment("production");
final Client client = Client.create(clientConfig);
final ABSmartlyConfig config = ABSmartlyConfig.create()
.setClient(client);
final ABSmartly sdk = ABSmartly.create(config);
// Create a context for this user
final ContextConfig contextConfig = ContextConfig.create()
.setUnit("user_id", "user-12345");
try (final Context context = sdk.createContext(contextConfig)
.waitUntilReady()) {
// Check which variant the user is in
if (context.getTreatment("homepage_banner_experiment") == 1) {
// Variant B: show a personalized banner
showBanner("Welcome back, we have new deals for you!");
} else {
// Variant A (control): show the existing banner
showBanner("Welcome back!");
}
// Use a variable set in the Web Console for more flexibility
String buttonColor = context.getVariableValue("button.color", "blue");
setButtonColor(buttonColor);
// Track when the user completes a key action
context.track("cta_click", Map.of("page", "homepage"));
// Track a purchase with revenue data
context.track("purchase", Map.of(
"revenue", 49.99,
"item_count", 3
));
}
}
}
package main
import (
"fmt"
"os"
absmartly "github.com/absmartly/go-sdk"
)
func main() {
// Initialize the SDK
clientConfig := absmartly.ClientConfig{
Endpoint_: "https://your-company.absmartly.io/v1",
ApiKey_: os.Getenv("ABSMARTLY_APIKEY"),
Application_: "website",
Environment_: "production",
}
sdkConfig := absmartly.ABSmartlyConfig{
Client_: absmartly.CreateDefaultClient(clientConfig),
}
sdk := absmartly.Create(sdkConfig)
// Create a context for this user
contextConfig := absmartly.ContextConfig{
Units_: map[string]string{
"user_id": "user-12345",
},
}
ctx := sdk.CreateContext(contextConfig)
ctx.WaitUntilReady()
// Check which variant the user is in
treatment, err := ctx.GetTreatment("homepage_banner_experiment")
if err != nil {
fmt.Println("Error getting treatment:", err)
return
}
if treatment == 1 {
// Variant B: show a personalized banner
showBanner("Welcome back, we have new deals for you!")
} else {
// Variant A (control): show the existing banner
showBanner("Welcome back!")
}
// Use a variable set in the Web Console for more flexibility
buttonColor, err := ctx.GetVariableValue("button.color", "blue")
if err != nil {
fmt.Println("Error getting variable:", err)
return
}
setButtonColor(buttonColor)
// Track when the user completes a key action
ctx.Track("cta_click", map[string]interface{}{
"page": "homepage",
})
// Track a purchase with revenue data
ctx.Track("purchase", map[string]interface{}{
"revenue": 49.99,
"item_count": 3,
})
// Close the context to flush remaining events
ctx.Close()
}
using ABSmartly;
using Microsoft.Extensions.DependencyInjection;
// Initialize the SDK
var serviceProvider = new ServiceCollection()
.AddHttpClient()
.BuildServiceProvider();
var httpClientFactory = serviceProvider
.GetRequiredService<IHttpClientFactory>();
var abSdk = new ABSdk(
new ABSdkHttpClientFactory(httpClientFactory),
new ABSmartlyServiceConfiguration
{
Environment = "production",
Application = "website",
Endpoint = "https://your-company.absmartly.io/v1",
ApiKey = "YOUR-API-KEY"
});
// Create a context for this user
var config = new ContextConfig()
.SetUnit("user_id", "user-12345");
// Using the disposable pattern ensures events are flushed on close
using var context = abSdk.CreateContext(config);
await context.WaitUntilReady();
// Check which variant the user is in
if (context.GetTreatment("homepage_banner_experiment") == 1)
{
// Variant B: show a personalized banner
ShowBanner("Welcome back, we have new deals for you!");
}
else
{
// Variant A (control): show the existing banner
ShowBanner("Welcome back!");
}
// Use a variable set in the Web Console for more flexibility
var buttonColor = context.GetVariableValue("button.color", "blue");
SetButtonColor(buttonColor);
// Track when the user completes a key action
context.Track("cta_click", new Dictionary<string, object>
{
{ "page", "homepage" }
});
// Track a purchase with revenue data
context.Track("purchase", new Dictionary<string, object>
{
{ "revenue", 49.99 },
{ "item_count", 3 }
});
// Context is automatically closed and flushed by the using statement
<?php
use \ABSmartly\SDK\SDK;
use \ABSmartly\SDK\Context\ContextConfig;
// Initialize the SDK
$sdk = SDK::createWithDefaults(
endpoint: 'https://your-company.absmartly.io/v1',
apiKey: 'YOUR-API-KEY',
environment: 'production',
application: 'website',
);
// Create a context for this user
$contextConfig = new ContextConfig();
$contextConfig->setUnit('user_id', 'user-12345');
$context = $sdk->createContext($contextConfig);
// Check which variant the user is in
$treatment = $context->getTreatment('homepage_banner_experiment');
if ($treatment === 1) {
// Variant B: show a personalized banner
showBanner('Welcome back, we have new deals for you!');
} else {
// Variant A (control): show the existing banner
showBanner('Welcome back!');
}
// Use a variable set in the Web Console for more flexibility
$buttonColor = $context->getVariableValue('button.color', 'blue');
setButtonColor($buttonColor);
// Track when the user completes a key action
$context->track('cta_click', (object) ['page' => 'homepage']);
// Track a purchase with revenue data
$context->track('purchase', (object) [
'revenue' => 49.99,
'item_count' => 3,
]);
// Close the context to flush remaining events
$context->close();
require "absmartly"
# Initialize the SDK
Absmartly.configure_client do |config|
config.endpoint = "https://your-company.absmartly.io/v1"
config.api_key = "YOUR-API-KEY"
config.application = "website"
config.environment = "production"
end
# Create a context for this user
context_config = Absmartly.create_context_config
context_config.units = { user_id: "user-12345" }
context = Absmartly.create_context(context_config)
context.wait_until_ready
# Check which variant the user is in
treatment = context.treatment("homepage_banner_experiment")
if treatment == 1
# Variant B: show a personalized banner
show_banner("Welcome back, we have new deals for you!")
else
# Variant A (control): show the existing banner
show_banner("Welcome back!")
end
# Use a variable set in the Web Console for more flexibility
button_color = context.variable_value("button.color", "blue")
set_button_color(button_color)
# Track when the user completes a key action
context.track("cta_click", { page: "homepage" })
# Track a purchase with revenue data
context.track("purchase", {
revenue: 49.99,
item_count: 3,
})
# Close the context to flush remaining events
context.close
import 'package:absmartly_sdk/absmartly_sdk.dart';
void main() async {
// Initialize the SDK
final ClientConfig clientConfig = ClientConfig()
..setEndpoint("https://your-company.absmartly.io/v1")
..setAPIKey("YOUR-API-KEY")
..setApplication("website")
..setEnvironment("production");
final ABSmartly sdk = ABSmartly(
ABSmartlyConfig.create()
.setClient(Client.create(clientConfig)),
);
// Create a context for this user
final ContextConfig contextConfig = ContextConfig.create()
.setUnit("user_id", "user-12345");
final Context context = await sdk
.createContext(contextConfig)
.waitUntilReady();
// Check which variant the user is in
final int treatment =
await context.getTreatment("homepage_banner_experiment");
if (treatment == 1) {
// Variant B: show a personalized banner
showBanner("Welcome back, we have new deals for you!");
} else {
// Variant A (control): show the existing banner
showBanner("Welcome back!");
}
// Use a variable set in the Web Console for more flexibility
final String buttonColor =
await context.getVariableValue("button.color", "blue");
setButtonColor(buttonColor);
// Track when the user completes a key action
context.track("cta_click", {"page": "homepage"});
// Track a purchase with revenue data
context.track("purchase", {
"revenue": 49.99,
"item_count": 3,
});
// Close the context to flush remaining events
await context.close();
}
Next steps
You now have everything you need to run a basic experiment. When you're ready to go deeper:
- Managing the Context Lifecycle covers when to close contexts, refresh experiment data, and flush events.
- Pre-Fetching Context Data shows how to fetch experiment data on the server and pass it to the client to avoid flickering.
- Targeting Users and Controlling Assignments shows how to pass user attributes, use custom assignments, and override variants during QA.
- Checking Variants Without Triggering Exposures explains peeking, which is useful for pre-loading assets or debugging.