Skip to main content

Getting Started

By the end of this document, you should have an understanding of how to integrate any of the Campfire SDK flows into your application, and be able to send messages and receive events from your chosen flow.

Choosing an import method

The Campfire SDK is available on NPM, which provides a variety of ways to integrate into your application. The package is available under @campfirelearning/lti-tool-consumer

Via <script />

The SDK can be imported via script tag using a service called unpkg. This will expose the SDK via window.CampfireSDK. If you are in a traditional HTML/JS environment, this is the way to go. Our JS SDK is available at the following URL:

https://unpkg.com/@campfirelearning/sdk-lti[@version]/dist/browser/index.js
note

Omitting @version in the URL above will cause Unpkg to always resolve to the latest version of the SDK. In production, we recommend that you specify a version to ensure that you do not introduce unexpected breaking changes in a newer SDK version.

<!DOCTYPE html>
<html lang="en">
<head>
<script
src="https://unpkg.com/@campfirelearning/sdk-lti/dist/browser/index.js"
>
</head>
<body>
<!-- ... -->
<script>
const service = new window.CampfireSDK.ItemEditor(/* ... */)
</script>
</body>
</html>

Via Package Manager

The SDK is also available directly via NPM, and can be imported. If you are using a framework like React, use this. This method also includes types if you are using Typescript.

// package.json
{
//...
dependencies: {
"@campfirelearning/lti-tool-consumer": "0.6.0"
}
}
import { ItemEditor} from "@campfirelearning/lti-tool-consumer"

export const initializeCampfireItemEditor = (/* ... */) => {
const service = new ItemEditor(/* ... */)
return service
}

🔒 Authenticating

The Campfire SDK uses LTI Authentication. At its core, this method uses a shared application key/secret to sign the parameters we use when launching our application inside of the iframe. The shared secret must NEVER be shared with the browser as it can authorize the creation of new users/content/etc. into the target workspace.

You must implement a mechanism on your server to approve every user launch request. Failing to properly check the launch parameters WILL lead to users having access to content they should not have access to. Please read through LTI Authentication and Authorization to ensure you have covered your bases

🚀 Launching your first experience

Simply instantiate one of our SDK classes (ex: CampfireSDK.ExamEditor) with the proper user data and credentials, then mount it to an iframe.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>My First Campfire Application</title>
</head>

<body>
<div id="app">
<!-- Where the UI will load -->
<iframe id="tool" name="tool"></iframe>
</div>

<script>
// Step 1: Gather user data (from your server)
const user = {
email: "john.deaux@example.com",
firstName: "Jonathon"
lastName: "Deaux",
roles: "Instructor"
}
const APP_ID = "THE_DISTRICT_APP_KEY"

// Step 2: Instantiate
const service = new window.CampfireSDK.ExamEditor({
params: {
oauth_consumer_key: APP_ID,
resource_link_id: "0",
user_id: user.email,
lis_person_contact_email_primary: user.email,
lis_person_name_given: user.firstName,
lis_person_name_family: user.lastName,
lis_person_name_full: `${user.firstName} ${user.lastName}`,
roles: user.roles
},
signingFunction: /* ... */
});

// Step 3: Mount
consumer.mount("tool").then(() => {
console.log("Mounted!");
})
</script>
</body>
</html>

⬅️ Listening for Events

Each Campfire experience emits events that allow you to respond to happenings inside of them. Events are emitted via the instantiated class and can be listened to using addEventListener.

const service = new window.CampfireSDK.ExamEditor( {/* ... */ } )

service.addEventListener("message", (message) => {
if ( message.data.name === "examCreated" ) {
// do something
}
})

For a list of currently supported events, see Components.

Listening to unsupported events.

Our SDK components may fire events we consider to be unsupported. Either they aren’t officially part of the SDK spec yet, or they’re being deprecated. In either case, if you wish to listen for these unsupported events use the message:unhandled message type.

const service = new window.CampfireSDK.ExamEditor( {/* ... */ } )
service.addEventListener("message:unhandled", (message) => {
// do something
})

➡️ Sending Messages to SDK

Send information into the Campfire experience using sendMessage.

const service = new window.CampfireSDK.ExamEditor( {/* ... */ } )

/* ... */

service.sendMessage({
type: "message",
name: "setGuidedExamFormData",
data: {
fields: [
{ field: "exam:title", value: "My exam!" }
]
}
})

For a list of currently supported messages, see Components

Full Example

You can copy and paste this into any code sandbox that runs HTML to launch our Item Editor component after replacing the CONSUMER_KEY and SHARED_SECRET with your actual credentials.

<!DOCTYPE html>
<html>
<head>
<title>Campfire LTI Integration</title>
<link rel="stylesheet"
href="https://unpkg.com/modern-normalize@2.0.0/modern-normalize.css" />
<style type="text/css">
iframe {
width: 100%;
height: 90vh;
border: 1px solid #999;
}
div#app {
margin: 0 2rem;
}
</style>
<script
src="https://unpkg.com/@campfirelearning/sdk-lti@latest/dist/browser/index.js"></script>
<script
src="https://unpkg.com/@campfirelearning/sdk-lti-oauth@latest/dist/browser/index.js"></script>
</head>
<body>
<div id="app">
<h1>Campfire &#128293; SDK Integration</h1>
<iframe id="tool" name="tool"></iframe>
</div>
<script>
const CONSUMER_KEY = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
const SHARED_SECRET = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
const component = new CampfireSDK.ExamEditor({
params: {
oauth_consumer_key: CONSUMER_KEY,
lti_version: "LTI-1p0",
lti_message_type: "basic-lti-launch-request",
tool_consumer_info_product_family_code: "examspark",
tool_consumer_info_version: "cloud",
tool_consumer_instance_name: "cloud",
resource_link_id: "0",
user_id: "kevin@examspark.com",
lis_person_contact_email_primary: "kevin@examspark.com",
lis_person_name_given: "Kevin",
lis_person_name_family: "Campbell",
lis_person_name_full: "Kevin Campbell",
roles: [
"Instructor",
"urn:lti:instrole:ims/lis/Administrator",
"urn:lti:sysrole:ims/lis/SysAdmin",
].join(","),
},
signingFunction: (launchUrl) => CampfireOAuth.getUnsafeOauthSigningFunction({
launchUrl: launchUrl,
secretKey: SHARED_SECRET,
}),
});
component.mount("tool").then(() => {
console.log("Mounted!");
});

const debug = (message) => {
console.debug(message.type, ": ", message.data);
if (message.data?.type === "event" && message.data.name === "launched") {
options?.onLaunch?.();
}
};

component.addEventListener("message", debug);
component.addEventListener("message:unhandled", debug);

</script>
</body>
</html>