Resco Wiki

Embed forms to custom web

Besides sharing a bare link by email, SMS, or instant messaging, a gen 2 questionnaire can be embedded directly into your own website or customer portal. For example, a citizen fills out an incident report directly on a utility company's website.

Getting the embed code

Enabling the Embed Code option on the Questionnaire Share component generates a ready-to-use snippet for embedding the questionnaire into a page. Example, as generated from Dataverse:

HTML
<script src="https://forms-page.dev.resco.net/nqp/main.bundle.js"></script>
<resco-questionnaire
  safelink="https://forms-page.dev.resco.net/q/Mi5saW5rX2NlM2JmYjM2LWZhZWEtNGYyYS05MWM3LTI3ODI5ZTA5YjlhNy41MDdiN2FiZjM1YTBmMTU0MDg4MDlkOGFhNTEzYTY5ODdiYmViODJmY2RmZTM1YWMwM2VmYjA4MTNiNTRkOTc1"
  regarding='{"entityName":"account","id":"3e134b85-5a1b-f011-998b-6045bd975014","name":"A. Datum Corporation"}'>
</resco-questionnaire>
  • The <script> tag loads the questionnaire player bundle and registers the <resco-questionnaire> custom element. Include it once per page.

  • safelink — the shared link generated for this questionnaire (see "Generating questionnaire links" above).

  • regarding — JSON describing the Dataverse record the submission should be linked to (entityName, id, name), matching the regarding record selected when the link was created.

Paste the whole snippet at the location on the page where the questionnaire should appear.

Listening to lifecycle events

The <resco-questionnaire> element communicates with the host page by dispatching a questionnaire-notification custom DOM event whenever a relevant lifecycle transition happens inside the player (save, complete, dirty-state change, etc.), so the host page can react without any direct coupling to the player's internals:

JavaScript
element.dispatchEvent(new CustomEvent("questionnaire-notification", {
  detail: { name: "<message-name>", data: <payload | undefined> },
  bubbles: true,
  composed: true,
}));

bubbles: true — you can also listen on a parent element or on document if needed. composed: true — the event crosses shadow DOM boundaries.

HTML
<script>
  document.querySelector("resco-questionnaire").addEventListener("questionnaire-notification", event => {
    const { name, data } = event.detail;

    switch (name) {
      case "saved":             /* ... */ break;
      case "dirtyChanged":      /* ... */ break;
      case "closeForm":         /* ... */ break;
      case "closeFormOpenNew":  /* ... */ break;
    }
  });
</script>

Supported messages

Message

Fired when

Payload (data)

saved

After a successful Save, Save & Close, or Save, Close & Open New; and after a successful Complete, Complete & Close, or Complete, Close & Open New.

savedQuestionnaireId (string) — the record ID of the saved questionnaire.

dirtyChanged

After the questionnaire data loads and the player evaluates whether edits are present; immediately after saved (with isDirty: false) to signal the form is clean again.

isDirty (boolean) — true while there are unsaved changes.

closeForm

After Save & Close or Complete & Close.

No payload. Close or dismiss the questionnaire view.

closeFormOpenNew

After Save, Close & Open New or Complete, Close & Open New.

No payload. Re-initialize the component for a fresh questionnaire (same template).

Message sequence reference

User action

Notifications fired (in order)

Save

saveddirtyChanged (isDirty: false)

Save & Close

saveddirtyChanged (isDirty: false) → closeForm

Save, Close & Open New

saveddirtyChanged (isDirty: false) → closeFormOpenNew

Complete

saveddirtyChanged (isDirty: false)

Complete & Close

saveddirtyChanged (isDirty: false) → closeForm

Complete, Close & Open New

saveddirtyChanged (isDirty: false) → closeFormOpenNew

Full example

A complete self-contained page that embeds the questionnaire and handles all notifications:

JavaScript
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>Resco Questionnaire</title>
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <style>
    body { margin: 0; padding: 0; }
    resco-questionnaire { display: block; width: 100%; height: 100vh; }

    #submission-success {
      display: flex; align-items: center; justify-content: center;
      width: 100%; height: 100vh;
      background: linear-gradient(135deg, #f0f7ff 0%, #e8f5e9 100%);
      font-family: sans-serif;
    }
    #submission-success .card {
      background: #fff; border-radius: 16px;
      box-shadow: 0 8px 32px rgba(0,0,0,.12);
      padding: 48px 40px; max-width: 420px; width: calc(100% - 48px);
      text-align: center;
    }
  </style>
</head>
<body>
  <script src="https://forms-page.dev.resco.net/nqp/main.bundle.js"></script>
  <resco-questionnaire
    safelink="..."
    regarding='{"entityName":"account","id":"...","name":"..."}'>
  </resco-questionnaire>

  <script>
    const questionnaire = document.querySelector("resco-questionnaire");

    questionnaire.addEventListener("questionnaire-notification", event => {
      const { name, data } = event.detail;

      switch (name) {
        case "saved":
          console.log("Saved, record ID:", data.savedQuestionnaireId);
          break;

        case "dirtyChanged":
          window.onbeforeunload = data.isDirty
            ? () => "You have unsaved changes."
            : null;
          break;

        case "closeForm":
          showSuccessScreen();
          break;

        case "closeFormOpenNew":
          location.reload();
          break;
      }
    });

    function showSuccessScreen() {
      const success = document.createElement("div");
      success.id = "submission-success";
      success.innerHTML = `
        <div class="card">
          <h2>All done!</h2>
          <p>Your response has been submitted successfully.<br>
             You can now close this window.</p>
        </div>`;
      questionnaire.replaceWith(success);
    }
  </script>
</body>
</html>


Last updated: