> ## Documentation Index
> Fetch the complete documentation index at: https://docs.anchorage.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Operation tagging

> Create and apply tags to operations, filter the Operations tab by tag, and build tag-filtered reports.

export const ImageCarousel = ({images, perView = 3, thumbMaxWidth = 220, children}) => {
  const [page, setPage] = useState(0);
  const [imgH, setImgH] = useState(0);
  const [zoomIdx, setZoomIdx] = useState(null);
  const stripRef = useRef(null);
  const THUMB_MAX_WIDTH = thumbMaxWidth;
  const PEEK_WIDTH = 34;
  const STAGE_HEIGHT = 460;
  const fromChildren = React.Children.toArray(children).map(c => c && c.props && c.props.src ? {
    src: c.props.src,
    alt: c.props.alt
  } : null).filter(Boolean);
  const items = fromChildren.length ? fromChildren : images || [];
  const count = items.length;
  const columns = Math.min(perView, count) || 1;
  const totalPages = Math.ceil(count / columns);
  const showControls = totalPages > 1;
  const goTo = p => setPage((p % totalPages + totalPages) % totalPages);
  const prev = () => goTo(page - 1);
  const next = () => goTo(page + 1);
  const zoomTo = i => {
    const idx = (i % count + count) % count;
    setZoomIdx(idx);
    setPage(Math.floor(idx / columns));
  };
  useEffect(() => {
    if (zoomIdx === null) return;
    const item = items[zoomIdx];
    const overlay = document.createElement("div");
    overlay.setAttribute("role", "dialog");
    overlay.setAttribute("aria-modal", "true");
    overlay.setAttribute("aria-label", item.alt || "Screenshot");
    Object.assign(overlay.style, {
      position: "fixed",
      top: "0",
      left: "0",
      right: "0",
      bottom: "0",
      zIndex: "2147483000",
      background: "rgba(5, 5, 5, 0.98)",
      display: "flex",
      alignItems: "center",
      justifyContent: "center",
      padding: "24px 72px",
      cursor: "zoom-out"
    });
    const img = document.createElement("img");
    img.src = item.src;
    img.alt = item.alt || "";
    Object.assign(img.style, {
      maxWidth: "94vw",
      maxHeight: "88vh",
      width: "auto",
      height: "auto",
      borderRadius: "10px",
      boxShadow: "0 8px 40px rgba(0, 0, 0, 0.5)",
      cursor: "zoom-out"
    });
    overlay.appendChild(img);
    const makeButton = (label, text, position) => {
      const b = document.createElement("button");
      b.type = "button";
      b.setAttribute("aria-label", label);
      b.textContent = text;
      Object.assign(b.style, {
        position: "absolute",
        width: "40px",
        height: "40px",
        borderRadius: "50%",
        border: "1px solid rgba(255, 255, 255, 0.35)",
        background: "rgba(255, 255, 255, 0.16)",
        color: "#fff",
        fontSize: "20px",
        lineHeight: "38px",
        textAlign: "center",
        cursor: "pointer",
        padding: "0"
      }, position);
      overlay.appendChild(b);
      return b;
    };
    const closeButton = makeButton("Close", "×", {
      top: "18px",
      right: "18px"
    });
    let prevButton = null;
    let nextButton = null;
    if (count > 1) {
      prevButton = makeButton("Previous screenshot", "‹", {
        left: "18px",
        top: "calc(50% - 20px)"
      });
      nextButton = makeButton("Next screenshot", "›", {
        right: "18px",
        top: "calc(50% - 20px)"
      });
      const counter = document.createElement("div");
      counter.textContent = `${zoomIdx + 1} of ${count}`;
      Object.assign(counter.style, {
        position: "absolute",
        bottom: "16px",
        left: "0",
        right: "0",
        textAlign: "center",
        fontSize: "13px",
        color: "rgba(255, 255, 255, 0.85)"
      });
      overlay.appendChild(counter);
    }
    const close = () => setZoomIdx(null);
    overlay.addEventListener("click", e => {
      if (e.target === prevButton || e.target === nextButton) return;
      close();
    });
    if (prevButton) prevButton.addEventListener("click", () => zoomTo(zoomIdx - 1));
    if (nextButton) nextButton.addEventListener("click", () => zoomTo(zoomIdx + 1));
    const onKey = e => {
      if (e.key === "Escape") close(); else if (e.key === "ArrowLeft") zoomTo(zoomIdx - 1); else if (e.key === "ArrowRight") zoomTo(zoomIdx + 1);
    };
    window.addEventListener("keydown", onKey);
    const previousOverflow = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    document.body.appendChild(overlay);
    closeButton.focus();
    return () => {
      window.removeEventListener("keydown", onKey);
      document.body.style.overflow = previousOverflow;
      overlay.remove();
    };
  }, [zoomIdx]);
  useEffect(() => {
    const strip = stripRef.current;
    if (!strip) return;
    const measure = () => {
      const box = strip.querySelector("[data-carousel-imgbox]");
      if (box && box.clientHeight) setImgH(box.clientHeight);
    };
    measure();
    const ro = new ResizeObserver(measure);
    ro.observe(strip);
    return () => ro.disconnect();
  }, []);
  if (!items.length) return null;
  const start = page * columns;
  const visible = items.slice(start, start + columns);
  const zoomBtnStyle = {
    position: "absolute",
    zIndex: 2,
    width: "40px",
    height: "40px",
    borderRadius: "50%",
    border: "1px solid rgba(255, 255, 255, 0.3)",
    background: "rgba(255, 255, 255, 0.14)",
    color: "#fff",
    fontSize: "20px",
    lineHeight: "38px",
    textAlign: "center",
    cursor: "pointer",
    padding: 0
  };
  const pager = showControls ? <div style={{
    textAlign: "center",
    marginTop: "8px",
    fontSize: "12px",
    color: "var(--ad-muted, #6b7280)"
  }}>
      {start + 1}
      {visible.length > 1 ? "–" + (start + visible.length) : ""} of {count}
    </div> : null;
  if (perView === 1) {
    const img = items[page];
    const overlayArrow = side => {
      const isLeft = side === "left";
      return <button type="button" onClick={isLeft ? prev : next} aria-label={isLeft ? "Previous screenshot" : "Next screenshot"} style={{
        position: "absolute",
        top: "50%",
        transform: "translateY(-50%)",
        [isLeft ? "left" : "right"]: "10px",
        zIndex: 2,
        width: "36px",
        height: "36px",
        borderRadius: "50%",
        border: "1px solid var(--ad-border, #e4e5e7)",
        background: "var(--background, #fff)",
        boxShadow: "0 1px 6px rgba(0, 0, 0, 0.25)",
        fontSize: "18px",
        lineHeight: "34px",
        textAlign: "center",
        cursor: "pointer",
        padding: 0
      }}>
          {isLeft ? "‹" : "›"}
        </button>;
    };
    return <div style={{
      outline: "none",
      margin: "1.5rem 0"
    }} role={showControls ? "group" : undefined} aria-label={showControls ? "Screenshot carousel" : undefined} aria-roledescription={showControls ? "carousel" : undefined}>
        <div style={{
      position: "relative"
    }}>
          <div style={{
      height: STAGE_HEIGHT + "px",
      display: "flex",
      alignItems: "center",
      justifyContent: "center"
    }}>
            <button type="button" onClick={() => setZoomIdx(page)} aria-label={"Enlarge: " + (img.alt || "screenshot")} style={{
      display: "block",
      maxWidth: "100%",
      maxHeight: "100%",
      border: 0,
      padding: 0,
      background: "none",
      cursor: "zoom-in"
    }}>
              <img src={img.src} alt={img.alt ?? ""} style={{
      display: "block",
      maxWidth: "100%",
      maxHeight: STAGE_HEIGHT + "px",
      width: "auto",
      height: "auto",
      margin: "0 auto",
      borderRadius: "10px",
      border: "1px solid var(--ad-border, #e4e5e7)"
    }} />
            </button>
          </div>

          {showControls && overlayArrow("left")}
          {showControls && overlayArrow("right")}
        </div>

        {img.alt && <div style={{
      marginTop: "8px",
      fontSize: "13px",
      lineHeight: 1.4,
      color: "var(--ad-muted, #6b7280)",
      textAlign: "center"
    }}>
            {img.alt}
          </div>}

        {pager}
      </div>;
  }
  const prevPeek = start > 0 ? items[start - 1] : null;
  const nextPeek = start + columns < count ? items[start + columns] : null;
  const renderPeek = (img, side) => {
    if (!img) return null;
    const isLeft = side === "left";
    return <button type="button" onClick={isLeft ? prev : next} aria-hidden="true" tabIndex={-1} style={{
      flex: `0 0 ${PEEK_WIDTH}px`,
      width: PEEK_WIDTH + "px",
      alignSelf: imgH ? "flex-start" : "stretch",
      height: imgH ? imgH + "px" : undefined,
      border: 0,
      padding: 0,
      cursor: "pointer",
      opacity: 0.5,
      borderRadius: isLeft ? "10px 0 0 10px" : "0 10px 10px 0",
      backgroundImage: `url("${img.src}")`,
      backgroundRepeat: "no-repeat",
      backgroundSize: "auto 100%",
      backgroundPosition: isLeft ? "right center" : "left center",
      WebkitMaskImage: `linear-gradient(to ${isLeft ? "left" : "right"}, #000 15%, transparent 100%)`,
      maskImage: `linear-gradient(to ${isLeft ? "left" : "right"}, #000 15%, transparent 100%)`
    }} />;
  };
  const arrowStyle = {
    flex: "0 0 auto",
    width: "30px",
    height: "30px",
    borderRadius: "50%",
    border: "1px solid var(--ad-border, #e4e5e7)",
    background: "var(--background, #fff)",
    fontSize: "16px",
    lineHeight: "28px",
    textAlign: "center",
    cursor: "pointer",
    padding: 0
  };
  return <div style={{
    outline: "none",
    margin: "1.5rem 0"
  }} role={showControls ? "group" : undefined} aria-label={showControls ? "Screenshot carousel" : undefined} aria-roledescription={showControls ? "carousel" : undefined}>
      <div style={{
    display: "flex",
    alignItems: "center",
    gap: "10px"
  }}>
        {showControls && <button type="button" onClick={prev} aria-label="Previous screenshots" style={arrowStyle}>
            ‹
          </button>}

        <div ref={stripRef} style={{
    display: "flex",
    flexWrap: "nowrap",
    alignItems: "flex-start",
    gap: "14px",
    justifyContent: "center",
    flex: 1
  }}>
          {renderPeek(prevPeek, "left")}
          {}
          {Array.from({
    length: columns
  }).map((_, i) => {
    const img = visible[i];
    const slotStyle = {
      margin: 0,
      flex: "1 1 0",
      maxWidth: THUMB_MAX_WIDTH + "px",
      minWidth: 0
    };
    if (!img) {
      return <div key={start + i} aria-hidden="true" style={{
        ...slotStyle,
        visibility: "hidden"
      }} />;
    }
    return <div key={start + i} style={slotStyle}>
                <button type="button" data-carousel-imgbox onClick={() => setZoomIdx(start + i)} aria-label={"Enlarge: " + (img.alt || "screenshot")} style={{
      display: "block",
      width: "100%",
      border: 0,
      padding: 0,
      background: "none",
      cursor: "zoom-in"
    }}>
                  <img src={img.src} alt={img.alt ?? ""} style={{
      display: "block",
      maxWidth: "100%",
      maxHeight: Math.round(THUMB_MAX_WIDTH * 1.4) + "px",
      width: "auto",
      height: "auto",
      margin: "0 auto",
      borderRadius: "10px",
      border: "1px solid var(--ad-border, #e4e5e7)"
    }} />
                </button>
                {img.alt && <div style={{
      marginTop: "6px",
      fontSize: "12px",
      lineHeight: 1.4,
      color: "var(--ad-muted, #6b7280)",
      textAlign: "center"
    }}>
                    {img.alt}
                  </div>}
              </div>;
  })}
          {renderPeek(nextPeek, "right")}
        </div>

        {showControls && <button type="button" onClick={next} aria-label="Next screenshots" style={arrowStyle}>
            ›
          </button>}
      </div>

      {pager}
    </div>;
};

Tags let your organization label operations with your own categories—for example, by desk, strategy, or client—so they're easier to find, filter, and report on later. You can add tags when you initiate an operation or at any time afterward, and each operation can carry up to 10 tags.

## Adding tags when initiating an operation

Tags are added on the **Preview operation** screen, after you've entered the operation details.

<Steps>
  <Step title="Go to the preview screen">
    Initiate the operation and enter its details as usual. On the **Preview operation** screen, find the **Tags** section and its **Add tags** bar.
  </Step>

  <Step title="Select existing tags">
    Select the **Add tags** bar to open your organization's library of existing tags. Search for and select the tags you want to apply.
  </Step>

  <Step title="Create a new tag">
    To create a tag that doesn't exist yet, type its name in the search field, then select **Create** or press Enter.
  </Step>

  <Step title="Remove a tag if needed">
    Select the **x** on a tag pill in the bar to remove it.
  </Step>

  <Step title="Submit the operation">
    Select **Confirm and submit for approval**. Everyone in the approval quorum sees the applied tags when reviewing the operation.
  </Step>
</Steps>

<ImageCarousel perView={1}>
  <img src="https://mintcdn.com/deployment-4/_09Sc2PFC3CsQaF1/knowledge-base/images/screenshots/anchorage-operation-tagging-preview.jpg?fit=max&auto=format&n=_09Sc2PFC3CsQaF1&q=85&s=f4fb9a494c5d15060761eff40465b0e8" alt="Preview operation screen showing the Tags section with an empty Add tags bar" width="2880" height="1800" data-path="knowledge-base/images/screenshots/anchorage-operation-tagging-preview.jpg" />

  <img src="https://mintcdn.com/deployment-4/_09Sc2PFC3CsQaF1/knowledge-base/images/screenshots/anchorage-operation-tagging-library.jpg?fit=max&auto=format&n=_09Sc2PFC3CsQaF1&q=85&s=42df9b75a4dbe878b98c61b640718d65" alt="Tag library open under the Add tags bar with a tag selected and the cursor over the list" width="2880" height="1800" data-path="knowledge-base/images/screenshots/anchorage-operation-tagging-library.jpg" />

  <img src="https://mintcdn.com/deployment-4/_09Sc2PFC3CsQaF1/knowledge-base/images/screenshots/anchorage-operation-tagging-create.jpg?fit=max&auto=format&n=_09Sc2PFC3CsQaF1&q=85&s=78aae9434a2c01cd974caf19f133f794" alt="Text typed into the tag search field showing matching tags and the Create option" width="2880" height="1800" data-path="knowledge-base/images/screenshots/anchorage-operation-tagging-create.jpg" />

  <img src="https://mintcdn.com/deployment-4/_09Sc2PFC3CsQaF1/knowledge-base/images/screenshots/anchorage-operation-tagging-remove.jpg?fit=max&auto=format&n=_09Sc2PFC3CsQaF1&q=85&s=a047e0a3649b33efcbd58f46b0d439e1" alt="Cursor over the x on a tag pill in the Tags bar" width="2880" height="1800" data-path="knowledge-base/images/screenshots/anchorage-operation-tagging-remove.jpg" />

  <img src="https://mintcdn.com/deployment-4/_09Sc2PFC3CsQaF1/knowledge-base/images/screenshots/anchorage-operation-tagging-quorum-ios.jpg?fit=max&auto=format&n=_09Sc2PFC3CsQaF1&q=85&s=ce2881da03c7e69fed8c6712e301e193" alt="Approvers see the operation's tags during quorum review in the iOS app" width="750" height="1624" data-path="knowledge-base/images/screenshots/anchorage-operation-tagging-quorum-ios.jpg" />
</ImageCarousel>

## Viewing and editing tags on an existing operation

Select an operation in the **Operations** tab to open its details panel and see the tags applied to it. From there, you can add more tags from the **Tags** bar or remove tags by selecting the **x** on a tag pill—the same way as during initiation, with the same 10-tag maximum.

Changes to tags save to the operation automatically as you add or remove them.

<ImageCarousel perView={1}>
  <img src="https://mintcdn.com/deployment-4/_09Sc2PFC3CsQaF1/knowledge-base/images/screenshots/anchorage-operation-tagging-existing.png?fit=max&auto=format&n=_09Sc2PFC3CsQaF1&q=85&s=87e6f9ea9a4ca27e45f3c5312ff5dbbc" alt="Tags on a completed operation's details panel" width="2848" height="1779" data-path="knowledge-base/images/screenshots/anchorage-operation-tagging-existing.png" />
</ImageCarousel>

## Filtering operations by tag

<Steps>
  <Step title="Open the Operations tab">
    Navigate to the **Operations** tab.
  </Step>

  <Step title="Add a tag filter">
    Select **Add filter**, then **Tags**.
  </Step>

  <Step title="Select the tags to filter by">
    Select one or more tags. The table updates to show matching operations, and the active filter appears as a pill above the table.
  </Step>
</Steps>

Selecting multiple tags shows every operation that carries any of the selected tags—an operation only needs to match one of them to appear. To remove filters, select the **x** on a filter pill or select **Clear all filters**.

<ImageCarousel perView={1}>
  <img src="https://mintcdn.com/deployment-4/_09Sc2PFC3CsQaF1/knowledge-base/images/screenshots/anchorage-operation-tagging-filter-menu.png?fit=max&auto=format&n=_09Sc2PFC3CsQaF1&q=85&s=bcef1f3e050597615e7bec4f75ec8849" alt="Operations tab with the Add filter menu open and the cursor over Tags" width="2880" height="1800" data-path="knowledge-base/images/screenshots/anchorage-operation-tagging-filter-menu.png" />

  <img src="https://mintcdn.com/deployment-4/_09Sc2PFC3CsQaF1/knowledge-base/images/screenshots/anchorage-operation-tagging-filter-applied.png?fit=max&auto=format&n=_09Sc2PFC3CsQaF1&q=85&s=5ad9821cbfb3dbcae1fde5b491d200aa" alt="Operations tab with type and tag filter pills applied and the filtered results displayed" width="2880" height="1800" data-path="knowledge-base/images/screenshots/anchorage-operation-tagging-filter-applied.png" />
</ImageCarousel>

## Creating a report filtered by tag

You can use tags as a filter when building a transaction report in the [Reporting](/knowledge-base/platform/users/web-dashboard/reporting) section.

<Steps>
  <Step title="Create a new report">
    Go to the **Reporting** section and select **Create new report**.
  </Step>

  <Step title="Choose the report type">
    Select **Transaction Report** as the report type, then enter your desired inputs, such as the report name, format, and date range.
  </Step>

  <Step title="Add a tag filter">
    Select **Add filter**, then **Tags**, and select the tags you want the report to cover. As with operation filtering, multiple tags match operations that carry any of the selected tags.
  </Step>

  <Step title="Create the report">
    Select **Create report**. The generated report includes a **Tag Names** column listing the tags that apply to each transaction.
  </Step>
</Steps>

<ImageCarousel perView={1}>
  <img src="https://mintcdn.com/deployment-4/_09Sc2PFC3CsQaF1/knowledge-base/images/screenshots/anchorage-operation-tagging-report-filter-menu.png?fit=max&auto=format&n=_09Sc2PFC3CsQaF1&q=85&s=8503d4175db1704c334e2937b09b744b" alt="Create new report modal with the Add filter menu open and the cursor over Tags" width="2880" height="1800" data-path="knowledge-base/images/screenshots/anchorage-operation-tagging-report-filter-menu.png" />

  <img src="https://mintcdn.com/deployment-4/_09Sc2PFC3CsQaF1/knowledge-base/images/screenshots/anchorage-operation-tagging-report-tags.png?fit=max&auto=format&n=_09Sc2PFC3CsQaF1&q=85&s=73422c66d0c9f4b876d782c99d72438d" alt="Create new report modal showing the tag list with checkboxes in the filter" width="2880" height="1800" data-path="knowledge-base/images/screenshots/anchorage-operation-tagging-report-tags.png" />
</ImageCarousel>

<ImageCarousel perView={1}>
  <img src="https://mintcdn.com/deployment-4/_09Sc2PFC3CsQaF1/knowledge-base/images/screenshots/anchorage-operation-tagging-report-column.png?fit=max&auto=format&n=_09Sc2PFC3CsQaF1&q=85&s=1504b6a0687105ed2f941fa7567fbbc6" alt="The Tag Names column in a generated transaction report" width="2880" height="1800" data-path="knowledge-base/images/screenshots/anchorage-operation-tagging-report-column.png" />
</ImageCarousel>

## Related topics

* [Operations](/knowledge-base/platform/users/web-dashboard/operations) — View, filter, and download pending and past account operations
* [Reporting](/knowledge-base/platform/users/web-dashboard/reporting) — View statements and download balance and transaction reports


## Related topics

- [Operations](/knowledge-base/platform/users/web-dashboard/operations.md)
- [Reporting](/knowledge-base/platform/users/web-dashboard/reporting.md)
- [Overview](/knowledge-base/platform/developers/webhooks/webhooks-overview.md)
- [API Changelog](/knowledge-base/porto/api-reference/changelog.md)
