diff --git a/frontend-js/src/main/js/ConfigurationType.js b/frontend-js/src/main/js/ConfigurationType.js
index 183411fcea0dadee718eb8984c9874866e201534..5ebf5f1e7d5148b7b7a0fd321f1a4ff3032fe41b 100644
--- a/frontend-js/src/main/js/ConfigurationType.js
+++ b/frontend-js/src/main/js/ConfigurationType.js
@@ -18,6 +18,7 @@ var ConfigurationType = {
   SHOW_REACTION_TYPE: "SHOW_REACTION_TYPE",
   SEARCH_DISTANCE: "SEARCH_DISTANCE",
   SEARCH_RESULT_NUMBER: "SEARCH_RESULT_NUMBER",
+  TERMS_OF_USE: "TERMS_OF_USE",
   USER_MANUAL_FILE: "USER_MANUAL_FILE"
 };
 
diff --git a/frontend-js/src/main/js/ServerConnector.js b/frontend-js/src/main/js/ServerConnector.js
index 9f062cf988f167ccb5ee7d059c27f9ae1285ef2c..6efe146936336b6e509c892f3ba619f76c971ba3 100644
--- a/frontend-js/src/main/js/ServerConnector.js
+++ b/frontend-js/src/main/js/ServerConnector.js
@@ -1007,7 +1007,7 @@ ServerConnector.getUser = function (login) {
     login: login
   };
   var filterParams = {
-    columns: ["id", "login", "name", "surname", "email", "minColor", "maxColor", "neutralColor", "simpleColor", "removed", "privileges", "preferences"]
+    columns: ["id", "login", "name", "surname", "email", "minColor", "maxColor", "neutralColor", "simpleColor", "removed", "privileges", "preferences", "termsOfUseConsent"]
   };
 
   return self.sendGetRequest(self.getUserUrl(queryParams, filterParams)).then(function (content) {
@@ -1024,6 +1024,11 @@ ServerConnector.getUser = function (login) {
   });
 };
 
+/**
+ *
+ * @param {User} user
+ * @returns {PromiseLike<any>}
+ */
 ServerConnector.updateUser = function (user) {
   var self = this;
   var queryParams = {
@@ -1034,7 +1039,8 @@ ServerConnector.updateUser = function (user) {
       name: user.getName(),
       surname: user.getSurname(),
       password: user.getPassword(),
-      email: user.getEmail()
+      email: user.getEmail(),
+      termsOfUseConsent: user.isTermsOfUseConsent()
     }
   };
   return self.sendPatchRequest(self.getUserUrl(queryParams), filterParams).then(function () {
diff --git a/frontend-js/src/main/js/gui/AddOverlayDialog.js b/frontend-js/src/main/js/gui/AddOverlayDialog.js
index 8d730471ae36be7564ed0b13bdb6f4778a0c8c91..d0813b9624be787788320e2cdaf254f19f10bbfb 100644
--- a/frontend-js/src/main/js/gui/AddOverlayDialog.js
+++ b/frontend-js/src/main/js/gui/AddOverlayDialog.js
@@ -73,6 +73,13 @@ AddOverlayDialog.prototype.createGui = function () {
   content.appendChild(contentInput);
   content.appendChild(guiUtils.createNewLine());
 
+  var consentCheckbox = Functions.createElement({type:"input", name:"overlay-google-consent"});
+  consentCheckbox.type = "checkbox";
+  content.appendChild(consentCheckbox);
+  content.appendChild(guiUtils.createLabel("I am aware that this map is displayed under the terms of the <a href='https://cloud.google.com/maps-platform/terms/' target='_blank'>license of Google Maps Platform</a> and I agree to these terms. " +
+    "In particular, I warrant that this dataset does not contain Protected Health Information (as defined in and subject to HIPAA). "));
+  content.appendChild(guiUtils.createNewLine());
+
   self.getElement().appendChild(content);
 };
 
@@ -154,6 +161,7 @@ AddOverlayDialog.prototype.addOverlay = function () {
   var nameInput = $("[name='overlay-name']", self.getElement())[0];
   var descriptionInput = $("[name='overlay-description']", self.getElement())[0];
   var filename = $("[name='overlay-file']", self.getElement())[0].value;
+  var consent = $("[name='overlay-google-consent']", self.getElement()).is(":checked");
   var overlay = new DataOverlay({
     name: nameInput.value,
     description: descriptionInput.value,
@@ -170,7 +178,8 @@ AddOverlayDialog.prototype.addOverlay = function () {
     return ServerConnector.addOverlay({
       fileId: file.id,
       overlay: overlay,
-      projectId: self.getProject().getProjectId()
+      projectId: self.getProject().getProjectId(),
+      googleLicenseConsent: consent
     });
   }).then(function (result) {
     overlay = result;
diff --git a/frontend-js/src/main/js/map/data/User.js b/frontend-js/src/main/js/map/data/User.js
index 65abd561260675f63b37cec1d6013d4e6059f4db..6128f56bbf5aff332df5dacfe0e804bd88083f59 100644
--- a/frontend-js/src/main/js/map/data/User.js
+++ b/frontend-js/src/main/js/map/data/User.js
@@ -24,6 +24,7 @@ function User(javaObject) {
   this.setMaxColor(javaObject.maxColor);
   this.setNeutralColor(javaObject.neutralColor);
   this.setSimpleColor(javaObject.simpleColor);
+  this.setTermsOfUseConsent(javaObject.termsOfUseConsent);
 }
 
 // this class inherits from ObjectWithListeners class where generic methods for
@@ -216,4 +217,12 @@ User.prototype.update = function (user) {
   return self.callListeners("onreload");
 };
 
+User.prototype.setTermsOfUseConsent = function(termsOfUseConsent) {
+  this._termsOfUseConsent = termsOfUseConsent;
+};
+
+User.prototype.isTermsOfUseConsent = function() {
+  return this._termsOfUseConsent;
+};
+
 module.exports = User;
diff --git a/frontend-js/src/main/js/minerva.js b/frontend-js/src/main/js/minerva.js
index a97d50545bab049b7c03a6cb3a93d8496438e198..92dac01dcd42c64326b777842c1cd737407e7a00 100644
--- a/frontend-js/src/main/js/minerva.js
+++ b/frontend-js/src/main/js/minerva.js
@@ -64,6 +64,60 @@ function processUrlGetParams(params) {
 
 }
 
+/**
+ *
+ * @param {User} user
+ * @param {string} termsOfUseUrl
+ */
+function requestConsent(user, termsOfUseUrl) {
+  var dialog = document.createElement("div");
+  var dialogContent = document.createElement("div");
+  dialogContent.appendChild(functions.createElement({
+    type: "span",
+    content: "I agree to the minerva <a href='" + termsOfUseUrl + "' target='_blank'>Terms of Use</a>."
+  }));
+  var checkbox = functions.createElement({type: "input", inputType: "checkbox", style: "float: left"});
+  var okButton = functions.createElement({
+    type: "button",
+    content: "OK",
+    className: "ui-button ui-corner-all ui-widget",
+    onclick: function () {
+      user.setTermsOfUseConsent($(checkbox).is(':checked'));
+      return ServerConnector.updateUser(user).then(function () {
+        $(dialog).dialog("close");
+      }).catch(GuiConnector.alert);
+    }
+  });
+  var cancelButton = functions.createElement({
+    type: "button",
+    content: "I disagree",
+    className: "ui-button ui-corner-all ui-widget",
+    onclick: function () {
+      return ServerConnector.logout().catch(GuiConnector.alert);
+    }
+  });
+  $(okButton).prop("disabled", true);
+  $(checkbox).change(function () {
+    $(okButton).prop("disabled", !$(checkbox).is(':checked'));
+  });
+  dialogContent.appendChild(checkbox);
+  dialogContent.appendChild(okButton);
+  dialogContent.appendChild(cancelButton);
+
+  dialog.appendChild(dialogContent);
+  document.body.appendChild(dialog);
+  $(dialog).dialog({
+    classes: {
+      "ui-dialog": "ui-state-error"
+    },
+    modal: true,
+    closeOnEscape: false,
+    title: "Terms of Use"
+  }).siblings('.ui-dialog-titlebar').css("background", "red");
+  $(".ui-dialog-titlebar-close", $(dialog).dialog().siblings('.ui-dialog-titlebar')).hide();
+  $(dialog).dialog("open");
+}
+
 function insertGoogleAnalyticsCode() {
   return ServerConnector.getConfigurationParam(ConfigurationType.GOOGLE_ANALYTICS_IDENTIFIER).then(function (identifier) {
     if (identifier === "" || identifier === undefined || identifier === null) {
@@ -360,9 +414,14 @@ function create(params) {
     }
     return Promise.all(promises);
   }).then(function () {
+    return ServerConnector.getLoggedUser();
+  }).then(function (user) {
     if (leftPanel.isGoogleLicenseConsentRequired()) {
       GuiConnector.alert("Some data overlays doesn't have consent to the terms of the <a href='https://cloud.google.com/maps-platform/terms/' target='_blank'>license of Google Maps Platform</a>. To be able to visualize them you must edit data overlay. ")
     }
+    if (user.getLogin() !== "anonymous" && !user.isTermsOfUseConsent()) {
+      requestConsent(user, params.getConfiguration().getOption(ConfigurationType.TERMS_OF_USE));
+    }
     var result = {
       destroy: function () {
         return leftPanel.destroy().then(function () {
diff --git a/model/src/main/java/lcsb/mapviewer/model/user/ConfigurationElementType.java b/model/src/main/java/lcsb/mapviewer/model/user/ConfigurationElementType.java
index 27b2aceee9fb34686cb5d703814b1a9551e3c427..835fcc4f7203c0ce4e6354f1a9264abe64d21345 100644
--- a/model/src/main/java/lcsb/mapviewer/model/user/ConfigurationElementType.java
+++ b/model/src/main/java/lcsb/mapviewer/model/user/ConfigurationElementType.java
@@ -194,6 +194,11 @@ public enum ConfigurationElementType {
       + "(\"General overlays\") on this MINERVA server contain Protected Health Information (as defined in and subject to HIPAA).",
       "", ConfigurationElementEditType.STRING, false, ConfigurationElementTypeGroup.SERVER_CONFIGURATION),
 
+  /**
+   * File where legend 4/4 is stored.
+   */
+  TERMS_OF_USE("Terms of use file", "resources/other/terms_of_use.pdf", ConfigurationElementEditType.URL, false, ConfigurationElementTypeGroup.LEGEND_AND_LOGO),
+
   ;
 
   /**
diff --git a/model/src/main/java/lcsb/mapviewer/model/user/User.java b/model/src/main/java/lcsb/mapviewer/model/user/User.java
index 744af477513acf882220c9f23128dbfb77733e78..fdb5e080a10f840dda1a19bc7330acf051c72602 100644
--- a/model/src/main/java/lcsb/mapviewer/model/user/User.java
+++ b/model/src/main/java/lcsb/mapviewer/model/user/User.java
@@ -31,7 +31,7 @@ import lcsb.mapviewer.common.comparator.StringComparator;
 public class User implements Serializable {
 
   /**
-   * 
+   *
    */
   private static final long serialVersionUID = 1L;
 
@@ -118,6 +118,9 @@ public class User implements Serializable {
    */
   private boolean removed = false;
 
+    @Column(name="terms_of_use_consent")
+    private boolean                     termsOfUseConsent = false;
+
   /**
    * Set of user privileges.
    */
@@ -139,7 +142,7 @@ public class User implements Serializable {
 
   /**
    * Adds privilege to the user.
-   * 
+   *
    * @param privilege
    *          privilege to add
    */
@@ -367,4 +370,12 @@ public class User implements Serializable {
     this.neutralColor = neutralColor;
   }
 
+  public boolean isTermsOfUseConsent() {
+    return termsOfUseConsent;
+  }
+
+  public void setTermsOfUseConsent(boolean termsOfUseConsent) {
+    this.termsOfUseConsent = termsOfUseConsent;
+  }
+
 }
diff --git a/persist/src/db/11.1.0/fix_db_20180525.sql b/persist/src/db/11.1.0/fix_db_20180525.sql
new file mode 100644
index 0000000000000000000000000000000000000000..70350604e3100f5731f53e5b0162df1098da67f7
--- /dev/null
+++ b/persist/src/db/11.1.0/fix_db_20180525.sql
@@ -0,0 +1 @@
+alter table user_table add column terms_of_use_consent boolean default false;
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayController.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayController.java
index 02c676e99a510cff2f83efa3a03f388379fc7ace..fb2f9e247b1eddfd6f241563c8e4c8a2ad9510b3 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayController.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayController.java
@@ -106,9 +106,10 @@ public class OverlayController extends BaseController {
       @RequestParam(value = "content", defaultValue = "") String content, //
       @RequestParam(value = "fileId", defaultValue = "") String fileId, //
       @RequestParam(value = "filename") String filename, //
+            @RequestParam(value = "googleLicenseConsent") String googleLicenseConsent, //
       @RequestParam(value = "type", defaultValue = "") String type //
   ) throws SecurityException, QueryException, IOException {
-    return overlayRestImp.addOverlay(token, projectId, name, description, content, fileId, filename, type);
+    return overlayRestImp.addOverlay(token, projectId, name, description, content, fileId, filename, type, googleLicenseConsent);
   }
 
   @RequestMapping(value = "/projects/{projectId}/overlays/{overlayId}", method = { RequestMethod.DELETE }, produces = {
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayRestImpl.java
index 9e4148389169025792ace2fc548f5a61e9e41bfb..1e5ac46b63110b119b51c45cf034ba33e17908e0 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayRestImpl.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayRestImpl.java
@@ -314,7 +314,7 @@ public class OverlayRestImpl extends BaseRestImpl {
   }
 
   public Map<String, Object> addOverlay(String token, String projectId, String name, String description, String content,
-      String fileId, String filename, String type) throws SecurityException, QueryException, IOException {
+      String fileId, String filename, String type, String googleLicenseConsent) throws SecurityException, QueryException, IOException {
     User user = getUserService().getUserByToken(token);
     if (Configuration.ANONYMOUS_LOGIN.equals(user.getLogin())) {
       throw new SecurityException("You have no privileges to add overlay");
@@ -357,7 +357,7 @@ public class OverlayRestImpl extends BaseRestImpl {
 
       Layout layout = layoutService.createLayout(new CreateLayoutParams().async(false).colorInputStream(stream)
           .description(description).layoutFileName(filename).model(model).name(name).user(user)
-          .colorSchemaType(colorSchemaType).directory("."));
+          .colorSchemaType(colorSchemaType).directory(".").googleLicenseConsent(googleLicenseConsent.equalsIgnoreCase("true")));
 
       int count = layoutService.getCustomLayouts(model, token, false, user).size();
       layout.setOrderIndex(count);
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/users/UserRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/users/UserRestImpl.java
index aa64c6491b495b3aa77b6bc473fa8424d00772d5..de838df959d2569ba49fe26d57fc0f12c666c7fd 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/users/UserRestImpl.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/users/UserRestImpl.java
@@ -81,6 +81,7 @@ public class UserRestImpl extends BaseRestImpl {
       columnsSet.add("simpleColor");
       columnsSet.add("removed");
       columnsSet.add("privileges");
+      columnsSet.add("termsOfUseConsent");
     } else {
       for (String str : columns.split(",")) {
         columnsSet.add(str);
@@ -114,6 +115,8 @@ public class UserRestImpl extends BaseRestImpl {
         value = user.getSimpleColor();
       } else if (column.equals("removed")) {
         value = user.isRemoved();
+      } else if (column.equals("termsofuseconsent")) {
+        value = user.isTermsOfUseConsent();
       } else if (column.equals("privileges") && admin) {
         value = preparePrivileges(user);
       } else if (column.equals("preferences")) {
@@ -149,7 +152,7 @@ public class UserRestImpl extends BaseRestImpl {
   /**
    * Prepares annotator parameters in the form of a map having annotators class
    * names as keys and map of name:value pairs of given annotator as values.
-   * 
+   *
    * @param annotatorsParams
    * @return
    */
@@ -537,6 +540,8 @@ public class UserRestImpl extends BaseRestImpl {
         user.setSurname(stringValue);
       } else if (key.equalsIgnoreCase("email")) {
         user.setEmail(stringValue);
+      } else if (key.equalsIgnoreCase("termsofuseconsent")) {
+        user.setTermsOfUseConsent((Boolean) value);
       } else if (key.equalsIgnoreCase("password")) {
         if (stringValue != null && !stringValue.trim().isEmpty()) {
           user.setCryptedPassword(getUserService().encodePassword(stringValue));
diff --git a/web/src/main/webapp/resources/other/terms_of_use.pdf b/web/src/main/webapp/resources/other/terms_of_use.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..21f7fb0abbde215ce1391ed614874e4060bcb94c
Binary files /dev/null and b/web/src/main/webapp/resources/other/terms_of_use.pdf differ
diff --git a/web/src/main/webapp/resources/other/user_guide.pdf b/web/src/main/webapp/resources/other/user_guide.pdf
index 6f4d57c5108c5da7993f9184d8300101f57b0153..84030df5fa349e3ba56d6253110297473e85ef98 100644
Binary files a/web/src/main/webapp/resources/other/user_guide.pdf and b/web/src/main/webapp/resources/other/user_guide.pdf differ