upgrade-integration
Integrate Carnegie Learning's UpGrade A/B testing platform into LMS and EdTech applications. Guides setup of decision points, experiment conditions, LTI/xAPI integration, and outcome logging. Use when asked to add A/B testing, experiments, or feature flags to educational software.
Best use case
upgrade-integration is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Integrate Carnegie Learning's UpGrade A/B testing platform into LMS and EdTech applications. Guides setup of decision points, experiment conditions, LTI/xAPI integration, and outcome logging. Use when asked to add A/B testing, experiments, or feature flags to educational software.
Teams using upgrade-integration should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/upgrade-integration/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How upgrade-integration Compares
| Feature / Agent | upgrade-integration | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Integrate Carnegie Learning's UpGrade A/B testing platform into LMS and EdTech applications. Guides setup of decision points, experiment conditions, LTI/xAPI integration, and outcome logging. Use when asked to add A/B testing, experiments, or feature flags to educational software.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# UpGrade A/B Testing Integration for EdTech
You are helping integrate [UpGrade](https://github.com/CarnegieLearningWeb/UpGrade), Carnegie Learning's open-source A/B testing platform designed specifically for educational technology.
## When This Skill Applies
- Adding A/B testing or experiments to educational apps
- Integrating feature flags in learning platforms
- Connecting EdTech apps to LMS via LTI with experiment support
- Setting up learning analytics with xAPI + experimentation
- Debugging experiment assignment issues
## Critical Context
UpGrade is NOT a generic A/B testing tool. It's designed for education with features like:
- **Group-level assignment** (whole classrooms get same condition)
- **Consistency rules** (students don't get re-randomized)
- **Educational context metadata** (grade, subject, proficiency)
**ALWAYS** ask these questions before implementing:
1. What's the assignment unit? (Individual student vs classroom vs school)
2. What happens if a student changes classes mid-experiment?
3. How will teachers access both conditions (or will they)?
4. Is the app used in LMS iframes? (Cookie issues!)
## Quick Reference
### Installation
```bash
# JavaScript/TypeScript
npm install upgrade_client_lib
# Java (Maven)
<dependency>
<groupId>com.carnegielearning</groupId>
<artifactId>upgrade-client</artifactId>
</dependency>
```
### Core Integration Pattern
```typescript
import UpgradeClient from 'upgrade_client_lib/dist/browser';
import { MARKED_DECISION_POINT_STATUS } from 'upgrade_client_lib';
// 1. Initialize (MUST complete before getDecisionPointAssignment)
const client = new UpgradeClient(userId, hostUrl, context);
await client.init(groupData, workingGroupData);
// 2. Get assignment at decision point
const assignment = await client.getDecisionPointAssignment('feature_name', 'target');
const condition = assignment.getCondition();
const payload = assignment.getPayload();
// 3. Mark that condition was applied
client.markDecisionPoint('feature_name', MARKED_DECISION_POINT_STATUS.CONDITION_APPLIED);
// 4. Log outcomes
client.log('score', 85);
client.log('completion_time_ms', 45000);
```
### Three SDK Modes
| Mode | Use Case | Requires init()? |
|------|----------|------------------|
| **Standard** | Pre-registered users with stored groups | Yes |
| **Ephemeral** | Runtime-provided groups, no DB lookup | No |
| **Merged** | Combine session + stored groups | Yes |
## Integration Architecture
```
┌─────────────────────────────────────────────────────────────┐
│ LMS │
│ (Canvas, Moodle, etc.) │
└─────────────────────┬───────────────────────────────────────┘
│ LTI 1.3 Launch
│ (user_id, context_id, roles)
▼
┌─────────────────────────────────────────────────────────────┐
│ Your EdTech App │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Identity Mapper │ │
│ │ LTI user_id → UpGrade userId + altUserIds │ │
│ └─────────────────────┬───────────────────────────────┘ │
│ │ │
│ ┌─────────────────────▼───────────────────────────────┐ │
│ │ UpGrade SDK │ │
│ │ - init(groupData) │ │
│ │ - getDecisionPointAssignment() │ │
│ │ - markDecisionPoint() │ │
│ │ - log() │ │
│ └─────────────────────┬───────────────────────────────┘ │
└─────────────────────────┼───────────────────────────────────┘
│ HTTPS
▼
┌─────────────────────────────────────────────────────────────┐
│ UpGrade Backend │
│ (Self-hosted or Carnegie Learning) │
└─────────────────────────────────────────────────────────────┘
```
## CRITICAL: Known Pitfalls
Before writing ANY integration code, read `resources/pitfalls-and-edge-cases.md`. The most dangerous issues:
### 1. Third-Party Cookie Blocking (CRITICAL)
If your app runs in an LMS iframe, Safari and Chrome WILL block your session cookies by default.
**Symptoms:**
- User gets re-randomized on every page load
- `init()` seems to work but assignments are inconsistent
- Works in development, fails in production LMS
**Solutions:**
- Set `SameSite=None; Secure` on all cookies
- Use localStorage with user-provided identifier (not session-based)
- Consider opening in new window instead of iframe
### 2. Race Condition: init() vs getDecisionPointAssignment()
```typescript
// WRONG - race condition
const client = new UpgradeClient(userId, hostUrl, context);
client.init(groupData); // async, not awaited!
const assignment = await client.getDecisionPointAssignment('feature');
// assignment may be NO_CONDITION_ASSIGNED
```
```typescript
// CORRECT
const client = new UpgradeClient(userId, hostUrl, context);
await client.init(groupData); // AWAIT this!
const assignment = await client.getDecisionPointAssignment('feature');
```
### 3. LTI Identity Mismatch
LTI provides `user_id` which is opaque and LMS-specific. Your app may use email or internal IDs.
```typescript
// Map all identities together
await client.init(groupData);
client.setAltUserIds([
ltiUserId, // from LTI launch
userEmail, // from your auth
internalDatabaseId // your user table PK
]);
```
### 4. Group Assignment Drift
Student transfers from Mrs. Smith's class (Treatment A) to Mr. Jones' class (Treatment B).
**Default behavior:** Student KEEPS original assignment (consistency rule)
**Problem:** Student now sees different UI than classmates, causing confusion.
**Solution:** Decide upfront:
- Accept drift (experimental purity)
- Re-assign on class change (classroom consistency)
- Exclude transferred students from analysis
### 5. Shared Device / Chromebook Cart Problem
```typescript
// WRONG - userId persists from previous student
const client = new UpgradeClient(getUserIdFromLocalStorage(), ...);
// CORRECT - validate identity on each session
const client = new UpgradeClient(getCurrentAuthenticatedUserId(), ...);
// Clear any cached assignments if userId changed
```
## Decision Point Patterns for Education
See `resources/decision-point-patterns.md` for detailed examples:
| Pattern | Example | Assignment Unit |
|---------|---------|-----------------|
| **UI Variant** | New vs old problem interface | Individual |
| **Pedagogical** | Worked examples vs practice problems | Classroom |
| **Adaptive Algorithm** | Mastery threshold 80% vs 90% | Individual |
| **Content Ordering** | Teach fractions before decimals vs after | School |
| **Feedback Timing** | Immediate vs delayed feedback | Classroom |
## Code Templates
See `templates/` directory for:
- `react-hook.tsx` - React hook with proper error handling
- `nextjs-middleware.ts` - Next.js API route pattern
- `vanilla-js.js` - Framework-agnostic implementation
- `lti-launch-handler.ts` - LTI 1.3 launch with UpGrade init
## Logging Best Practices
```typescript
// DO: Use consistent types
client.log('score', 85); // number
client.log('completed', true); // boolean
client.log('response', 'correct'); // string
// DON'T: Mix types for same metric
client.log('score', 85);
client.log('score', '85'); // String! Will corrupt analysis
// DON'T: Log before marking decision point
client.log('score', 85); // Not associated with condition!
client.markDecisionPoint('quiz', MARKED_DECISION_POINT_STATUS.CONDITION_APPLIED);
// DO: Mark first, then log
client.markDecisionPoint('quiz', MARKED_DECISION_POINT_STATUS.CONDITION_APPLIED);
client.log('score', 85); // Correctly associated
```
## Troubleshooting Decision Tree
```
Assignment returns NO_CONDITION_ASSIGNED
├── Did you await init()?
│ └── No → Add await before init()
├── Is experiment in ENROLLING state?
│ └── No → Check UpGrade UI, start experiment
├── Does user match segment criteria?
│ └── No → Check inclusion/exclusion rules
├── Is context correct?
│ └── No → Verify context string matches experiment config
└── Check network tab for failed requests
```
```
User gets different condition than classmates
├── Is assignment unit set to GROUP?
│ └── No → Change to GROUP in experiment settings
├── Was groupData provided to init()?
│ └── No → Pass { classId: 'xxx' } to init()
├── Did student join after experiment started?
│ └── Yes → Check POST_EXPERIMENT_RULE
└── Is student in multiple groups?
└── Yes → Check group priority/override logic
```
## External Resources
- [UpGrade GitHub](https://github.com/CarnegieLearningWeb/UpGrade)
- [UpGrade Documentation](https://upgrade-platform.gitbook.io/docs/)
- [JavaScript SDK](https://github.com/CarnegieLearningWeb/UpGrade/tree/develop/clientlibs/js)
- [LTI 1.3 Spec](https://www.imsglobal.org/spec/lti/v1p3)
- [xAPI Spec](https://xapi.com/overview/)
## When to Escalate
Recommend the developer contact UpGrade support or file a GitHub issue if:
- Assignment algorithm seems incorrect (statistical anomaly)
- Data export shows impossible values
- Backend returns 5xx errors consistently
- Need custom consistency rules not supported by SDKRelated Skills
upgrade-stripe
Guide for upgrading Stripe API versions and SDKs
tipalti-integration-specialist
Tipalti payment integration guide for payee onboarding, payment processing, webhooks, and tax compliance. Use when implementing payment features.
testcontainers-integration-tests
Use when integration tests require real infrastructure (database, message queue, cache) or when mocking infrastructure is insufficient. Defines container lifecycle, test isolation, and performance optimization for Testcontainers-based testing.
stripe-integration
Guides consistent, correct implementation of Stripe payment processing including payment flows, webhooks, subscriptions, and customer management. Use when integrating Stripe payments, setting up subscriptions, implementing webhooks, or managing customer billing.
orama-integration
Use when integrating with Orama. Links to official docs for search, indexing, answer engine. (project)
moai-context7-lang-integration
Enterprise-grade Context7 MCP integration patterns for language-specific documentation access with real-time library resolution and intelligent caching
MCP Integration
Model Context Protocol (MCP) integration specialist. Use when creating MCP server configurations, implementing MCP integrations, or optimizing MCP performance. Specializes in MCP server architecture and integration patterns.
mapbox-integration-patterns
Official integration patterns for Mapbox GL JS across popular web frameworks. Covers setup, lifecycle management, token handling, search integration, and common pitfalls. Based on Mapbox's create-web-app scaffolding tool.
lsp-integration
This skill should be used when the user asks to "add LSP server", "configure language server", "set up LSP in plugin", "add code intelligence", "integrate language server protocol", "use pyright-lsp", "use typescript-lsp", "use rust-lsp", "socket transport", "initializationOptions", mentions LSP servers, or discusses extensionToLanguage mappings. Provides guidance for integrating Language Server Protocol servers into Claude Code plugins for enhanced code intelligence.
kuroco-frontend-integration
Kurocoとフロントエンドフレームワークの統合パターンおよびAI自動デプロイメント。使用キーワード:「Kuroco Nuxt」「Kuroco Next.js」「フロントエンド連携」「Nuxt3」「Nuxt2」「App Router」「Pages Router」「SSG」「SSR」「静的生成」「コンテンツ表示」「ログイン実装」「会員登録」「signup」「KurocoPages」「フロントエンド環境構築」「Vue」「React」「useAsyncData」「$fetch」「asyncData」「composable」「useAuth」「認証状態」「プロフィール取得」「profile」「generateStaticParams」「動的ルート」「v-html」「dangerouslySetInnerHTML」「XSS対策」「サードパーティCookie」「credentials include」「AI自動デプロイ」「Kuroco自動化」「サイト登録API」「自動ビルド」「自動デプロイ」「temp-upload」「presigned URL」「S3アップロード」「artifact_url」「KurocoFront」「プレビューデプロイ」「stage_url」「add_site」「site_key」「kuroco_front/deploy」「CI/CD」「フロントエンドビルド」「ZIP配備」「自動公開」「nuxt generate」「next build」「vite build」「デプロイAPI」「一時アップロード」「署名付きURL」。Nuxt/Next.jsでのKuroco連携、認証実装、SSG/SSR設定、AI自動デプロイに関する質問で使用。
java-21-to-java-25-upgrade
Comprehensive best practices for adopting new Java 25 features since the release of Java 21. Triggers on: ['*']
integration
Backend-Frontend integration patterns expert. Type-safe API contracts with Pydantic-Zod validation sync (Python FastAPI) or Prisma-TypeScript native (Next.js). Shadcn forms connected to backend, error handling, loading states. Use when creating full-stack features.