diff --git a/src/Plugin/EntityUsage/Track/Link.php b/src/Plugin/EntityUsage/Track/Link.php
new file mode 100644
index 0000000..13f7a5a
--- /dev/null
+++ b/src/Plugin/EntityUsage/Track/Link.php
@@ -0,0 +1,255 @@
+<?php
+
+namespace Drupal\entity_usage\Plugin\EntityUsage\Track;
+
+use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\Core\Entity\EntityFieldManagerInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\entity_usage\EntityUsage;
+use Drupal\entity_usage\EntityUsageTrackBase;
+use Drupal\link\LinkItemInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Tracks usage of entities related in entity_reference fields.
+ *
+ * @EntityUsageTrack(
+ *   id = "link",
+ *   label = @Translation("Link Fields"),
+ *   description = @Translation("Tracks usage of entities related in link fields."),
+ * )
+ */
+class Link extends EntityUsageTrackBase {
+
+  /**
+   * Entity field manager service.
+   *
+   * @var \Drupal\Core\Entity\EntityFieldManagerInterface
+   */
+  protected $entityFieldManager;
+
+  /**
+   * Entity type manager service.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * Constructs display plugin.
+   *
+   * @param array $configuration
+   *   A configuration array containing information about the plugin instance.
+   * @param string $plugin_id
+   *   The plugin_id for the plugin instance.
+   * @param mixed $plugin_definition
+   *   The plugin implementation definition.
+   * @param \Drupal\entity_usage\EntityUsage $usage_service
+   *   The usage tracking service.
+   * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
+   *   The EntityFieldManager service.
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+   *   The EntityTypeManager service.
+   */
+  public function __construct(
+    array $configuration,
+    $plugin_id,
+    $plugin_definition,
+    EntityUsage $usage_service,
+    EntityFieldManagerInterface $entity_field_manager,
+    EntityTypeManagerInterface $entity_type_manager
+  ) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition, $usage_service);
+    $this->entityFieldManager = $entity_field_manager;
+    $this->entityTypeManager = $entity_type_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('entity_usage.usage'),
+      $container->get('entity_field.manager'),
+      $container->get('entity_type.manager')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function trackOnEntityCreation(ContentEntityInterface $entity) {
+    foreach ($this->linkFieldsAvailable($entity) as $field_name) {
+      if (!$entity->{$field_name}->isEmpty()) {
+        /** @var \Drupal\link\Plugin\Field\FieldType\LinkItem $field_item */
+        foreach ($entity->{$field_name} as $field_item) {
+          // This item got added. Track the usage up.
+          $linked_entity = $this->getEntityFromLinkValue($field_item);
+          $this->usageService->add($linked_entity['entity_id'], $linked_entity['entity_type'], $entity->id(), $entity->getEntityTypeId(), $this->pluginId);
+        }
+      }
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function trackOnEntityUpdate(ContentEntityInterface $entity) {
+    // The assumption here is that an entity that is referenced by any
+    // translation of another entity should be tracked, and only once
+    // (regardless if many translations point to the same entity). So the
+    // process to identify them is quite simple: we build a list of all entity
+    // ids referenced before the update by all translations (original included),
+    // and compare it with the list of ids referenced by all translations after
+    // the update.
+    $translations = [];
+    $originals = [];
+    $languages = $entity->getTranslationLanguages();
+    foreach ($languages as $langcode => $language) {
+      if (!$entity->hasTranslation($langcode)) {
+        continue;
+      }
+      $translations[] = $entity->getTranslation($langcode);
+      if (!$entity->original->hasTranslation($langcode)) {
+        continue;
+      }
+      $originals[] = $entity->original->getTranslation($langcode);
+    }
+
+    foreach ($this->linkFieldsAvailable($entity) as $field_name) {
+      $current_target_ids = [];
+      foreach ($translations as $translation) {
+        if (!$translation->{$field_name}->isEmpty()) {
+          foreach ($translation->{$field_name} as $field_item) {
+            $linked_entity = $this->getEntityFromLinkValue($field_item);
+            if (!empty($linked_entity['entity_type']) && !empty($linked_entity['entity_id'])) {
+              $current_target_ids[] = $linked_entity['entity_type'] . ':' . $linked_entity['entity_id'];
+            }
+          }
+        }
+      }
+      $original_target_ids = [];
+      foreach ($originals as $original) {
+        if (!$original->{$field_name}->isEmpty()) {
+          foreach ($original->{$field_name} as $field_item) {
+            $linked_entity = $this->getEntityFromLinkValue($field_item);
+            if (!empty($linked_entity['entity_type']) && !empty($linked_entity['entity_id'])) {
+              $original_target_ids[] = $linked_entity['entity_type'] . ':' . $linked_entity['entity_id'];
+            }
+          }
+        }
+      }
+      // If more than one translation references the same target entity, we
+      // record only one usage.
+      $original_target_ids = array_unique($original_target_ids);
+      $current_target_ids = array_unique($current_target_ids);
+
+      $added_ids = array_diff($current_target_ids, $original_target_ids);
+      $removed_ids = array_diff($original_target_ids, $current_target_ids);
+
+      foreach ($added_ids as $id) {
+        $values = explode(":", $id);
+        $this->usageService->add($values[1], $values[0], $entity->id(), $entity->getEntityTypeId(), $this->pluginId);
+      }
+      foreach ($removed_ids as $id) {
+        $values = explode(":", $id);
+        $this->usageService->delete($values[1], $values[0], $entity->id(), $entity->getEntityTypeId());
+      }
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function trackOnEntityDeletion(ContentEntityInterface $entity) {
+    $translations = [];
+    // When deleting the main (untranslated) entity, loop over all translations
+    // as well to release referenced entities there too.
+    if ($entity === $entity->getUntranslated()) {
+      $languages = $entity->getTranslationLanguages();
+      foreach ($languages as $langcode => $language) {
+        if (!$entity->hasTranslation($langcode)) {
+          continue;
+        }
+        $translations[] = $entity->getTranslation($langcode);
+      }
+    }
+    else {
+      // Otherwise, this is a single translation being deleted, so we just need
+      // to release usage reflected here.
+      $translations = [$entity];
+    }
+
+    foreach ($this->linkFieldsAvailable($entity) as $field_name) {
+      foreach ($translations as $translation) {
+        if (!$translation->{$field_name}->isEmpty()) {
+          /** @var \Drupal\link\Plugin\Field\FieldType\LinkItem $field_item */
+          foreach ($translation->{$field_name} as $field_item) {
+            // This item got deleted. Track the usage down.
+            $linked_entity = $this->getEntityFromLinkValue($field_item);
+            $this->usageService->delete($linked_entity['entity_id'], $linked_entity['entity_type'], $entity->id(), $entity->getEntityTypeId());
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * Retrieve the link fields on a given entity.
+   *
+   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
+   *   The entity object.
+   *
+   * @return array
+   *   An array of field_names that could reference to other content entities.
+   */
+  private function linkFieldsAvailable(ContentEntityInterface $entity) {
+    $return_fields = [];
+    $fields_on_entity = $this->entityFieldManager->getFieldDefinitions($entity->getEntityTypeId(), $entity->bundle());
+    $link_fields_on_this_entity_type = [];
+    if (!empty($this->entityFieldManager->getFieldMapByFieldType('link')[$entity->getEntityTypeId()])) {
+      $link_fields_on_this_entity_type = $this->entityFieldManager->getFieldMapByFieldType('link')[$entity->getEntityTypeId()];
+    }
+    $link_fields_on_this_bundle = array_intersect_key($fields_on_entity, $link_fields_on_this_entity_type);
+    // Clean out basefields.
+    $basefields = $this->entityFieldManager->getBaseFieldDefinitions($entity->getEntityTypeId());
+    $link_fields_on_this_bundle = array_diff_key($link_fields_on_this_bundle, $basefields);
+    if (!empty($link_fields_on_this_bundle)) {
+      $return_fields = array_keys($link_fields_on_this_bundle);
+    }
+    return $return_fields;
+  }
+
+  /**
+   * Get entity type and ID from a Link field uri.
+   *
+   * @param \Drupal\link\LinkItemInterface $field_item
+   *   The field value item.
+   *
+   * @return array
+   *   An associative array with keys:
+   *   - entity_type: The entity type found, or NULL otherwise.
+   *   - entity_id: The entity ID found, or NULL otherwise.
+   */
+  private function getEntityFromLinkValue(LinkItemInterface $field_item) {
+    $return = [
+      'entity_type' => NULL,
+      'entity_id' => NULL,
+    ];
+
+    $uri = !empty($field_item->uri) ? $field_item->uri : NULL;
+    if ($uri && strpos($uri, 'entity:') === 0) {
+      $values = explode("/", substr($uri, 7));
+      if ($values) {
+        $return['entity_type'] = $values[0];
+        $return['entity_id'] = $values[1];
+      }
+    }
+
+    return $return;
+  }
+
+}
diff --git a/tests/src/FunctionalJavascript/IntegrationTest.php b/tests/src/FunctionalJavascript/IntegrationTest.php
index 9b91e3c..134fd8d 100644
--- a/tests/src/FunctionalJavascript/IntegrationTest.php
+++ b/tests/src/FunctionalJavascript/IntegrationTest.php
@@ -2,6 +2,10 @@
 
 namespace Drupal\Tests\entity_usage\FunctionalJavascript;
 
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
+use Drupal\field\Entity\FieldConfig;
+use Drupal\field\Entity\FieldStorageConfig;
+use Drupal\link\LinkItemInterface;
 use Drupal\node\Entity\Node;
 
 /**
@@ -14,11 +18,19 @@ use Drupal\node\Entity\Node;
 class IntegrationTest extends EntityUsageJavascriptTestBase {
 
   /**
+   * {@inheritdoc}
+   */
+  protected static $modules = [
+    'link',
+  ];
+
+  /**
    * Tests the tracking of nodes in some simple CRUD operations.
    */
   public function testCrudTracking() {
-
     $page = $this->getSession()->getPage();
+    $assert_session = $this->assertSession();
+
     /** @var \Drupal\entity_usage\EntityUsage $usage_service */
     $usage_service = \Drupal::service('entity_usage.usage');
 
@@ -26,7 +38,7 @@ class IntegrationTest extends EntityUsageJavascriptTestBase {
     $this->drupalGet('/node/add/eu_test_ct');
     $page->fillField('title[0][value]', 'Node 1');
     $page->pressButton('Save');
-    $this->assertSession()->pageTextContains('eu_test_ct Node 1 has been created.');
+    $assert_session->pageTextContains('eu_test_ct Node 1 has been created.');
     $this->saveHtmlOutput();
     $node1 = Node::load(1);
 
@@ -35,7 +47,7 @@ class IntegrationTest extends EntityUsageJavascriptTestBase {
     $page->fillField('title[0][value]', 'Node 2');
     $page->fillField('field_eu_test_related_nodes[0][target_id]', 'Node 1 (1)');
     $page->pressButton('Save');
-    $this->assertSession()->pageTextContains('eu_test_ct Node 2 has been created.');
+    $assert_session->pageTextContains('eu_test_ct Node 2 has been created.');
     $this->saveHtmlOutput();
     $node2 = Node::load(2);
     // Check that we registered correctly the relation between N2 and N1.
@@ -125,4 +137,101 @@ class IntegrationTest extends EntityUsageJavascriptTestBase {
     $this->assertEquals($usage['linkit']['node'], ['5' => '1'], 'Correct usage found.');
   }
 
+  /**
+   * Tests the tracking of nodes in link fields.
+   */
+  public function testLinkTracking() {
+    $page = $this->getSession()->getPage();
+    $assert_session = $this->assertSession();
+
+    /** @var \Drupal\entity_usage\EntityUsage $usage_service */
+    $usage_service = \Drupal::service('entity_usage.usage');
+
+    // Add a link field to our test content type.
+    $field_storage = FieldStorageConfig::create([
+      'field_name' => 'field_link1',
+      'entity_type' => 'node',
+      'type' => 'link',
+      'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
+      'settings' => [],
+    ]);
+    $field_storage->save();
+    $field = FieldConfig::create([
+      'field_storage' => $field_storage,
+      'bundle' => 'eu_test_ct',
+      'settings' => [
+        'title' => DRUPAL_OPTIONAL,
+        'link_type' => LinkItemInterface::LINK_GENERIC,
+      ],
+    ]);
+    $field->save();
+
+    entity_get_form_display('node', 'eu_test_ct', 'default')
+      ->setComponent('field_link1', ['type' => 'link_default'])
+      ->save();
+
+    entity_get_display('node', 'eu_test_ct', 'default')
+      ->setComponent('field_link1', ['type' => 'link'])
+      ->save();
+
+    // Create Node 1.
+    $this->drupalGet('/node/add/eu_test_ct');
+    $page->fillField('title[0][value]', 'Node 1');
+    $page->pressButton('Save');
+    $assert_session->pageTextContains('eu_test_ct Node 1 has been created.');
+    $this->saveHtmlOutput();
+    $node1_id = \Drupal::entityQuery('node')
+      ->sort('changed', 'DESC')
+      ->execute();
+    $node1_id = reset($node1_id);
+    $this->assertNotNull($node1_id);
+    $node1 = \Drupal::entityTypeManager()->getStorage('node')
+      ->loadUnchanged($node1_id);
+
+    // Create Node 2, referencing Node 1.
+    $this->drupalGet('/node/add/eu_test_ct');
+    $page->fillField('title[0][value]', 'Node 2');
+    $page->fillField('field_link1[0][uri]', "Node 1 ($node1_id)");
+    $page->fillField('field_link1[0][title]', "Linked text");
+    $page->pressButton('Save');
+    $assert_session->pageTextContains('eu_test_ct Node 2 has been created.');
+    $this->saveHtmlOutput();
+    $node2_id = \Drupal::entityQuery('node')
+      ->sort('changed', 'DESC')
+      ->execute();
+    $node2_id = reset($node2_id);
+    $this->assertNotNull($node2_id);
+    $node2 = \Drupal::entityTypeManager()->getStorage('node')
+      ->loadUnchanged($node2_id);
+    // Check that the usage of Node 1 points to Node 2.
+    $usage = $usage_service->listUsage($node1, TRUE);
+    $this->assertEquals([$node2_id => '1'], $usage['link']['node']);
+
+    // Edit Node 2, remove reference.
+    $this->drupalGet("/node/{$node2_id}/edit");
+    $page->fillField('field_link1[0][uri]', '');
+    $page->fillField('field_link1[0][title]', '');
+    $page->pressButton('Save');
+    $assert_session->pageTextContains('eu_test_ct Node 2 has been updated.');
+    $this->saveHtmlOutput();
+    // Verify the usage was released.
+    $usage = $usage_service->listUsage($node1);
+    $this->assertEquals([], $usage);
+
+    // Reference Node 1 again, and then delete the host node.
+    $this->drupalGet("/node/{$node2_id}/edit");
+    $page->fillField('field_link1[0][uri]', "Node 1 ($node1_id)");
+    $page->fillField('field_link1[0][title]', "Linked text");
+    $page->pressButton('Save');
+    $assert_session->pageTextContains('eu_test_ct Node 2 has been updated.');
+    $this->saveHtmlOutput();
+    // Usage now should be there.
+    $usage = $usage_service->listUsage($node1, TRUE);
+    $this->assertEquals([$node2_id => '1'], $usage['link']['node']);
+    // Delete the host and usage should be released.
+    $node2->delete();
+    $usage = $usage_service->listUsage($node1, TRUE);
+    $this->assertEquals([], $usage);
+  }
+
 }
