diff --git a/step/createbackup/classes/privacy/provider.php b/step/createbackup/classes/privacy/provider.php
new file mode 100644
index 0000000000000000000000000000000000000000..306f0a8242c9769c5ffb306dbee6b4a748986655
--- /dev/null
+++ b/step/createbackup/classes/privacy/provider.php
@@ -0,0 +1,40 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace lifecyclestep_createbackup\privacy;
+
+use core_privacy\local\metadata\null_provider;
+
+/**
+ * Privacy subsystem implementation for lifecyclestep_createbackup.
+ *
+ * @package     lifecyclestep_createbackup
+ * @copyright   2022 ISB Bayern
+ * @author      Philipp Memmel
+ * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class provider implements null_provider {
+
+    /**
+     * Get the language string identifier with the component's language
+     * file to explain why this plugin stores no data.
+     *
+     * @return string the reason
+     */
+    public static function get_reason() : string {
+        return 'privacy:metadata';
+    }
+}
diff --git a/step/createbackup/lang/de/lifecyclestep_createbackup.php b/step/createbackup/lang/de/lifecyclestep_createbackup.php
index f767e9f0666fdbe4a8157da24dde1ca0788dfc85..12cc46d483d6d9b27aeb859c763b4ad99ca8fd25 100644
--- a/step/createbackup/lang/de/lifecyclestep_createbackup.php
+++ b/step/createbackup/lang/de/lifecyclestep_createbackup.php
@@ -23,5 +23,6 @@
  */
 
 $string['pluginname'] = 'Kurssicherungs-Schritt';
+$string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.';
 
 $string['maximumbackupspercron'] = 'Maximale Anzahl an Sicherungen per cron';
diff --git a/step/createbackup/lang/en/lifecyclestep_createbackup.php b/step/createbackup/lang/en/lifecyclestep_createbackup.php
index 7f811a5cd8e279a9c9817fef846f008522f37e3f..693e7fa6c791e6b248896432d7d36f3794f82487 100644
--- a/step/createbackup/lang/en/lifecyclestep_createbackup.php
+++ b/step/createbackup/lang/en/lifecyclestep_createbackup.php
@@ -23,5 +23,6 @@
  */
 
 $string['pluginname'] = 'Create backup step';
+$string['privacy:metadata'] = 'This subplugin does not store any personal data.';
 
 $string['maximumbackupspercron'] = 'Maximum number of backups per cron';
diff --git a/step/deletecourse/classes/privacy/provider.php b/step/deletecourse/classes/privacy/provider.php
new file mode 100644
index 0000000000000000000000000000000000000000..6ab29e62de88cb6552b1aca96ef7eb7d68093dde
--- /dev/null
+++ b/step/deletecourse/classes/privacy/provider.php
@@ -0,0 +1,40 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace lifecyclestep_deletecourse\privacy;
+
+use core_privacy\local\metadata\null_provider;
+
+/**
+ * Privacy subsystem implementation for lifecyclestep_deletecourse.
+ *
+ * @package     lifecyclestep_deletecourse
+ * @copyright   2022 ISB Bayern
+ * @author      Philipp Memmel
+ * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class provider implements null_provider {
+
+    /**
+     * Get the language string identifier with the component's language
+     * file to explain why this plugin stores no data.
+     *
+     * @return string the reason
+     */
+    public static function get_reason() : string {
+        return 'privacy:metadata';
+    }
+}
diff --git a/step/deletecourse/lang/de/lifecyclestep_deletecourse.php b/step/deletecourse/lang/de/lifecyclestep_deletecourse.php
index 7b38ae14f7f0f27abd3238bec3becc1234d9ffbb..62c1f8fdc2047cc4a060fe4f0d27efab99a23077 100644
--- a/step/deletecourse/lang/de/lifecyclestep_deletecourse.php
+++ b/step/deletecourse/lang/de/lifecyclestep_deletecourse.php
@@ -23,5 +23,6 @@
  */
 
 $string['pluginname'] = 'Kurslöschen-Schritt';
+$string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.';
 
 $string['deletecourse_maximumdeletionspercron'] = 'Maximale Anzahl an Kurslöschungen per cron';
diff --git a/step/deletecourse/lang/en/lifecyclestep_deletecourse.php b/step/deletecourse/lang/en/lifecyclestep_deletecourse.php
index 1246a2e9451bf07bfb9fd5c73720466adcae3815..5e6f337fc9c6f7f7541a706ee6c17a4e7dc8f35a 100644
--- a/step/deletecourse/lang/en/lifecyclestep_deletecourse.php
+++ b/step/deletecourse/lang/en/lifecyclestep_deletecourse.php
@@ -23,5 +23,6 @@
  */
 
 $string['pluginname'] = 'Delete course step';
+$string['privacy:metadata'] = 'This subplugin does not store any personal data.';
 
 $string['deletecourse_maximumdeletionspercron'] = 'Maximum number of courses deleted per cron';
diff --git a/step/duplicate/classes/privacy/provider.php b/step/duplicate/classes/privacy/provider.php
new file mode 100644
index 0000000000000000000000000000000000000000..136ee7cacfe34f430a6abcbd12052865fa666886
--- /dev/null
+++ b/step/duplicate/classes/privacy/provider.php
@@ -0,0 +1,40 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace lifecyclestep_duplicate\privacy;
+
+use core_privacy\local\metadata\null_provider;
+
+/**
+ * Privacy subsystem implementation for lifecyclestep_duplicate.
+ *
+ * @package     lifecyclestep_duplicate
+ * @copyright   2022 ISB Bayern
+ * @author      Philipp Memmel
+ * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class provider implements null_provider {
+
+    /**
+     * Get the language string identifier with the component's language
+     * file to explain why this plugin stores no data.
+     *
+     * @return string the reason
+     */
+    public static function get_reason() : string {
+        return 'privacy:metadata';
+    }
+}
diff --git a/step/duplicate/lang/de/lifecyclestep_duplicate.php b/step/duplicate/lang/de/lifecyclestep_duplicate.php
index 1ba8f7c1da8398ca2cd171980de41c356291125d..39f01957766c1f106aea2fd21a5f95ea26b7dd9a 100644
--- a/step/duplicate/lang/de/lifecyclestep_duplicate.php
+++ b/step/duplicate/lang/de/lifecyclestep_duplicate.php
@@ -23,6 +23,7 @@
  */
 
 $string['pluginname'] = 'Kurs-Duplizieren-Schritt';
+$string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.';
 
 $string['duplicate_form'] = 'Daten eingeben';
 
diff --git a/step/duplicate/lang/en/lifecyclestep_duplicate.php b/step/duplicate/lang/en/lifecyclestep_duplicate.php
index 4639947599ce16c11da31cdd520f9a2d7a9951c0..b71b5a1519ba529be82d4fa1777b582817356540 100644
--- a/step/duplicate/lang/en/lifecyclestep_duplicate.php
+++ b/step/duplicate/lang/en/lifecyclestep_duplicate.php
@@ -23,6 +23,7 @@
  */
 
 $string['pluginname'] = 'Duplicate step';
+$string['privacy:metadata'] = 'This subplugin does not store any personal data.';
 
 $string['duplicate_form'] = 'Enter data';
 
diff --git a/step/email/classes/privacy/provider.php b/step/email/classes/privacy/provider.php
new file mode 100644
index 0000000000000000000000000000000000000000..afbcb51137b4f75466b4fdd053aa7f486071be6b
--- /dev/null
+++ b/step/email/classes/privacy/provider.php
@@ -0,0 +1,173 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace lifecyclestep_email\privacy;
+
+use context;
+use context_course;
+use context_system;
+use core_privacy\local\metadata\collection;
+use core_privacy\local\request\approved_contextlist;
+use core_privacy\local\request\approved_userlist;
+use core_privacy\local\request\contextlist;
+use core_privacy\local\request\core_userlist_provider;
+use core_privacy\local\request\userlist;
+use core_privacy\local\request\writer;
+use dml_exception;
+
+/**
+ * Privacy provider for lifecyclestep_email.
+ *
+ * @package    lifecyclestep_email
+ * @copyright  2022 ISB Bayern
+ * @author     Philipp Memmel
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class provider implements \core_privacy\local\metadata\provider,
+    \core_privacy\local\request\plugin\provider,
+    core_userlist_provider {
+
+    /**
+     * Returns metadata about lifecyclestep_email.
+     *
+     * @param collection $collection The initialised collection to add items to.
+     * @return collection A listing of user data stored by lifecyclestep_email.
+     */
+    public static function get_metadata(collection $collection): collection {
+        $collection->add_database_table(
+            'lifecyclestep_email',
+            [
+                'touser' => 'privacy:metadata:lifecyclestep_email:touser',
+                'courseid' => 'privacy:metadata:lifecyclestep_email:courseid',
+                'instanceid' => 'privacy:metadata:lifecyclestep_email:instanceid'
+            ],
+            'privacy:metadata:lifecyclestep_email:summary'
+        );
+        return $collection;
+    }
+
+    /**
+     * Get the list of contexts that contain user information for the specified user.
+     *
+     * @param int $userid The user to search.
+     * @return contextlist $contextlist The contextlist containing the list of contexts used
+     */
+    public static function get_contexts_for_userid(int $userid): contextlist {
+        $contextlist = new contextlist();
+        $contextlist->add_system_context();
+
+        $sql = "SELECT c.id FROM {context} c JOIN {lifecyclestep_email} e ON c.instanceid = e.courseid "
+            . "WHERE contextlevel = :coursecontextlevel "
+            . "AND e.touser = :touser";
+        $contextlist->add_from_sql($sql, ['coursecontextlevel' => CONTEXT_COURSE, 'touser' => $userid]);
+        return $contextlist;
+    }
+
+    /**
+     * Export all user data for the specified user, in the specified contexts.
+     *
+     * @param approved_contextlist $contextlist The approved contexts to export information for
+     * @throws dml_exception
+     */
+    public static function export_user_data(approved_contextlist $contextlist): void {
+        global $DB;
+
+        foreach ($contextlist->get_contexts() as $context) {
+            if ($context instanceof context_system) {
+                $records = $DB->get_records('lifecyclestep_email', ['touser' => $contextlist->get_user()->id]);
+                $writer = writer::with_context($context);
+                foreach ($records as $record) {
+                    $subcontext = ['lifecyclestep_email-' . $record->id];
+                    $writer->export_data($subcontext, $record);
+                }
+            } else if ($context instanceof context_course) {
+                $records = $DB->get_records('lifecyclestep_email',
+                    ['courseid' => $context->instanceid, 'touser' => $contextlist->get_user()->id]);
+                $writer = writer::with_context($context);
+                foreach ($records as $record) {
+                    $subcontext = ['lifecyclestep_email-' . $record->id];
+                    $writer->export_data($subcontext, $record);
+                }
+            }
+        }
+    }
+
+    /**
+     * Get the list of users who have data within a context.
+     *
+     * @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
+     */
+    public static function get_users_in_context(userlist $userlist): void {
+        if ($userlist->get_context() instanceof context_system) {
+            $sql = "SELECT touser FROM {lifecyclestep_email}";
+            $userlist->add_from_sql('touser', $sql, []);
+        } else if ($userlist->get_context() instanceof context_course) {
+            $sql = "SELECT touser FROM {lifecyclestep_email} WHERE courseid = :courseid";
+            $userlist->add_from_sql('touser', $sql, ['courseid' => $userlist->get_context()->instanceid]);
+        }
+    }
+
+    /**
+     * Delete data of multiple users within a single context.
+     *
+     * @param approved_userlist $userlist The approved context and user information to delete information for.
+     * @throws dml_exception
+     */
+    public static function delete_data_for_users(approved_userlist $userlist): void {
+        global $DB;
+        foreach ($userlist->get_userids() as $userid) {
+            if ($userlist->get_context() instanceof context_system) {
+                $DB->delete_records('lifecyclestep_email', ['touser' => $userid]);
+            } else if ($userlist->get_context() instanceof context_course) {
+                $DB->delete_records('lifecyclestep_email', ['touser' => $userid,
+                    'courseid' => $userlist->get_context()->instanceid]);
+            }
+        }
+    }
+
+    /**
+     * Delete all data for all users in the specified context.
+     *
+     * @param context $context The specific context to delete data for.
+     * @throws dml_exception
+     */
+    public static function delete_data_for_all_users_in_context(context $context): void {
+        global $DB;
+        if ($context instanceof context_system) {
+            $DB->delete_records('lifecyclestep_email');
+        } else if ($context instanceof context_course) {
+            $DB->delete_records('lifecyclestep_email', ['courseid' => $context->instanceid]);
+        }
+    }
+
+    /**
+     * Delete all user data for the specified user, in the specified contexts.
+     *
+     * @param approved_contextlist $contextlist The approved contexts and user information to delete information for
+     * @throws dml_exception
+     */
+    public static function delete_data_for_user(approved_contextlist $contextlist): void {
+        global $DB;
+        $user = $contextlist->get_user();
+        foreach ($contextlist as $context) {
+            if ($context instanceof context_system) {
+                $DB->delete_records('lifecyclestep_email', ['touser' => $user->id]);
+            } else if ($context instanceof context_course) {
+                $DB->delete_records('lifecyclestep_email', ['touser' => $user->id, 'courseid' => $context->instanceid]);
+            }
+        }
+    }
+}
diff --git a/step/email/lang/de/lifecyclestep_email.php b/step/email/lang/de/lifecyclestep_email.php
index 2a6c2a269aa1ba773d5bcf6cc7a13ef3a41010ae..82e8115c7830245677e99c26c1cc910e9ccc9af7 100644
--- a/step/email/lang/de/lifecyclestep_email.php
+++ b/step/email/lang/de/lifecyclestep_email.php
@@ -49,3 +49,8 @@ $string['email:preventdeletion'] = 'Löschen verhindern';
 $string['keep_course'] = 'Kurs behalten';
 $string['status_message_requiresattention'] = 'Kurs ist zum Löschen vorgemerkt';
 $string['action_prevented_deletion'] = '{$a} verhinderte Löschung';
+
+$string['privacy:metadata:lifecyclestep_email:courseid'] = 'Die ID des Kurses, zu dem E-Mail-Benachrichtigungen versandt werden';
+$string['privacy:metadata:lifecyclestep_email:instanceid'] = 'Die ID der Schritt-Instanz, der E-Mails verschickt';
+$string['privacy:metadata:lifecyclestep_email:summary'] = 'Informationen, welche Benutzer per E-Mail benachrichtigt werden';
+$string['privacy:metadata:lifecyclestep_email:touser'] = 'Die ID des Benutzers, an den eine E-Mail verschickt wird';
diff --git a/step/email/lang/en/lifecyclestep_email.php b/step/email/lang/en/lifecyclestep_email.php
index 15a77d5ccc7ccef5b1d08c046cd93cac7fbf4857..a4d064430395514b8489154443575ca2a8bcc1df 100644
--- a/step/email/lang/en/lifecyclestep_email.php
+++ b/step/email/lang/en/lifecyclestep_email.php
@@ -49,3 +49,8 @@ $string['email:preventdeletion'] = 'Prevent deletion';
 $string['keep_course'] = 'Keep course';
 $string['status_message_requiresattention'] = 'Course is marked for deletion';
 $string['action_prevented_deletion'] = '{$a} prevented deletion';
+
+$string['privacy:metadata:lifecyclestep_email:courseid'] = 'ID of the course, emails will be sent for';
+$string['privacy:metadata:lifecyclestep_email:instanceid'] = 'ID of the step instance sending emails';
+$string['privacy:metadata:lifecyclestep_email:summary'] = 'Information about whhich users will be informed by email';
+$string['privacy:metadata:lifecyclestep_email:touser'] = 'ID of the user who is being notified via email';
diff --git a/step/email/tests/privacy/provider_test.php b/step/email/tests/privacy/provider_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..37e3afa7f2079cd1f694bd9c6d01fb4cbd8b4316
--- /dev/null
+++ b/step/email/tests/privacy/provider_test.php
@@ -0,0 +1,292 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+/**
+ * Unit tests for the lifecyclestep_email implementation of the privacy API.
+ *
+ * @package    lifecyclestep_email
+ * @copyright  2022 ISB Bayern
+ * @author     Philipp Memmel
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+namespace lifecyclestep_email\privacy;
+
+use context_course;
+use context_system;
+use core_privacy\local\request\approved_contextlist;
+use core_privacy\local\request\approved_userlist;
+use core_privacy\local\request\userlist;
+use core_privacy\local\request\writer;
+use core_privacy\tests\provider_testcase;
+use dml_exception;
+use stdClass;
+use tool_lifecycle\local\entity\step_subplugin;
+use tool_lifecycle\local\manager\step_manager;
+use tool_lifecycle\local\manager\workflow_manager;
+
+/**
+ * Unit tests for the lifecyclestep_email implementation of the privacy API.
+ *
+ * @package    lifecyclestep_email
+ * @copyright  2022 ISB Bayern
+ * @author     Philipp Memmel
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class provider_test extends provider_testcase {
+
+    /**
+     * Basic setup for the provider tests.
+     *
+     * @return void
+     * @throws dml_exception
+     */
+    public function setUp(): void {
+        global $DB;
+        $this->resetAfterTest();
+        $this->user1 = $this->getDataGenerator()->create_user();
+        $this->user2 = $this->getDataGenerator()->create_user();
+        $this->user3 = $this->getDataGenerator()->create_user();
+
+        $this->course1 = $this->getDataGenerator()->create_course();
+        $this->course2 = $this->getDataGenerator()->create_course();
+        $this->course3 = $this->getDataGenerator()->create_course();
+
+        // Create a lifecycle email step.
+        $testworkflow = workflow_manager::create_workflow('testworkflow');
+        $step = new step_subplugin('test email', 'email', $testworkflow->id);
+        step_manager::insert_or_update($step);
+
+        // Add some entries.
+        $record = new stdClass();
+        $record->touser = $this->user1->id;
+        $record->courseid = $this->course1->id;
+        $record->instanceid = $step->id;
+        $DB->insert_record('lifecyclestep_email', $record);
+
+        $record = new stdClass();
+        $record->touser = $this->user1->id;
+        $record->courseid = $this->course2->id;
+        $record->instanceid = $step->id;
+        $DB->insert_record('lifecyclestep_email', $record);
+
+        $record = new stdClass();
+        $record->touser = $this->user2->id;
+        $record->courseid = $this->course1->id;
+        $record->instanceid = $step->id;
+        $DB->insert_record('lifecyclestep_email', $record);
+
+        $record = new stdClass();
+        $record->touser = $this->user2->id;
+        $record->courseid = $this->course2->id;
+        $record->instanceid = $step->id;
+        $DB->insert_record('lifecyclestep_email', $record);
+
+        $record = new stdClass();
+        $record->touser = $this->user2->id;
+        $record->courseid = $this->course3->id;
+        $record->instanceid = $step->id;
+        $DB->insert_record('lifecyclestep_email', $record);
+
+        $record = new stdClass();
+        $record->touser = $this->user3->id;
+        $record->courseid = $this->course3->id;
+        $record->instanceid = $step->id;
+        $DB->insert_record('lifecyclestep_email', $record);
+        // We now have 6 entries in the table, 2 for user1, 3 for user2 and 1 for user3.
+    }
+
+    /**
+     * Tests \block_lifecyclealert\privacy\provider::get_contexts_for_userid.
+     *
+     * @covers \lifecyclestep_email\privacy\provider::get_contexts_for_userid
+     */
+    public function test_get_contexts_for_userid(): void {
+        $contextlist = provider::get_contexts_for_userid($this->user1->id);
+        $this->assertEquals(3, $contextlist->count());
+        $this->assertTrue(in_array(context_system::instance(), $contextlist->get_contexts()));
+        $this->assertTrue(in_array(context_course::instance($this->course1->id), $contextlist->get_contexts()));
+        $this->assertTrue(in_array(context_course::instance($this->course2->id), $contextlist->get_contexts()));
+    }
+
+    /**
+     * Tests \lifecyclestep_email\privacy\provider::export_user_data.
+     *
+     * @covers \lifecyclestep_email\privacy\provider::export_user_data
+     * @return void
+     * @throws dml_exception
+     */
+    public function test_export_user_data(): void {
+        global $DB;
+        $course1context = context_course::instance($this->course1->id);
+        $course2context = context_course::instance($this->course2->id);
+        $approvedcontextlist = new approved_contextlist($this->user1, 'lifecyclestep_email',
+            [context_system::instance()->id, $course1context->id, $course2context->id]);
+        provider::export_user_data($approvedcontextlist);
+        $writer = writer::with_context(context_system::instance());
+        $this->assertTrue($writer->has_any_data());
+        $recordids = $DB->get_records('lifecyclestep_email', ['touser' => $this->user1->id], '', 'id');
+        foreach ($recordids as $id) {
+            $exportedrecord = $writer->get_data(['lifecyclestep_email-' . $id->id]);
+            $this->assertEquals($this->user1->id, $exportedrecord->touser);
+            $this->assertTrue(in_array($exportedrecord->courseid, [$this->course1->id, $this->course2->id]));
+        }
+
+        $writer = writer::with_context($course1context);
+        $this->assertTrue($writer->has_any_data());
+        $recordids = $DB->get_records('lifecyclestep_email', ['touser' => $this->user1->id,
+            'courseid' => $this->course1->id], '', 'id');
+        foreach ($recordids as $id) {
+            $exportedrecord = $writer->get_data(['lifecyclestep_email-' . $id->id]);
+            $this->assertEquals($this->user1->id, $exportedrecord->touser);
+            $this->assertEquals($exportedrecord->courseid, $this->course1->id);
+        }
+
+        $writer = writer::with_context($course2context);
+        $this->assertTrue($writer->has_any_data());
+        $recordids = $DB->get_records('lifecyclestep_email', ['touser' => $this->user1->id,
+            'courseid' => $this->course2->id], '', 'id');
+        foreach ($recordids as $id) {
+            $exportedrecord = $writer->get_data(['lifecyclestep_email-' . $id->id]);
+            $this->assertEquals($this->user1->id, $exportedrecord->touser);
+            $this->assertEquals($exportedrecord->courseid, $this->course2->id);
+        }
+    }
+
+    /**
+     * Tests \lifecyclestep_email\privacy\provider::get_users_in_context.
+     *
+     * @covers \lifecyclestep_email\privacy\provider::get_users_in_context
+     * @return void
+     * @throws dml_exception
+     */
+    public function test_get_users_in_context(): void {
+        $userlist = new userlist(context_system::instance(), 'lifecyclestep_email');
+        provider::get_users_in_context($userlist);
+        $this->assertCount(3, $userlist->get_userids());
+
+        $userlist = new userlist(context_course::instance($this->course1->id), 'lifecyclestep_email');
+        provider::get_users_in_context($userlist);
+        $this->assertEquals(2, count($userlist->get_userids()));
+        $this->assertTrue(in_array($this->user1->id, $userlist->get_userids()));
+        $this->assertTrue(in_array($this->user2->id, $userlist->get_userids()));
+    }
+
+    /**
+     * Tests \lifecyclestep_email\privacy\provider::delete_data_for_users with system context.
+     *
+     * @covers \lifecyclestep_email\privacy\provider::delete_data_for_users
+     * @return void
+     * @throws dml_exception
+     */
+    public function test_delete_data_for_users() {
+        global $DB;
+        $approveduserlist = new approved_userlist(context_system::instance(), 'lifecyclestep_email',
+            [$this->user1->id, $this->user2->id]);
+        $this->assertEquals(6, count($DB->get_records('lifecyclestep_email')));
+        provider::delete_data_for_users($approveduserlist);
+        // Only user3 should be left.
+        $this->assertEquals(1, count($DB->get_records('lifecyclestep_email')));
+        foreach ($DB->get_records('lifecyclestep_email') as $record) {
+            // This should really only be one record.
+            $this->assertNotEquals($this->user1->id, $record->touser);
+            $this->assertNotEquals($this->user2->id, $record->touser);
+        }
+    }
+
+    /**
+     * Tests \lifecyclestep_email\privacy\provider::delete_data_for_users with a course context.
+     *
+     * @covers \lifecyclestep_email\privacy\provider::delete_data_for_users
+     * @return void
+     * @throws dml_exception
+     */
+    public function test_delete_data_for_users_coursecontext() {
+        global $DB;
+        $approveduserlist = new approved_userlist(context_course::instance($this->course1->id), 'lifecyclestep_email',
+            [$this->user1->id, $this->user2->id]);
+        $this->assertEquals(2, count($DB->get_records('lifecyclestep_email', ['courseid' => $this->course1->id])));
+        provider::delete_data_for_users($approveduserlist);
+        $this->assertEquals(0, count($DB->get_records('lifecyclestep_email', ['courseid' => $this->course1->id])));
+        // Other entries should still exist.
+        $this->assertEquals(4, count($DB->get_records('lifecyclestep_email')));
+    }
+
+    /**
+     * Tests \lifecyclestep_email\privacy\provider::delete_data_for_all_users_in_context.
+     *
+     * @covers \lifecyclestep_email\privacy\provider::delete_data_for_all_users_in_context
+     * @return void
+     * @throws dml_exception
+     */
+    public function test_delete_data_for_all_users_in_context(): void {
+        global $DB;
+        $this->assertEquals(6, count($DB->get_records('lifecyclestep_email')));
+        provider::delete_data_for_all_users_in_context(context_system::instance());
+        $this->assertEmpty($DB->get_records('lifecyclestep_email'));
+    }
+
+    /**
+     * Tests \lifecyclestep_email\privacy\provider::delete_data_for_all_users_in_context with a course context.
+     *
+     * @covers \lifecyclestep_email\privacy\provider::delete_data_for_all_users_in_context
+     * @return void
+     * @throws dml_exception
+     */
+    public function test_delete_data_for_all_users_in_context_coursecontext(): void {
+        global $DB;
+        $this->assertEquals(2, count($DB->get_records('lifecyclestep_email', ['courseid' => $this->course1->id])));
+        provider::delete_data_for_all_users_in_context(context_course::instance($this->course1->id));
+        $this->assertEmpty($DB->get_records('lifecyclestep_email', ['courseid' => $this->course1->id]));
+    }
+
+    /**
+     * Tests \lifecyclestep_email\privacy\provider::delete_data_for_user.
+     *
+     * @covers \lifecyclestep_email\privacy\provider::delete_data_for_user
+     * @return void
+     * @throws dml_exception
+     */
+    public function test_delete_data_for_user(): void {
+        global $DB;
+        $approvedcontextlist = new approved_contextlist($this->user2, 'lifecyclestep_email',
+            [context_system::instance()->id]);
+        $this->assertEquals(6, count($DB->get_records('lifecyclestep_email')));
+        provider::delete_data_for_user($approvedcontextlist);
+        $this->assertEquals(3, count($DB->get_records('lifecyclestep_email')));
+        foreach ($DB->get_records('lifecyclestep_email') as $record) {
+            // This should really only be one record.
+            $this->assertNotEquals($this->user2->id, $record->touser);
+        }
+    }
+
+    /**
+     * Tests \lifecyclestep_email\privacy\provider::delete_data_for_user.
+     *
+     * @covers \lifecyclestep_email\privacy\provider::delete_data_for_user
+     * @return void
+     * @throws dml_exception
+     */
+    public function test_delete_data_for_user_coursecontext(): void {
+        global $DB;
+        $approvedcontextlist = new approved_contextlist($this->user1, 'lifecyclestep_email',
+            [context_course::instance($this->course1->id)->id, context_course::instance($this->course2->id)->id]);
+        $this->assertEquals(6, count($DB->get_records('lifecyclestep_email')));
+        provider::delete_data_for_user($approvedcontextlist);
+        $this->assertEquals(0, count($DB->get_records('lifecyclestep_email',
+            ['courseid' => $this->course1->id, 'touser' => $this->user1->id])));
+        $this->assertEquals(0, count($DB->get_records('lifecyclestep_email',
+            ['courseid' => $this->course2->id, 'touser' => $this->user1->id])));
+    }
+}
diff --git a/trigger/categories/classes/privacy/provider.php b/trigger/categories/classes/privacy/provider.php
new file mode 100644
index 0000000000000000000000000000000000000000..19da3d64224c6260fe55a8f5ca4ba7ae6225c48c
--- /dev/null
+++ b/trigger/categories/classes/privacy/provider.php
@@ -0,0 +1,40 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace lifecycletrigger_categories\privacy;
+
+use core_privacy\local\metadata\null_provider;
+
+/**
+ * Privacy subsystem implementation for lifecycletrigger_categories.
+ *
+ * @package     lifecycletrigger_categories
+ * @copyright   2022 ISB Bayern
+ * @author      Philipp Memmel
+ * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class provider implements null_provider {
+
+    /**
+     * Get the language string identifier with the component's language
+     * file to explain why this plugin stores no data.
+     *
+     * @return string the reason
+     */
+    public static function get_reason() : string {
+        return 'privacy:metadata';
+    }
+}
diff --git a/trigger/categories/lang/de/lifecycletrigger_categories.php b/trigger/categories/lang/de/lifecycletrigger_categories.php
index 4711e721d139f5258636ec01062c9a57999fe45b..fcec1378ae44033d7c93995d6f1f76ce94cf3f0b 100644
--- a/trigger/categories/lang/de/lifecycletrigger_categories.php
+++ b/trigger/categories/lang/de/lifecycletrigger_categories.php
@@ -23,6 +23,7 @@
  */
 
 $string['pluginname'] = 'Kategorie-Trigger';
+$string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.';
 
 $string['categories'] = 'Kategorien, für die der Workflow ausgelöst werden soll.';
 $string['categories_noselection'] = 'Bitte wählen sie mindestens eine Kategorie aus.';
diff --git a/trigger/categories/lang/en/lifecycletrigger_categories.php b/trigger/categories/lang/en/lifecycletrigger_categories.php
index 178e0364791555d8dedf7079b0658b46ec3caa98..423bd48e4b62e0f037a4e19251d2e4be48f062cd 100644
--- a/trigger/categories/lang/en/lifecycletrigger_categories.php
+++ b/trigger/categories/lang/en/lifecycletrigger_categories.php
@@ -23,6 +23,7 @@
  */
 
 $string['pluginname'] = 'Categories trigger';
+$string['privacy:metadata'] = 'This subplugin does not store any personal data.';
 
 $string['categories'] = 'Categories, for which the workflow should be triggered';
 $string['categories_noselection'] = 'Please choose at least one category.';
diff --git a/trigger/delayedcourses/classes/privacy/provider.php b/trigger/delayedcourses/classes/privacy/provider.php
new file mode 100644
index 0000000000000000000000000000000000000000..2befaf3031d9226cf4f5738d7af99080dcf4f032
--- /dev/null
+++ b/trigger/delayedcourses/classes/privacy/provider.php
@@ -0,0 +1,40 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace lifecycletrigger_delayedcourses\privacy;
+
+use core_privacy\local\metadata\null_provider;
+
+/**
+ * Privacy subsystem implementation for lifecycletrigger_delayedcourses.
+ *
+ * @package     lifecycletrigger_delayedcourses
+ * @copyright   2022 ISB Bayern
+ * @author      Philipp Memmel
+ * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class provider implements null_provider {
+
+    /**
+     * Get the language string identifier with the component's language
+     * file to explain why this plugin stores no data.
+     *
+     * @return string the reason
+     */
+    public static function get_reason() : string {
+        return 'privacy:metadata';
+    }
+}
diff --git a/trigger/delayedcourses/lang/de/lifecycletrigger_delayedcourses.php b/trigger/delayedcourses/lang/de/lifecycletrigger_delayedcourses.php
index 1dac873c8c889f9a3efc5f0eeda70f9ee99254d6..317e656702472efa60b4c46a3ce428ea8e83f64a 100644
--- a/trigger/delayedcourses/lang/de/lifecycletrigger_delayedcourses.php
+++ b/trigger/delayedcourses/lang/de/lifecycletrigger_delayedcourses.php
@@ -23,5 +23,6 @@
  */
 
 $string['pluginname'] = 'Verzögerte Kurse ausschließen - Trigger';
+$string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.';
 
 $string['delay'] = 'Dieser Trigger wird alle Kurse ausschließen, die durch Nutzerinteraktion verzögert wurden.';
diff --git a/trigger/delayedcourses/lang/en/lifecycletrigger_delayedcourses.php b/trigger/delayedcourses/lang/en/lifecycletrigger_delayedcourses.php
index 4a5dcdcfe56dd097397c578dd88b82c90f54604c..2d8525ee4df026ace03b9406966ac72195adc491 100644
--- a/trigger/delayedcourses/lang/en/lifecycletrigger_delayedcourses.php
+++ b/trigger/delayedcourses/lang/en/lifecycletrigger_delayedcourses.php
@@ -23,5 +23,6 @@
  */
 
 $string['pluginname'] = 'Exclude delayed courses trigger';
+$string['privacy:metadata'] = 'This subplugin does not store any personal data.';
 
 $string['delay'] = 'This module will exclude all courses, which were delayed by user interaction';
diff --git a/trigger/manual/classes/privacy/provider.php b/trigger/manual/classes/privacy/provider.php
new file mode 100644
index 0000000000000000000000000000000000000000..b595b593699b12f78bb145aeb27d04c07cbaed11
--- /dev/null
+++ b/trigger/manual/classes/privacy/provider.php
@@ -0,0 +1,40 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace lifecycletrigger_manual\privacy;
+
+use core_privacy\local\metadata\null_provider;
+
+/**
+ * Privacy subsystem implementation for lifecycletrigger_manual.
+ *
+ * @package     lifecycletrigger_manual
+ * @copyright   2022 ISB Bayern
+ * @author      Philipp Memmel
+ * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class provider implements null_provider {
+
+    /**
+     * Get the language string identifier with the component's language
+     * file to explain why this plugin stores no data.
+     *
+     * @return string the reason
+     */
+    public static function get_reason() : string {
+        return 'privacy:metadata';
+    }
+}
diff --git a/trigger/manual/lang/de/lifecycletrigger_manual.php b/trigger/manual/lang/de/lifecycletrigger_manual.php
index af6f1d1d294aacaa8bc4c0e3ecfb9928ff1dac56..41bc729807e49983dbf537c8dd51f820cd7a6f67 100644
--- a/trigger/manual/lang/de/lifecycletrigger_manual.php
+++ b/trigger/manual/lang/de/lifecycletrigger_manual.php
@@ -23,6 +23,7 @@
  */
 
 $string['pluginname'] = 'Manueller Trigger';
+$string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.';
 $string['setting_capability'] = 'Berechtigung';
 $string['setting_capability_help'] = 'Die Moodle-Berechtigung, die ein Nutzer benötigt, um einen Workflow mit diesem Trigger zu sehen und auszulösen, z.B. "enrol/manual:enrol". Bitte schauen Sie sich die Moodle Access API für Details an.';
 $string['setting_icon'] = 'Icon';
diff --git a/trigger/manual/lang/en/lifecycletrigger_manual.php b/trigger/manual/lang/en/lifecycletrigger_manual.php
index 249ef5e9e5d3c21baf7306304cf97c76ede9fc84..dea6815d1b8844f6df09fab258598e6a7bc25949 100644
--- a/trigger/manual/lang/en/lifecycletrigger_manual.php
+++ b/trigger/manual/lang/en/lifecycletrigger_manual.php
@@ -23,6 +23,7 @@
  */
 
 $string['pluginname'] = 'Manual trigger';
+$string['privacy:metadata'] = 'This subplugin does not store any personal data.';
 $string['setting_capability'] = 'Capability';
 $string['setting_capability_help'] = 'The Moodle capability needed to see and invoke a workflow using this trigger, e.g. "enrol/manual:enrol". Please see Moodle access API documentation for details.';
 $string['setting_icon'] = 'Icon';
diff --git a/trigger/sitecourse/classes/privacy/provider.php b/trigger/sitecourse/classes/privacy/provider.php
new file mode 100644
index 0000000000000000000000000000000000000000..8ef22f4c49ec2a177018b149a264e82ceade6d5f
--- /dev/null
+++ b/trigger/sitecourse/classes/privacy/provider.php
@@ -0,0 +1,40 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace lifecycletrigger_sitecourse\privacy;
+
+use core_privacy\local\metadata\null_provider;
+
+/**
+ * Privacy subsystem implementation for lifecycletrigger_sitecourse.
+ *
+ * @package     lifecycletrigger_sitecourse
+ * @copyright   2022 ISB Bayern
+ * @author      Philipp Memmel
+ * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class provider implements null_provider {
+
+    /**
+     * Get the language string identifier with the component's language
+     * file to explain why this plugin stores no data.
+     *
+     * @return string the reason
+     */
+    public static function get_reason() : string {
+        return 'privacy:metadata';
+    }
+}
diff --git a/trigger/sitecourse/lang/de/lifecycletrigger_sitecourse.php b/trigger/sitecourse/lang/de/lifecycletrigger_sitecourse.php
index acd54b6dab51cd577a28a94c32b0858998b00b71..4ea16ed60d1cee9782d7fe0ba3dd13815d2f809c 100644
--- a/trigger/sitecourse/lang/de/lifecycletrigger_sitecourse.php
+++ b/trigger/sitecourse/lang/de/lifecycletrigger_sitecourse.php
@@ -23,5 +23,6 @@
  */
 
 $string['pluginname'] = 'Startseitenkurs ausschließen - Trigger';
+$string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.';
 
 $string['delay'] = 'Dieser Trigger wird den Startseitenkurs ausschließen.';
diff --git a/trigger/sitecourse/lang/en/lifecycletrigger_sitecourse.php b/trigger/sitecourse/lang/en/lifecycletrigger_sitecourse.php
index 330ef9f6ec34a3f4289fae7e6d3decb0c73eaf0f..7a6c02e280a5e52de57a45e4ceb3944ac4bfee80 100644
--- a/trigger/sitecourse/lang/en/lifecycletrigger_sitecourse.php
+++ b/trigger/sitecourse/lang/en/lifecycletrigger_sitecourse.php
@@ -23,5 +23,6 @@
  */
 
 $string['pluginname'] = 'Exclude site course trigger';
+$string['privacy:metadata'] = 'This subplugin does not store any personal data.';
 
 $string['delay'] = 'This module will exclude the site course from processing';
diff --git a/trigger/specificdate/classes/privacy/provider.php b/trigger/specificdate/classes/privacy/provider.php
new file mode 100644
index 0000000000000000000000000000000000000000..72e670ced0728cc4b4cef5e7d1f5734ef76e3065
--- /dev/null
+++ b/trigger/specificdate/classes/privacy/provider.php
@@ -0,0 +1,40 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace lifecycletrigger_specificdate\privacy;
+
+use core_privacy\local\metadata\null_provider;
+
+/**
+ * Privacy subsystem implementation for lifecycletrigger_specificdate.
+ *
+ * @package     lifecycletrigger_specificdate
+ * @copyright   2022 ISB Bayern
+ * @author      Philipp Memmel
+ * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class provider implements null_provider {
+
+    /**
+     * Get the language string identifier with the component's language
+     * file to explain why this plugin stores no data.
+     *
+     * @return string the reason
+     */
+    public static function get_reason() : string {
+        return 'privacy:metadata';
+    }
+}
diff --git a/trigger/specificdate/lang/de/lifecycletrigger_specificdate.php b/trigger/specificdate/lang/de/lifecycletrigger_specificdate.php
index 8e64a25aac0ebf79e53070b9b9e247b5d9bf7a37..7eab683684dde2ee6baeea54e1c05edfd794a166 100644
--- a/trigger/specificdate/lang/de/lifecycletrigger_specificdate.php
+++ b/trigger/specificdate/lang/de/lifecycletrigger_specificdate.php
@@ -23,6 +23,7 @@
  */
 
 $string['pluginname'] = 'Bestimmtes Datum - Trigger';
+$string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.';
 
 $string['dates'] = 'Daten, an denen der Workflow ausgeführt werden soll.';
 $string['dates_desc'] = 'Ein Datum pro Zeile in dem Format Tag.Monat';
diff --git a/trigger/specificdate/lang/en/lifecycletrigger_specificdate.php b/trigger/specificdate/lang/en/lifecycletrigger_specificdate.php
index 1529ac202ab7ff06356e76b522826d5017345e0a..9b7113e8961b100cf03e94fc04f3b1315ee33036 100644
--- a/trigger/specificdate/lang/en/lifecycletrigger_specificdate.php
+++ b/trigger/specificdate/lang/en/lifecycletrigger_specificdate.php
@@ -23,6 +23,7 @@
  */
 
 $string['pluginname'] = 'Specific date trigger';
+$string['privacy:metadata'] = 'This subplugin does not store any personal data.';
 
 $string['dates'] = 'Dates at which the workflow should run.';
 $string['dates_desc'] = 'Write one date per line with the format Day.Month';
diff --git a/trigger/startdatedelay/classes/privacy/provider.php b/trigger/startdatedelay/classes/privacy/provider.php
new file mode 100644
index 0000000000000000000000000000000000000000..f994ae06db05164a8662075bce195fb16f5d5f17
--- /dev/null
+++ b/trigger/startdatedelay/classes/privacy/provider.php
@@ -0,0 +1,40 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace lifecycletrigger_startdatedelay\privacy;
+
+use core_privacy\local\metadata\null_provider;
+
+/**
+ * Privacy subsystem implementation for lifecycletrigger_startdatedelay.
+ *
+ * @package     lifecycletrigger_startdatedelay
+ * @copyright   2022 ISB Bayern
+ * @author      Philipp Memmel
+ * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class provider implements null_provider {
+
+    /**
+     * Get the language string identifier with the component's language
+     * file to explain why this plugin stores no data.
+     *
+     * @return string the reason
+     */
+    public static function get_reason() : string {
+        return 'privacy:metadata';
+    }
+}
diff --git a/trigger/startdatedelay/lang/de/lifecycletrigger_startdatedelay.php b/trigger/startdatedelay/lang/de/lifecycletrigger_startdatedelay.php
index 7f92b7c8bde043dced9656728bf8ffa3631a6bad..1be8ecc179de3be1691a45d6dc94382b766a1269 100644
--- a/trigger/startdatedelay/lang/de/lifecycletrigger_startdatedelay.php
+++ b/trigger/startdatedelay/lang/de/lifecycletrigger_startdatedelay.php
@@ -23,6 +23,7 @@
  */
 
 $string['pluginname'] = 'Startdatumsabstand - Trigger';
+$string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.';
 
 $string['delay'] = 'Zeit seit Kursstartdatum, bis ein Prozess gestartet wird';
 $string['delay_help'] = 'Der Trigger wird ausgeführt, falls die Zeit, die seit dem Start des Kurses vergangen ist, größer ist, als der angegebene Zeitraum.';
diff --git a/trigger/startdatedelay/lang/en/lifecycletrigger_startdatedelay.php b/trigger/startdatedelay/lang/en/lifecycletrigger_startdatedelay.php
index 93d29d534db99d81277cffd4a7ce68981bf11abc..ba6f77df0c21956f1deb48ce9ae01e7324a1eb87 100644
--- a/trigger/startdatedelay/lang/en/lifecycletrigger_startdatedelay.php
+++ b/trigger/startdatedelay/lang/en/lifecycletrigger_startdatedelay.php
@@ -23,6 +23,7 @@
  */
 
 $string['pluginname'] = 'Start date delay trigger';
+$string['privacy:metadata'] = 'This subplugin does not store any personal data.';
 
 $string['delay'] = 'Delay from start of course until starting a process';
 $string['delay_help'] = 'The trigger will be invoked if the time passed since the course has started is longer than this delay.';