On this page

Canvas LMS

Canvas LMS Integration

Install the NotAI Pixel on Canvas LMS by uploading a small JavaScript snippet in the Canvas Theme Editor. One upload covers every page in your Canvas instance, including assignments, quizzes, discussions, and SpeedGrader. If you need detection limited to specific courses rather than the whole instance, see Course scoping. This guide is for Canvas administrators; instructors do not need to do anything.

Overview

This page covers the Canvas-specific install of the universal NotAI Pixel. The pixel installs anywhere; Canvas has its own install shape because the Theme Editor accepts JavaScript file uploads rather than raw HTML, so the pixel is attached via a small DOM-injection snippet instead of a <script> tag. The runtime behavior is identical to any other install.

Once the theme upload is live, the pixel observes behavioral signals on every Canvas page and reports them to your NotAI dashboard. Reviewer features that attribute sessions to specific students are included with academic plans and are configured from inside your dashboard once the pixel is reporting. See Reviewer features. For procurement, student privacy terms live in the Data Processing Agreement and the NY Ed Law 2-d notice.

Requirements

  • Canvas admin access. You need account-level admin to upload a custom theme JavaScript file.
  • NotAI account and integration ID. Create an account to get your 8-character integration ID from the dashboard.
  • An academic plan, if you want the reviewer features (authorship orbs and session replay tied to specific students). See academic pricing.

Supported Canvas versions

  • Canvas Cloud (Instructure-hosted)
  • Canvas Self-Hosted (all versions currently supported by Instructure)
Note: Canvas Free for Teachers does not support custom theme JavaScript, so the pixel install is not available on free-tier accounts.

Installation

Install the NotAI Pixel by uploading a theme JavaScript file in the Canvas Theme Editor. This works for both Canvas Cloud and self-hosted instances.

Step 1: Open the Theme Editor

  1. Log in to Canvas as an administrator.
  2. Navigate to Admin → [Your Account] → Themes.
  3. Select your active theme, or create a new one that inherits from it.
  4. Click Open in Theme Editor.

Step 2: Upload the NotAI theme JavaScript

In the Theme Editor, open the Upload tab and upload a JavaScript file with the following contents. Canvas serves this file on every page, so the pixel attaches automatically.

notai.js
// NotAI pixel for Canvas LMS
(function() {
  const s = document.createElement('script');
  s.src = 'https://cdn.isnotai.com/api.js';
  s.async = true;
  s.setAttribute('data-key', 'a7f3c2e1');
  document.head.appendChild(s);
})();

Replace a7f3c2e1 with your 8-character integration ID from the NotAI dashboard, and add your Canvas domain (for example, yourschool.instructure.com) to the authorized origins list under Settings → Authorized Origins.

Step 3: Save and apply the theme

  1. Click Save Theme.
  2. Click Apply Theme to activate the changes across your Canvas instance.
  3. Open any Canvas page. The pixel begins reporting within seconds.
Propagation: Theme changes can take a few minutes to reach every Canvas page. If you do not see sessions in your NotAI dashboard immediately, wait a few minutes and reload.

Configuration

The Canvas install accepts the same configuration as the universal pixel. Use setAttribute for the short attributes; pass a data-config JSON string for anything else.

Short attributes

Attribute Default Description
data-key Required Your 8-character integration ID.
data-region us Reporting region. us or eu. Must match the region configured for your account.
data-text absent Presence-only. When set, enables text monitoring in observe mode.
data-courses absent Comma-separated Canvas course IDs. When set, the pixel runs only inside those courses. See Course scoping.
data-exclude-courses absent Comma-separated Canvas course IDs. When set, the pixel runs everywhere except those courses. See Course scoping.

JSON configuration

For everything else, set data-config to a JSON string. Use this when you need to set sampleRate, customize the text monitor editor allowlist, or pass any other option beyond the short attributes above.

notai.js
(function() {
  const s = document.createElement('script');
  s.src = 'https://cdn.isnotai.com/api.js';
  s.async = true;
  s.setAttribute('data-config', JSON.stringify({
    integrationId: 'a7f3c2e1',
    region: 'us',
    sampleRate: 1.0
  }));
  document.head.appendChild(s);
})();

See the pixel configuration reference for the full list of JSON keys.

Course scoping

A theme upload applies to your whole Canvas instance, so by default the pixel runs on every page. Course scoping narrows that to the courses you choose, which is useful for pilots, for a single department, or for honoring an opt-out. Scope with an allowlist or a blocklist, whichever expresses fewer IDs.

Course IDs are the numbers Canvas puts in course URLs. The course at https://yourschool.instructure.com/courses/1470 has the ID 1470.

Allowlist: run only in these courses

notai.js
(function() {
  const s = document.createElement('script');
  s.src = 'https://cdn.isnotai.com/api.js';
  s.async = true;
  s.setAttribute('data-key', 'a7f3c2e1');
  s.setAttribute('data-courses', '1470,1471,1509');
  document.head.appendChild(s);
})();

The pixel initializes on pages belonging to courses 1470, 1471, and 1509, and does nothing anywhere else in Canvas.

Blocklist: run everywhere except these courses

notai.js
(function() {
  const s = document.createElement('script');
  s.src = 'https://cdn.isnotai.com/api.js';
  s.async = true;
  s.setAttribute('data-key', 'a7f3c2e1');
  s.setAttribute('data-exclude-courses', '2201');
  document.head.appendChild(s);
})();

The pixel initializes everywhere in your instance except pages belonging to course 2201.

JSON form

Both lists are also available as data-config keys, where they take an array of course IDs. Use this form when you are already passing other JSON options.

notai.js
s.setAttribute('data-config', JSON.stringify({
  integrationId: 'a7f3c2e1',
  region: 'us',
  courses: [1470, 1471, 1509]
}));

IDs may be numbers or strings; both forms match the same course. If you set both an attribute and its JSON key, the attribute wins.

Use Canvas course IDs, not SIS codes. A course ID is the number in the course URL. A course code such as MATH-101 is not a course ID and will never match a page. If any entry in your list is not a course ID, the pixel treats the whole list as a configuration error and does not start, rather than quietly ignoring that entry: a blocklist with one bad entry would otherwise keep monitoring the course you meant to exclude. The same applies to a list longer than 512 courses. Blank entries and a trailing comma are fine.
Use one list, not both. courses and excludeCourses are mutually exclusive. Setting both is a configuration error, and the pixel will not start anywhere until you remove one. The same applies to data-courses and data-exclude-courses, in any combination.

How a page's course is determined

The pixel reads the course from the /courses/{id} segment of the page URL whenever it is present, including sub-path installs such as /lms/courses/1470/assignments/9. For the few course pages whose URL does not carry that segment, it falls back to the course Canvas publishes in the page environment.

Canvas moves between sections without reloading the page, so the pixel re-checks the scope on each of those in-page navigations as well as on page load. If a navigation lands on a course outside your scope, the pixel shuts itself down: it sends the data it collected while it was in scope, then removes every listener and stops. It stays stopped until the next full page load, so returning to an in-scope course in the same page view will not restart it. This is deliberate: it errs toward not running, at the cost of occasionally missing a course you scoped it into.

Pages that are not part of a course

Canvas has many pages with no course context: the dashboard, account and admin pages, the calendar, and the inbox. Scoping treats them as follows.

Page With an allowlist With a blocklist
Page in a listed course Runs Does not run
Page in an unlisted course Does not run Runs
Page with no course (dashboard, account, calendar, inbox) Does not run Runs
Course page where the course cannot be determined Does not run Runs

An allowlist is a statement about which courses to monitor, so it never runs outside them. A blocklist is a statement about which courses to leave alone, so it runs anywhere it has not been told to stop. Both rules hold even when the course cannot be identified, and that last row is where the two differ in a way worth knowing.

Choosing between them. On a page whose course cannot be identified, an allowlist does not run and a blocklist does. So an allowlist is the stricter choice: it can only ever collect from courses you named. A blocklist is the more convenient choice for excluding a handful of courses from an otherwise instance-wide deployment, but it cannot promise that an excluded course is never observed, because a page of that course whose ID the pixel cannot determine is not recognizably excluded. If you need a hard guarantee that specific courses are never monitored, express it as an allowlist of the courses that may be.
What "does not run" means: the pixel stops before it creates a session, stores anything in the browser, attaches any listener, or contacts NotAI. A scoped-out page produces no data at all.

Verifying your scope

Load each page below fresh, by pasting its URL into the address bar or reloading, rather than clicking through Canvas. Clicking through uses the in-page navigation described above, which means leaving a monitored course shuts the pixel down for the rest of that page view and sends one final batch on the way out. Both are correct, and both will make a working configuration look wrong if you are watching the Network tab while browsing.

  1. Load a page inside a course that should be monitored. In Developer Tools, on the Network tab, confirm requests to your reporting host appear.
  2. Load a page in a course that should not be monitored. Confirm no reporting requests are made.
  3. Load a non-course page such as the dashboard. What to expect depends on which list you set: with an allowlist there should be no requests, and with a blocklist there should be, because the dashboard is not in an excluded course. Check this against the table above rather than assuming silence means success.
  4. In your NotAI dashboard, check that new sessions carry only the courses you scoped to.

If every page stops reporting after you add scoping, check that you have not set both lists, and that the list you set contains at least one valid numeric course ID. Both are configuration errors that stop the pixel everywhere by design, so a mistake fails toward collecting nothing rather than collecting too much.

Text monitoring

Text monitoring captures typing behavior inside Canvas editors (assignment submissions, discussion posts, quiz essay responses) to classify authorship at the session level. It is off by default. Enable it with either data-text or the JSON equivalent.

notai.js
(function() {
  const s = document.createElement('script');
  s.src = 'https://cdn.isnotai.com/api.js';
  s.async = true;
  s.setAttribute('data-key', 'a7f3c2e1');
  s.setAttribute('data-text', '');
  document.head.appendChild(s);
})();

The default editor allowlist covers Canvas's Rich Content Editor (RCE) and the standard form surfaces. If your instance uses a custom editor plugin, pass extraSelectors via data-config. See the pixel text monitoring reference.

Reviewer features

The pixel install above is all you need to detect AI agents and bots at the session level. Reviewer features (authorship orbs tied to specific students, full session replay for suspected essays, and the instructor-facing reviewer UI inside your NotAI dashboard) are included with academic plans. On those plans, verdicts flow to the Canvas gradebook and the reviewer UI, so instructors meet the evidence where they grade.

Setup is guided from your NotAI dashboard's admin area. The theme file above needs no changes, and there is no shared secret or endpoint to manage. Attribution relies on identity fields your institution chooses to provide, listed in the Data Processing Agreement.

For tiers and eligibility, see academic pricing.

Testing

Verify the install after applying the theme.

Confirm the script loads

  1. Open any Canvas page in your browser.
  2. Open Developer Tools (F12 or Cmd+Option+I) and select the Network tab.
  3. Filter by cdn.isnotai.com.
  4. Confirm api.js loads with a 200 status.

Confirm sessions reach your dashboard

  1. Log in to your NotAI dashboard.
  2. Navigate to Sessions.
  3. Look for sessions with a hostname that matches your Canvas domain (for example, yourschool.instructure.com).

Sessions appear within seconds of the first signal. If you do not see any, check the Troubleshooting section.

Dashboard

All Canvas sessions surface in the NotAI dashboard alongside sessions from any other integration. Each session carries a verdict (Clean, Suspicious, or Bot) and the signal evidence behind it. On academic plans, reviewer features add authorship orbs and session replay inside the dashboard itself.

Session data is also available through the Customer Data API, documented at /developers.

Content Security Policy

Canvas does not set a default Content Security Policy that blocks the NotAI Pixel. If your institution has added a custom CSP at a proxy or WAF in front of Canvas, allow the script host and the reporting host for your region.

United States

Header
Content-Security-Policy:
  script-src 'self' https://cdn.isnotai.com;
  connect-src 'self' https://chl.isnot.ai wss://chl.isnot.ai;

European Union

Header
Content-Security-Policy:
  script-src 'self' https://cdn.isnotai.com;
  connect-src 'self' https://chl-eu.isnot.ai wss://chl-eu.isnot.ai;

Only the reporting host differs between regions. Both regions use the same script host.

Troubleshooting

Pixel does not load

  • Confirm data-key matches the integration ID from your NotAI dashboard exactly.
  • Confirm your Canvas domain (for example, yourschool.instructure.com) is on the authorized origins list for your integration. Add origins from Settings → Authorized Origins in your dashboard. Requests from origins outside the list are rejected.
  • Confirm the theme is saved and applied. Saving without applying will not propagate the upload.
  • Clear your browser cache and reload.
  • Check the browser console for CSP violations.

Pixel loads but no sessions appear

  • Confirm data-region matches the region configured for your account.
  • If you set sampleRate, confirm it is high enough that sessions are not being dropped on the client.
  • Confirm the dashboard is filtered to the correct integration.

Theme changes not appearing

  • Ensure you clicked both Save Theme and Apply Theme.
  • Wait a few minutes for changes to propagate.
  • View the page in an incognito window to bypass browser caching.
  • Check that no other theme is overriding the one you edited.

False positives

  • Users with assistive technology can produce patterns that overlap with automation.
  • Remote desktop sessions can surface bot-like pointer traces.
  • Review ambiguous sessions in the dashboard before taking action.

Performance

  • The script loads asynchronously and does not block Canvas page rendering.
  • Use sampleRate only if necessary on high-volume instances. Sampling hides sessions from detection entirely; it does not sub-sample a session.

Still stuck? Support usually replies within a business day.

Contact support

Ready to install on Canvas?

Create an account, grab your integration ID, and upload one theme file. Reviewer features come with academic plans.