The method selected partially depends on what the input signal does, how it behaves and how that might effect the input circuit and the code that reads it?
e.g. Is it always 12V? Does it have spikes or noise? How much current can it drive? Can current be driven into it? Will taking current from it affect anything else? Is it safety critical?....
Because of this there can never be a universal answer to this question as the 'correct' solution depends on what the rest of the system does.
The chosen solution that meets the requirements will have differing cost and complexity.
That said, as nobody else has yet suggested it, I'll go for a FET input.
A JFET or MOSFET can be used and either could be common source or common drain modes. For example, common drain:
simulate this circuit – Schematic created using CircuitLab
The advantage of the common drain mode is that it allows the input to be connected to both an analogue (e.g. ADC) or a digital pin. If the signal is truly digital I would enable the schmitt trigger on the CPU input (if it has one), or add an external schmitt buffer to the CPU's input pin.
Advantages
- Very high input impedance
- Partially isolated input (can withstand +/- 30V, depending on FET selection)
- Analogue possible
- Minimal effect on external signal