Answers.Body: <p>I guess this is not the best way to do it and perhaps someone can point you to a better solution. I'll put it as an answer for readability purposes.</p>
  
  <p><strong>Edit</strong></p>
  
  <p>Create a <a href="https://wiki.civicrm.org/confluence/display/CRMDOC/Create+an+Extension" rel="nofollow">custom extensions</a> or use an exiting and implement <code>hook_civicrm_pageRun</code>, something like:</p>
  
  <pre><code>function myextension_civicrm_pageRun(&amp;$page){
    $pageName = $page-&gt;getVar('_name');
    if ($pageName == 'Civi\Angular\Page\Main') {
      CRM_Core_Resources::singleton()-&gt;addScriptFile('myextension', 'js/myJsScript.js');
    }
  }
  </code></pre>
  
  <p><strong>Edit: making some assumption this is with what I came up, as I said not the best thing to do but... perhaps someone finds it useful.</strong></p>
  
  <pre><code>// js/myJsScript.js
  
  CRM.$(function($){
  
    var disableUrlTracking = function(){
      // Access angular $scope
      var mailingElement = document.querySelector('[ng-model="mailing.url_tracking"]');
      var mailingScope = angular.element(mailingElement).scope();
  
      // Convert the mailing created date into seconds
      var createdDate = new Date(mailingScope.mailing.created_date).getTime()/1000;
  
      // Current date into seconds
      var nowDate = new Date().getTime()/1000;
  
      // Compare both dates
      var dif = nowDate - createdDate;
  
        // if the difference is less 60 seconds, assuming that to creat a mailing takes more than 60 seconds
      if(dif &lt;= 60){
        mailingScope.mailing.url_tracking = '0';
        CRM.alert('URL Tracking disabled', 'URL Tracking');
      }
    }
    // Optional: wait for the page to load completeley, in my case it takes some seconds until it renders the whole mailing page.
    // If you don't have that issue just call the function
    setTimeout(disableUrlTracking, 4000 );
  
  });
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-01-26T08:03:51.213Z
Answers.Text: But if the user enables url_tracking and saves the mailing as draft to finish it later, your code will disable it, when the user opens the page again.
Answers.UserDisplayName: Philipp Michael
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-01-26T08:09:26.610Z
Answers.Text: Totally true, I haven't thought about that, my fault, I misunderstood your comment.
Answers.UserDisplayName: Andrei
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-01-26T15:01:23.267Z
Answers.Text: Updated the answer, maybe you can find a better way to check if the mailing has been saved as a draft
Answers.UserDisplayName: Andrei
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-04-27T13:15:25.583Z
Answers.Text: sorry that I've not accepted your answer. I'm still hoping that there might be an easy way to alter the form.
Answers.UserDisplayName: Philipp Michael
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-04-28T00:01:48.983Z
Answers.Text: No worries, I agree there must be a better way to do it, at least it should, perhaps the `angular way`, but better doesn't necessarily mean easier, have a look at the Api explorer and try a `get` action on the Mailing entity, the only way I see you could differentiate a saved draft from a new mailing is comparing the `created_date` with the current date that is being edited, as there's no other property that I can think of that you could check for, for a sent/scheduled mailing you can see that you do have new properties like, `is_completed, scheduled_date, scheduled_id, etc`
Answers.UserDisplayName: Andrei
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-04-28T00:04:15.373Z
Answers.Text: I'll have a look tomorrow at how the Mailing app acts and see if we can come up with a better/easier solution.
Answers.UserDisplayName: Andrei
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-04-29T07:06:06.813Z
Answers.Text: Someone answered a similar question: http://civicrm.stackexchange.com/questions/11352/what-is-the-mechanism-for-tailoring-an-angular-form#answer-11499 I will give it a try.
Answers.UserDisplayName: Philipp Michael
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-04-29T14:36:56.233Z
Answers.Text: I've updated the answer, and cleaned a bit the js script. I had a look at angular and managed to hook into the form, I'll post an answer later on.
Answers.UserDisplayName: Andrei
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-01-25T19:47:00.563Z
Answers.LastActivityDate: 2016-04-29T14:30:11.540Z
Answers.LastEditDate: 2016-04-29T14:30:11.540Z
Answers.UserDisplayName: Andrei
Answers.Body: <p>In Drupal you can do this with hook_civicrm_pre():</p>
  
  <pre><code>function mymodule_civicrm_pre($op, $objectName, $id, &amp;$params) {
    if ($objectName == 'Mailing' &amp;&amp; $op == 'create') {
      $params['url_tracking'] = 0;
    }
  }
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-09-28T19:08:57.780Z
Answers.Text: It seems this is the only answer that works with Mosaico. In Mosaico the email message is immediately saved before you can get to the Tracking tab. So, the angular/javascript based solutions are not executed until you click on the Tracking tab. But if you remember to click on the tracking tab, you don't really need this functionality. So, better turn it off on creation, and leave open the possibility of turning it back on when updated.
Answers.UserDisplayName: Jamie
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-12-30T00:47:35.030Z
Answers.LastActivityDate: 2019-12-30T00:47:35.030Z
Answers.UserDisplayName: bugfolder
Answers.Body: <p>This feature is now part of core: Administer -&gt; CiviMail -&gt; CiviMail Component Settings:</p>
  <p><a href="https://i.sstatic.net/1hkVU.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/1hkVU.png" alt="enter image description here" /></a></p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-09-29T13:24:32.203Z
Answers.LastActivityDate: 2021-09-29T13:24:32.203Z
Answers.UserDisplayName: Jamie
Answers.Body: <p>Another option you may want to consider is installing <a href="https://github.com/systopia/CiviProxy" rel="nofollow noreferrer">CiviProxy</a>.  You set it up somewhere on the public Internet (I imagine a free hosting account would suffice), whitelist its IP in your firewall, and it has a very limited ability to talk to CiviCRM.  But the CiviProxy extension will rewrite your URL tracking to go to the proxy - and the proxy knows how to handle the rewrite.  It also lets you, e.g. embed images in your mailing, which otherwise wouldn't be possible.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-01-16T20:08:37.230Z
Answers.LastActivityDate: 2020-01-16T20:08:37.230Z
Answers.UserDisplayName: Jon G - Megaphone Tech
Answers.Body: <p>I wrote an extension borrowing heavily from @andrei, with a few improvements on identifying a creation vs modification of a draft</p>
  
  <p>Hope you find it useful</p>
  
  <p><a href="https://github.com/TechToThePeople/privacier" rel="nofollow noreferrer">https://github.com/TechToThePeople/privacier</a></p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-05-07T07:38:21.547Z
Answers.LastActivityDate: 2020-05-07T07:38:21.547Z
Answers.UserDisplayName: Xavier
Answers.Body: <p><strong>Disclaimer</strong>: I'm not an angularjs expert</p>
  
  <p>Again this is a bit of a hack, we are intercepting a built-in CiviCRM angular directive and extending to add behaviour.</p>
  
  <p>Create a <a href="https://wiki.civicrm.org/confluence/display/CRMDOC/Create+an+Extension?desktop=true" rel="noreferrer">custom extensions</a> or use an existing one and implement <a href="https://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_angularModules?desktop=true" rel="noreferrer">hook_civicrm_angularModules</a>:</p>
  
  <pre><code>function myextension_civicrm_angularModules(&amp;$angularModules){
          $angularModules['myModule'] = array(
                  'ext' =&gt; 'myextension',
                  'js' =&gt; array('js/myModule.js'),
          );
  }
  </code></pre>
  
  <p>In your js file:</p>
  
  <pre><code>// js/myModule.js
  
  (function(angular, $, _){
    // Your module
    angular.module('myModule', []);
  
    // the hack
    angular.module('crmMailing').config(function($provide){
  
      // crmMailingBlockTracking directive
      $provide.decorator('crmMailingBlockTrackingDirective', function($delegate){
          var directive = $delegate[0];
  
          // Original link function
          var link = directive.link;
  
          // compile function, returns new link function
          directive.compile = function(){
              return function(scope, element, attrs){
                  // get old link functionality
                  link.apply(this, arguments);
  
                  // new functionality here
                  scope.$parent.$watch(attrs.crmMailing, function(){
                      var createdDate = new Date(scope.mailing.created_date).getTime()/1000;
                      var nowDate = new Date().getTime()/1000;
  
                      if((nowDate - createdDate) &lt; 60){
                          scope.mailing.url_tracking = '0';
                          CRM.alert('Tracking Disabled');
                      }
  
                  }); 
              };
          };
  
          return $delegate;
      });
    });
  })(angular, CRM.$, CRM._);
  </code></pre>
  
  <p>The angular Mailing app uses a kind of boilerplate service, <code>crmMailingSimpleDirective</code> for constructing directives <a href="https://github.com/civicrm/civicrm-core/blob/master/ang/crmMailing/services.js#L527" rel="noreferrer">see here more info</a></p>
  
  <p>The above snippet will do the same as my other answer without relying on <code>setTimeout()</code>.</p>
  
  <p>Hope that helps.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-08-10T00:27:26.847Z
Answers.Text: That's great, thank you! Folks can also set "Track Opens" to no by default, by using scope.mailing.open_tracking = '0'; instead of or in addition to  scope.mailing.url_tracking = '0'; in the js file.
Answers.UserDisplayName: Norris
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-04-30T16:56:35.157Z
Answers.LastActivityDate: 2016-04-30T17:05:56.320Z
Answers.LastEditDate: 2016-04-30T17:05:56.320Z
Answers.UserDisplayName: Andrei
Body: <p>Is it possible to alter the mailing form? I want to set the default value for url_tracking to false. Usually I would write a hook_civicrm_buildForm and set a custom default value but this hook is not being called when loading the mailing form.</p>
  
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2016-01-23T12:00:01.297Z
Comments.Text: The mailing page/form is built with angular, I'm not sure if there's a way to hook into angular, there's a hook_civicrm_AngularModules in the hook reference, that said I guess you'll have to go with JavaScript/jQuery or modify the angular partial at `/path/to/civi/civicrm/civicrm/ang/crmMailing/BlockTracking.html` adding `ng-init="mailing.url_tracking='0'"` to the **url_tracking input**, that will make the checkbox unchecked when the page loads, please note that this is **not recommended**, you will lose any changes made to those files when upgrading CiviCRM.
Comments.UserDisplayName: Andrei
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2016-01-25T16:08:59.337Z
Comments.Text: I would update the initial value on document ready via JS in my theme. But I can't find a way to check, if the input has already been "touched". I don't want to uncheck the input if the user has set it by himself.
Comments.UserDisplayName: Philipp Michael
Tags: <civimail><hooks><angular>
Title: How to change mailing form and set the default value for url_tracking to false?
ThreadText: # How to change mailing form and set the default value for url_tracking to false?
  
  (Asked by: username_0 on 2016-01-22)
  
  Is it possible to alter the mailing form? I want to set the default value for url\_tracking to false. Usually I would write a hook\_civicrm\_buildForm and set a custom default value but this hook is not being called when loading the mailing form.
  
  **Tags:** civimail, hooks, angular
  
  > **Comments:**
  > **username_1**: The mailing page/form is built with angular, I'm not sure if there's a way to hook into angular, there's a hook_civicrm_AngularModules in the hook reference, that said I guess you'll have to go with JavaScript/jQuery or modify the angular partial at `/path/to/civi/civicrm/civicrm/ang/crmMailing/BlockTracking.html` adding `ng-init="mailing.url_tracking='0'"` to the **url_tracking input**, that will make the checkbox unchecked when the page loads, please note that this is **not recommended**, you will lose any changes made to those files when upgrading CiviCRM.  
  > **username_0**: I would update the initial value on document ready via JS in my theme. But I can't find a way to check, if the input has already been "touched". I don't want to uncheck the input if the user has set it by himself.  
  
  ---
  
  ## 6 answers
  
  ### Answer by username_1 on 2016-04-30. Score: 5 | Accepted answer
  
  **Disclaimer**: I'm not an angularjs expert
  
  Again this is a bit of a hack, we are intercepting a built-in CiviCRM angular directive and extending to add behaviour.
  
  Create a [custom extensions](https://wiki.civicrm.org/confluence/display/CRMDOC/Create+an+Extension?desktop=true) or use an existing one and implement [hook\_civicrm\_angularModules](https://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_angularModules?desktop=true):
  
  ```
  function myextension_civicrm_angularModules(&$angularModules){
          $angularModules['myModule'] = array(
                  'ext' => 'myextension',
                  'js' => array('js/myModule.js'),
          );
  }
  
  ```
  
  In your js file:
  
  ```
  // js/myModule.js
  
  (function(angular, $, _){
    // Your module
    angular.module('myModule', []);
  
    // the hack
    angular.module('crmMailing').config(function($provide){
  
      // crmMailingBlockTracking directive
      $provide.decorator('crmMailingBlockTrackingDirective', function($delegate){
          var directive = $delegate[0];
  
          // Original link function
          var link = directive.link;
  
          // compile function, returns new link function
          directive.compile = function(){
              return function(scope, element, attrs){
                  // get old link functionality
                  link.apply(this, arguments);
  
                  // new functionality here
                  scope.$parent.$watch(attrs.crmMailing, function(){
                      var createdDate = new Date(scope.mailing.created_date).getTime()/1000;
                      var nowDate = new Date().getTime()/1000;
  
                      if((nowDate - createdDate) < 60){
                          scope.mailing.url_tracking = '0';
                          CRM.alert('Tracking Disabled');
                      }
  
                  }); 
              };
          };
  
          return $delegate;
      });
    });
  })(angular, CRM.$, CRM._);
  
  ```
  
  The angular Mailing app uses a kind of boilerplate service, `crmMailingSimpleDirective` for constructing directives [see here more info](https://github.com/civicrm/civicrm-core/blob/master/ang/crmMailing/services.js#L527)
  
  The above snippet will do the same as my other answer without relying on `setTimeout()`.
  
  Hope that helps.
  
  > **Comments:**
  > **username_6**: That's great, thank you! Folks can also set "Track Opens" to no by default, by using scope.mailing.open_tracking = '0'; instead of or in addition to  scope.mailing.url_tracking = '0'; in the js file.  
  
  ---
  
  ### Answer by username_1 on 2016-01-25. Score: 3
  
  I guess this is not the best way to do it and perhaps someone can point you to a better solution. I'll put it as an answer for readability purposes.
  
  **Edit**
  
  Create a [custom extensions](https://wiki.civicrm.org/confluence/display/CRMDOC/Create+an+Extension) or use an exiting and implement `hook_civicrm_pageRun`, something like:
  
  ```
  function myextension_civicrm_pageRun(&$page){
    $pageName = $page->getVar('_name');
    if ($pageName == 'Civi\Angular\Page\Main') {
      CRM_Core_Resources::singleton()->addScriptFile('myextension', 'js/myJsScript.js');
    }
  }
  
  ```
  
  **Edit: making some assumption this is with what I came up, as I said not the best thing to do but... perhaps someone finds it useful.**
  
  ```
  // js/myJsScript.js
  
  CRM.$(function($){
  
    var disableUrlTracking = function(){
      // Access angular $scope
      var mailingElement = document.querySelector('[ng-model="mailing.url_tracking"]');
      var mailingScope = angular.element(mailingElement).scope();
  
      // Convert the mailing created date into seconds
      var createdDate = new Date(mailingScope.mailing.created_date).getTime()/1000;
  
      // Current date into seconds
      var nowDate = new Date().getTime()/1000;
  
      // Compare both dates
      var dif = nowDate - createdDate;
  
        // if the difference is less 60 seconds, assuming that to creat a mailing takes more than 60 seconds
      if(dif <= 60){
        mailingScope.mailing.url_tracking = '0';
        CRM.alert('URL Tracking disabled', 'URL Tracking');
      }
    }
    // Optional: wait for the page to load completeley, in my case it takes some seconds until it renders the whole mailing page.
    // If you don't have that issue just call the function
    setTimeout(disableUrlTracking, 4000 );
  
  });
  
  ```
  
  > **Comments:**
  > **username_0**: But if the user enables url_tracking and saves the mailing as draft to finish it later, your code will disable it, when the user opens the page again.  
  > **username_1**: Totally true, I haven't thought about that, my fault, I misunderstood your comment.  
  > **username_1**: Updated the answer, maybe you can find a better way to check if the mailing has been saved as a draft  
  > **username_0**: sorry that I've not accepted your answer. I'm still hoping that there might be an easy way to alter the form.  
  > **username_1**: No worries, I agree there must be a better way to do it, at least it should, perhaps the `angular way`, but better doesn't necessarily mean easier, have a look at the Api explorer and try a `get` action on the Mailing entity, the only way I see you could differentiate a saved draft from a new mailing is comparing the `created_date` with the current date that is being edited, as there's no other property that I can think of that you could check for, for a sent/scheduled mailing you can see that you do have new properties like, `is_completed, scheduled_date, scheduled_id, etc`  
  > **username_1**: I'll have a look tomorrow at how the Mailing app acts and see if we can come up with a better/easier solution.  
  > **username_0**: Someone answered a similar question: http://civicrm.stackexchange.com/questions/11352/what-is-the-mechanism-for-tailoring-an-angular-form#answer-11499 I will give it a try.  
  > **username_1**: I've updated the answer, and cleaned a bit the js script. I had a look at angular and managed to hook into the form, I'll post an answer later on.  
  
  ---
  
  ### Answer by username_2 on 2019-12-30. Score: 1
  
  In Drupal you can do this with hook\_civicrm\_pre():
  
  ```
  function mymodule_civicrm_pre($op, $objectName, $id, &$params) {
    if ($objectName == 'Mailing' && $op == 'create') {
      $params['url_tracking'] = 0;
    }
  }
  
  ```
  
  > **Comments:**
  > **username_3**: It seems this is the only answer that works with Mosaico. In Mosaico the email message is immediately saved before you can get to the Tracking tab. So, the angular/javascript based solutions are not executed until you click on the Tracking tab. But if you remember to click on the tracking tab, you don't really need this functionality. So, better turn it off on creation, and leave open the possibility of turning it back on when updated.  
  
  ---
  
  ### Answer by username_3 on 2021-09-29. Score: 1
  
  This feature is now part of core: Administer -> CiviMail -> CiviMail Component Settings:
  
  [![enter image description here](https://i.sstatic.net/1hkVU.png)](https://i.sstatic.net/1hkVU.png)
  
  
  ---
  
  ### Answer by username_4 on 2020-01-16. Score: 1
  
  Another option you may want to consider is installing [CiviProxy](https://github.com/systopia/CiviProxy). You set it up somewhere on the public Internet (I imagine a free hosting account would suffice), whitelist its IP in your firewall, and it has a very limited ability to talk to CiviCRM. But the CiviProxy extension will rewrite your URL tracking to go to the proxy - and the proxy knows how to handle the rewrite. It also lets you, e.g. embed images in your mailing, which otherwise wouldn't be possible.
  
  
  ---
  
  ### Answer by username_5 on 2020-05-07. Score: 1
  
  I wrote an extension borrowing heavily from @username_1, with a few improvements on identifying a creation vs modification of a draft
  
  Hope you find it useful
  
  <https://github.com/TechToThePeople/privacier>
  
  
  ---
  
  