Moodle Plugin Architecture

Moodle Activity Module Development, Explained Properly

A custom activity module (mod_*) is the right build when a workflow needs real gradebook, completion, and backup/restore integration inside a course — not something a block, local plugin, or generic content type can fake. Here's how it actually works, callback by callback.

8+ Years Building on MoodleMoodle 4.x & 5.xGradebook & Completion Ready
mod_pluginname Directory Structure

When Existing Activities and Content Types Aren't Enough

Core Moodle activities, H5P, and LTI content types cover most course needs. But when a workflow needs its own database structure, its own grading logic, or teacher tools that don't exist anywhere else, teams often force the closest existing activity to do the job — and end up fighting its assumptions at every step instead of building the activity the workflow actually needs.

Wrong Plugin Type Forced to Fit

Course-embedded, gradable functionality bolted onto a block or local plugin that was never built to hold gradebook or completion hooks.

H5P/LTI Stretched Too Far

Content types pushed into multi-stage workflows or custom data models they were never designed to express.

No Backup/Restore Support

Custom activity data that silently disappears on course backup, import, or migration because the backup classes were never built.

Activity Module vs. Local Plugin, Block, H5P, and LTI

An activity module is the heaviest of Moodle's plugin types for a reason — it's the only one built specifically for course-embedded, gradable, backed-up content.

A Moodle activity module (frankenstyle prefix mod_, living in /mod/pluginname) is what a teacher adds directly into a course section as a new activity, exactly like Assignment, Quiz, or Forum. It gets its own course-module instance per placement, its own database tables, direct gradebook integration, completion tracking, and — critically — first-class support in Moodle's backup and restore engine. A local plugin or block can display information or run logic, but neither has course-module instances or native gradebook hooks; forcing gradable, course-embedded functionality into either means reimplementing pieces of the module API badly, by hand.

H5P and LTI content types are often the faster, correct answer — H5P for self-contained interactive content, LTI for launching an external tool with grade passback. A custom activity module earns its cost when the workflow needs a data model or teacher-facing logic those formats can't express: multi-stage submission and review flows, custom reporting tied to your own database tables, or grading rules more specific than points and scales.

The Files Every Activity Module Actually Needs

Moodle's module API expects a specific set of callbacks and files — miss one and the activity either won't appear in "Add an activity" or won't behave correctly once added.

mod_form.php

Defines the activity's settings form using Moodle's moodleform library — name, description, grading options, availability, and any custom fields your activity needs.

lib.php

Holds the required callback functions Moodle core calls directly: <modname>_add_instance(), <modname>_update_instance(), <modname>_delete_instance(), plus optional hooks like <modname>_supports() and navigation callbacks.

view.php

The main student- and teacher-facing page for one instance of the activity, responsible for loading the course-module context and rendering the activity's actual content.

db/install.xml + version.php

Same schema-definition and versioning pattern as any other plugin type, plus the activity-specific requirement that at least one instance table exists to hold per-activity data.

backup/moodle2/

backup_<modname>_activity_task.class.php and restore_<modname>_activity_task.class.php, which teach Moodle's backup engine how to package and rebuild this activity's data.

lang/en/<modname>.php

Every label, setting name, and capability string the activity shows, including the required modulename and pluginname entries Moodle looks up when listing activity types.

What lib.php Actually Has to Implement

Moodle core calls a small set of functions in lib.php directly by name, matched against the module's frankenstyle name — this is what makes the module discoverable and functional at all. <modname>_add_instance($data) runs when a teacher first adds the activity to a course, inserting the instance record and returning its ID. <modname>_update_instance($data) runs on every settings edit. <modname>_delete_instance($id) handles cleanup, including any grade items and files tied to that instance, when the activity is removed. <modname>_supports($feature) declares which core features the module participates in — FEATURE_GRADE_HAS_GRADE, FEATURE_COMPLETION_TRACKING, FEATURE_BACKUP_MOODLE2, and others — and is what tells Moodle's course page, gradebook, and backup engine whether to even look for the rest of this integration in the first place.

Gradebook, Completion, Calendar, and Backup/Restore

These four integrations are what separate a real activity module from a page that merely looks like one inside a course.

Gradebook Integration

grade_update() in lib.php pushes scores into Moodle's gradebook through the Grade API, and <modname>_grade_item_update() defines how the activity's grade item is configured — points, scale, or none.

Completion Tracking

Activities declare support for completion via <modname>_supports(FEATURE_COMPLETION_TRACKING), then either let Moodle track manual/automatic completion or implement custom completion conditions the activity itself controls.

Calendar Integration

Optional <modname>_core_calendar_provide_event_action() and related callbacks let an activity's due dates or events appear correctly on the Moodle calendar and in the "This week" / timeline views.

Backup & Restore

Without correct backup/restore classes, an activity's data silently doesn't survive a course backup, a course import, or a Moodle site migration — one of the most common gaps in half-finished custom modules.

Activity Modules Built to Moodle's Own Module API

Real mod_* Architecture, Not a Workaround

Every activity module we build uses Moodle's actual module API — proper lib.php callbacks, grade hooks, and backup/restore — not a block or local plugin stretched to look like an activity.

Gradebook & Completion That Actually Work

Grades post correctly, completion tracks correctly, and the activity survives a course backup — the three things half-finished custom modules usually get wrong.

8+ Years of Moodle Core Experience

We've built and reviewed activity modules across dozens of Moodle installs, so we know exactly where the module API's edge cases live.

You Own the Code

Your activity module's full source lives on your Moodle installation. Nothing rented, nothing locked behind an ongoing license with us.

Got Questions About Moodle Activity Modules?

Straight answers to what comes up most when planning a custom activity module build.

An activity module is a mod_* plugin type that adds a new kind of course activity — something a teacher can add to a course section, that gets its own course-module instance, and that students interact with directly, like Assignment or Forum in core Moodle. It's the plugin type built specifically to support gradebook, completion, and backup/restore for course content.

A local plugin handles cross-cutting logic that isn't tied to a course, and a block is a small widget in a sidebar region — neither has course-module instances, gradebook hooks, or backup/restore support. An activity module is specifically built for content students engage with inside a course and that a teacher may need to grade.

At minimum, <modname>_add_instance(), <modname>_update_instance(), and <modname>_delete_instance() — Moodle calls these directly when a teacher adds, edits, or removes an instance of your activity from a course. Most real modules also implement <modname>_supports() to declare feature support like grading and completion.

Yes — that's done through the Grade API. <modname>_grade_item_update() defines the grade item (points, scale, or none) when an instance is created or updated, and grade_update() pushes actual scores into it as students complete the activity.

Only if you build it to — this is one of the most commonly skipped pieces. It requires backup_<modname>_activity_task.class.php and restore_<modname>_activity_task.class.php under backup/moodle2/, which teach Moodle's backup engine how to package and rebuild the activity's data during a course backup, import, or site migration.

H5P and LTI are the right call when an existing content type already covers what you need — interactive video, external tool launches, and so on. A custom activity module is the right call when you need first-class Moodle gradebook and completion integration, custom database structures specific to your workflow, or behavior H5P/LTI simply can't express, like multi-stage teacher workflows tied to course roles and capabilities.

It depends heavily on gradebook and completion complexity, but a focused custom activity module — settings form, core CRUD, grading, and backup/restore — typically runs several weeks of development plus a testing pass across roles and Moodle versions before it's ready for a live course.

Need a Custom Activity Module Built Right?

Tell us about the workflow your course needs and we'll scope an activity module built against Moodle's real module API — grading, completion, and backup included.

Talk to a Moodle Developer