Add parameter to the URL based on a field value
Don't know if it fits for your use case, but I wanted all outgoing links from a specific node type to have the ID appended, e.g. on every product page all outgoing "Call to action" links should appent something like ?from_product_id=1234. My module name was 'wt_ctalinks`

wt_ctalinks.services.yml

services:
  cache_context.wt_ctalinks:
    class: Drupal\wt_ctalinks\CtaLinksCacheContext
    arguments: ['@request_stack']
    tags:
      - { name: cache.context }
  wt_ctalinks.ctalinks_pathmodifier_service:
    class: Drupal\wt_ctalinks\CtaLinksPathModifierService
    arguments: ['@request_stack']
    tags:
      - { name: path_processor_outbound, priority: 3000 }


src/CtaLinksCacheContext.php

&lt;?php

namespace Drupal\wt_ctalinks;

use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Cache\Context\CacheContextInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Drupal\node\Entity\Node;
use Drupal\node\NodeInterface;

class CtaLinksCacheContext implements CacheContextInterface {


  /**
   * @var Symfony\Component\HttpFoundation\RequestStack;
   */
  protected $requestStack;

  public function __construct(RequestStack $request_stack) {
    $this-&gt;requestStack = $request_stack;
  }

  /**
  * {@inheritdoc}
  */
  public static function getLabel() {
    drupal_set_message('Modify CTA links based on current node type');
  }

  /**
  * {@inheritdoc}
  */
  public function getContext() {
    $nid = 0;
    $request = $this-&gt;requestStack-&gt;getCurrentRequest();
    $node = $request-&gt;attributes-&gt;get('node');
    if (is_numeric($node)) {
      $node = Node::load($node);
    }
    if ($node instanceof NodeInterface &amp;&amp; $node-&gt;bundle() === 'article') {
      $nid = $node-&gt;id();
    }
    return $nid;
  }

  /**
  * {@inheritdoc}
  */
  public function getCacheableMetadata() {
    return new CacheableMetadata();
  }
}



src/CtaLinksPathModifierService.php

&lt;?php

namespace Drupal\wt_ctalinks;
use Drupal\node\NodeInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Drupal\Core\PathProcessor\OutboundPathProcessorInterface;
use Symfony\Component\HttpFoundation\Request;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\config_pages\Entity\ConfigPages;
use Drupal\node\Entity\Node;


/**
 * Class DefaultService.
 */
class CtaLinksPathModifierService implements OutboundPathProcessorInterface {

  /**
   * @var \Symfony\Component\HttpFoundation\RequestStack
   */
  protected $requestStack;

  protected $bookingPath;
  protected $enquirePath;

  /**
   * Constructs a new DefaultService object.
   */
  public function __construct(RequestStack $request_stack) {
    $this-&gt;requestStack = $request_stack;
  }

  /**
   * {@inheritdoc}
   */
  public function processOutbound($path, &amp;$options = array(), Request $request = NULL, BubbleableMetadata $bubbleable_metadata = NULL) {
    if (empty($request)) {
      $request = $this-&gt;requestStack-&gt;getCurrentRequest();
    }

    $node = $request-&gt;attributes-&gt;get('node');

    if (is_numeric($node)) {
      // missing upcasting in revision view, have to load manually there
      $node = Node::load($node);
    }

    if ($node instanceof NodeInterface &amp;&amp; $node-&gt;getType() === 'article') {
      // your logic here
    }

    if ($bubbleable_metadata) {
      $bubbleable_metadata
        -&gt;addCacheContexts([
          'wt_ctalinks',
        ]);
    }
    return $path;
  }
}