Gathering of list

As requested by the OP:

Normal[GroupBy[data, First -> Last]] /. Rule -> List
   {{"bird", {1, 8, 14}}, {"cow", {2, 3, 5, 6, 7}}, {"dog", {4, 9, 11, 13}},
    {"cat", {10}}, {"pig", {12, 15}}}

The handy bit here is the second argument of GroupBy[]:

GroupBy[data, First -> Last]
   <|"bird" -> {1, 8, 14}, "cow" -> {2, 3, 5, 6, 7}, "dog" -> {4, 9, 11, 13},
     "cat" -> {10}, "pig" -> {12, 15}|>

which transforms the values associated with the keys into the desired list of numbers. Contrast this with a plain GroupBy[data, First].

As noted by multiple people, a more compact version is

List @@@ Normal[GroupBy[data, First -> Last]]

Tom in a comment below gives a slicker version:

KeyValueMap[List, GroupBy[data, First -> Last]]

The GatherBy[] approach presented by the OP can also be written as

Append[Union[#[[All, 1]]], #[[All, 2]]] & /@ GatherBy[data, First]

or as

Append @@ MapAt[Union, Transpose[#], 1] & /@ GatherBy[data, First]

I think this is one of the simplest here, both conceptually and in code:

Reap[Sow @@@ Reverse[data, {2}], _, List][[2]]

MapAt[#[[1]]&, Transpose/@ GatherBy[data, First], {;; , 1}]

{{"bird", {1, 8, 14}}, {"cow", {2, 3, 5, 6, 7}}, {"dog", {4, 9, 11, 13}}, {"cat", {10}}, {"pig", {12, 15}}}

Edit Corrected by murray, aka OP:

MapAt[Last, Transpose/@ GatherBy[data, First], {;; , 1}]

Edit2 Just for the ad hoc case with specific numeration PositionIndex:

List @@@ Normal @ PositionIndex[data[[All, 1]]]