スキル一覧に戻る
JDerekLomas

upgrade-integration

by JDerekLomas

Hosted multi-tenant A/B testing platform for EdTech, built on Carnegie Learning's UpGrade

0🍴 0📅 2026年1月9日
GitHubで見るManusで実行

SKILL.md


name: upgrade-integration description: 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. allowed-tools: Read, Write, Edit, Bash, WebFetch, Glob, Grep

UpGrade A/B Testing Integration for EdTech

You are helping integrate 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

# JavaScript/TypeScript
npm install upgrade_client_lib

# Java (Maven)
<dependency>
  <groupId>com.carnegielearning</groupId>
  <artifactId>upgrade-client</artifactId>
</dependency>

Core Integration Pattern

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

ModeUse CaseRequires init()?
StandardPre-registered users with stored groupsYes
EphemeralRuntime-provided groups, no DB lookupNo
MergedCombine session + stored groupsYes

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                          │
│     (Hosted: upgrade-hosting | Self-hosted | Carnegie)      │
└─────────────────────────────────────────────────────────────┘

Deployment Options

OptionBest ForSetup
Hosted PlatformMost EdTech apps, quick startGet API key, point SDK
Self-hostedFull control, on-prem requirementsDeploy UpGrade yourself
Carnegie LearningEnterprise, research partnershipsContact Carnegie

The easiest way to get started. See the live demo.

import UpgradeClient from 'upgrade_client_lib/dist/browser';

const client = new UpgradeClient(
  userId,
  'https://api.upgrade-hosting.com/v1',  // Hosted platform
  'your-app-context'
);

// Add your API key from the dashboard
client.setCustomHeaders({
  'X-API-Key': 'upg_live_your_key_here'
});

await client.init({
  schoolId: 'lincoln-elementary',
  classId: 'math-301',
  teacherId: 'ms-rodriguez'
});

Features of hosted platform:

  • Multi-tenant isolation: Each district/organization gets isolated database
  • No infrastructure: We manage UpGrade backend, you focus on your app
  • Dashboard: Manage experiments, API keys, view results
  • FERPA-ready: District-level data isolation for compliance

CRITICAL: Known Pitfalls

Before writing ANY integration code, read resources/pitfalls-and-edge-cases.md. The most dangerous issues:

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

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

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

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

PatternExampleAssignment Unit
UI VariantNew vs old problem interfaceIndividual
PedagogicalWorked examples vs practice problemsClassroom
Adaptive AlgorithmMastery threshold 80% vs 90%Individual
Content OrderingTeach fractions before decimals vs afterSchool
Feedback TimingImmediate vs delayed feedbackClassroom

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

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

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 SDK

スコア

総合スコア

50/100

リポジトリの品質指標に基づく評価

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

0/10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

レビュー

💬

レビュー機能は近日公開予定です