Drupal Configuration

Customize moderation behavior with data attributes, PHP hooks, or Webform-specific settings.

Data Attribute Configuration

Add data attributes to the script tag to configure Babel Shield without writing PHP or JavaScript:

Attribute Default Description
data-api-token (required) Your Babel Shield API token
data-feedback-mode inline Feedback display: inline, modal, or silent
data-blocked-message (default) Custom message shown when content is blocked
data-feedback-container (auto) CSS selector for a custom feedback container
data-debug false Enable console debug logging
data-fail-open true Allow form submission if the API is unavailable
data-api-url (production) Custom API endpoint URL

Security: data-api-url controls where form data is sent. Only use this on pages you fully control.

Excluding Forms

Via Form Alter Hook

Use hook_form_alter() to add the data-babel-shield-ignore attribute to specific forms:

function mymodule_form_alter(&$form, $form_state, $form_id) {
  // Exclude the user login form
  if ($form_id === 'user_login_form') {
    $form['#attributes']['data-babel-shield-ignore'] = TRUE;
  }

  // Exclude a specific webform
  if ($form_id === 'webform_submission_internal_feedback_form') {
    $form['#attributes']['data-babel-shield-ignore'] = TRUE;
  }

  // Exclude a Views exposed filter form
  if (strpos($form_id, 'views_exposed_form') === 0) {
    $form['#attributes']['data-babel-shield-ignore'] = TRUE;
  }
}

Via Twig Template

Add data-babel-shield-ignore directly to a form element in a Twig template override:

<form{{ attributes.setAttribute('data-babel-shield-ignore', true) }}>
  {{ children }}
</form>

Excluding Entire Content Types

Use form ID pattern matching to exclude all node forms for a specific content type:

function mymodule_form_alter(&$form, $form_state, $form_id) {
  // Exclude all 'page' content type forms (create + edit)
  if (preg_match('/^node_page_(form|edit_form)$/', $form_id)) {
    $form['#attributes']['data-babel-shield-ignore'] = TRUE;
  }
}

Excluding Fields

Add data-babel-shield-ignore to individual form elements to skip them during moderation. All other fields in the form are still checked.

In a form alter hook:

function mymodule_form_alter(&$form, $form_state, $form_id) {
  if (isset($form['field_internal_notes'])) {
    $form['field_internal_notes']['#attributes']['data-babel-shield-ignore'] = TRUE;
  }
}

In a Twig field template:

<textarea{{ attributes.setAttribute('data-babel-shield-ignore', true) }}></textarea>

Conditional Loading

Use hook_page_attachments() with route matching to load Babel Shield only on specific pages:

Load only on node view pages:

function babel_shield_page_attachments(array &$attachments) {
  $route = \Drupal::routeMatch()->getRouteName();

  // Only load on node view pages
  if ($route !== 'entity.node.canonical') {
    return;
  }

  $attachments['#attached']['html_head'][] = [
    [
      '#type' => 'html_tag',
      '#tag' => 'script',
      '#attributes' => [
        'src' => 'https://cdn.babelshield.ai/v1/babel-shield.js',
        'data-api-token' => 'YOUR_API_TOKEN',
      ],
    ],
    'babel_shield',
  ];
}

Skip admin routes:

function babel_shield_page_attachments(array &$attachments) {
  if (\Drupal::service('router.admin_context')->isAdminRoute()) {
    return;
  }

  // Attach Babel Shield script...
}

Load only on pages with webforms:

function babel_shield_page_attachments(array &$attachments) {
  $route = \Drupal::routeMatch()->getRouteName();

  // Load on webform canonical pages
  if ($route === 'entity.webform.canonical') {
    // Attach Babel Shield script...
    return;
  }

  // Load on pages that render webform elements
  $route_object = \Drupal::routeMatch()->getRouteObject();
  if ($route_object && strpos($route_object->getPath(), '/webform/') !== false) {
    // Attach Babel Shield script...
  }
}

System Fields Removed Automatically

The Drupal adapter strips these system fields from the moderation payload before sending content to the API:

Field Source Purpose
form_build_id Drupal core Form cache ID
form_token Drupal core CSRF protection token
form_id Drupal core Form identifier
op Drupal core Submit button value
honeypot_time Honeypot module Anti-spam timing field
url (honeypot) Honeypot module Anti-spam hidden field

Token-like fields (names matching patterns like token, csrf, nonce, captcha) with hex values are also removed automatically.

Webform-Specific Notes

Webform submissions are detected via the .webform-submission-form class. AJAX Webform submissions are intercepted via the webform:submit custom event.

To target a specific Webform for configuration, use hook_webform_submission_form_alter():

use Drupal\Core\Form\FormStateInterface;

function mymodule_webform_submission_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
  if ($form['#webform_id'] === 'contact') {
    // Add custom configuration for this specific webform
  }
}

Testing Your Integration

  1. Enable debug mode by adding data-debug="true" to the script tag
  2. Submit a clean message and check the browser console for [BabelShield] log entries
  3. Submit content that should be flagged (e.g., spam text) and verify the feedback message appears
  4. Run BabelShield.diagnose() in the console -- check that adapter.name is drupal and forms.protected shows the expected count
  5. Test AJAX forms separately -- submit a Webform via AJAX and verify moderation works

Next Steps