If you have ever wondered who changed a field on an Odoo record and when, the tracking feature is your answer.
Odoo allows you to monitor changes on specific fields and record each modification directly in the chatter of the record. This gives teams full visibility into how business data evolves over time, without building a separate audit system.
Whether you are configuring Odoo Studio fields or writing a custom Python module, understanding how field tracking works is a core part of working with the Odoo data model. This guide walks you through everything you need to know.
What is the Tracking Field in Odoo
In Odoo, tracking is not a field type by itself. It is an attribute you can enable on existing fields, such as Char, Many2one, Selection, Integer, or Date fields. When tracking is active on a field, Odoo records every value change in the chatter, displaying the old value, the new value, the date, and the user responsible.
This shows up in the interface as a log note in the record's message thread. For example, on a CRM lead you might see: "Stage changed from New to Qualified", logged automatically the moment a sales rep moves the deal forward.
The tracking attribute is available on most standard Odoo field types and can be enabled through Odoo Studio or directly in Python code as part of a custom odoo development project.
What Data Does It Store
Each tracked change is stored as a mail.message record linked to the document. The message contains:
- The field label that changed
- The previous value (before the change)
- The new value (after the change)
- The timestamp of the modification
- The user who made the change
This history is always visible to anyone with read access to the record. It does not require any additional configuration beyond enabling tracking on the field.
How the Field Works
For tracking to work, the model must use the mail.thread mixin. This mixin provides the messaging and logging infrastructure that powers the chatter. Most standard Odoo business models, including sale.order, crm.lead, account.move, and stock.picking, already inherit from mail.thread.
When a user saves a record that has changed tracked fields, Odoo compares the old and new values and writes a log message to the chatter automatically. No additional action is required from the user.
Technical Behavior in the Odoo ORM
From a technical standpoint, the Odoo ORM intercepts writes at the model level. When a write() call modifies a tracked field, the framework captures the previous value, applies the change, then creates a mail.message record describing the difference.
In Python, tracking is enabled by adding tracking=True to a field definition in your odoo python fields setup:
state = fields.Selection(
[('draft', 'Draft'), ('confirmed', 'Confirmed')],
tracking=True
)
You can also use a priority number from 1 to 10 to control the display order when multiple tracked fields change in the same save operation. Lower numbers appear first in the log message:
partner_id = fields.Many2one('res.partner', tracking=1)
priority = fields.Selection(tracking=10)
Interaction with Other Records
Tracked changes are stored directly on the record where the field lives. They do not propagate to related records automatically. If you want tracking across related models, you need to enable it separately on each model where it matters.
This is by design. The Odoo data model keeps the audit trail close to the object being modified, which makes it easy to review the history without navigating through multiple related records.
Business Use Cases
Here are five practical examples where enabling field tracking adds real value in day-to-day operations.
1. CRM and Sales Pipeline Management
Sales teams need to know when a lead moved from one stage to another and who made that change. Enabling tracking on the stage_id field in the CRM module gives managers a complete timeline of every status transition.
This helps identify where deals stall, supports pipeline reviews, and makes it easier to coach sales reps based on actual data rather than memory.
2. Purchase and Invoice Approval Workflows
In accounting and procurement, audit compliance often requires knowing who approved a document and when. Tracking the state field on purchase orders or vendor bills makes this history immediately available in the chatter without needing a separate audit module.
This is especially useful in companies subject to financial controls or internal audit requirements.
3. Inventory and Stock Management
When product quantities or storage locations change unexpectedly, tracking fields on stock moves or products helps warehouse managers identify the source of discrepancies quickly.
Rather than digging through logs or asking colleagues, the answer is right there in the chatter of the relevant record.
4. Customer Data Quality Management
If your team regularly updates customer records, you can track changes to critical fields like email, phone, or pricelist_id on the partner model. This maintains a history of contact data changes directly in the CRM, which is useful for customer service teams and data quality reviews.
5. HR and Employee Records
Tracking changes to fields like job position, department, or salary grade on employee records ensures a transparent history of any modifications. This is important for HR compliance in many industries and makes internal audits significantly easier to conduct.
Creating or Customizing the Tracking Field
There are two main ways to enable tracking on a field in Odoo: using Odoo Studio for a no-code approach, or writing Python code for a fully technical implementation.
Using Odoo Studio
Odoo Studio makes it straightforward to enable tracking on existing fields without writing any code. Open Studio on the relevant model, click on the field you want to monitor, and look for the Track Changes toggle in the field settings panel.
Once enabled, all future changes to that field will appear in the chatter. This is the recommended approach for administrators and business users who want to add tracking as part of their odoo customization workflow, without involving a developer.
The same Studio interface can be used when you create fields in Odoo from scratch. When adding a new custom field through Studio, you can toggle tracking on right during field creation.
Using Python in a Custom Module
For developers building or extending modules, the tracking attribute is added directly to the field definition in the model class. This is standard practice in any odoo developer guide or odoo technical tutorial.
The model must also inherit from mail.thread for tracking to have any effect. Here is a minimal example:
from odoo import models, fields
class ProjectTask(models.Model):
_name = 'project.task'
_inherit = ['project.task', 'mail.thread']
x_client_priority = fields.Selection(
[('low', 'Low'), ('medium', 'Medium'), ('high', 'High')],
string='Client Priority',
tracking=True
)
This is a typical pattern when you need to extend an existing model as part of an odoo development project. The field behaves like any other odoo database fields entry, but now every change to its value is automatically recorded.
Important Note on Custom Models
When creating entirely new custom models, make sure to include _inherit = ['mail.thread', 'mail.activity.mixin'] in your model definition. Without this, the tracking attribute will be silently ignored and no changes will be recorded in the chatter.
This is a point that trips up many developers following an odoo field tutorial for the first time. The mixin is not optional if you want tracking to work.
Best Practices
Tracking fields is easy to set up but easy to misuse. These guidelines will help you get the most out of the feature.
Only Track Fields That Matter
Enabling tracking on every field creates noise in the chatter and makes it harder to find relevant history. Focus on fields that are genuinely useful to audit: states, stages, responsible users, key dates, and financial values.
Use Priority Numbers for Clarity
When multiple fields are tracked on the same model, use priority numbers from 1 to 10 to control how changes are grouped in the log message. This improves readability in the chatter, especially on models with many tracked fields.
Combine with Access Rights
Tracking is most useful when combined with proper record rules and access controls. There is little value in maintaining an audit trail if everyone in the system can modify it freely. Secure your data model before relying on the chatter as an audit mechanism.
Document Your Tracked Fields
Keep a clear record of which fields have tracking enabled, especially in shared or multi-developer projects. This avoids confusion during code reviews and prevents accidental double-tracking after module upgrades.
Test Before Going Live
Always verify tracking behavior in a staging environment before deploying to production. Some field types, particularly computed or related fields, may behave differently from standard stored fields when tracking is involved.
Common Pitfalls
These are the mistakes that come up most often when working with field tracking in Odoo.
Forgetting to Inherit from mail.thread
This is the most frequent issue. If a custom model does not inherit from mail.thread, the tracking attribute will be silently ignored. No error is raised and no log messages will appear in the chatter. Always verify the model's inheritance chain when tracking does not seem to work.
Tracking Non-Stored Computed Fields
Computed fields can be tracked, but only if they are stored using store=True. A non-stored computed field has no persistent value in the odoo database fields, so there is nothing to compare before and after a change. If you try to track a non-stored computed field, tracking will silently have no effect.
Enabling Tracking on Too Many Fields
It is tempting to enable tracking everywhere to maximize transparency. In practice, this clutters the chatter and makes it genuinely harder to find meaningful changes. Be selective and focus on fields with real audit or operational value.
Expecting Tracking in Bulk or Direct SQL Operations
Tracking is triggered through the Odoo ORM when records are modified using the standard write() method. Direct SQL updates, bulk imports that bypass the ORM, or certain low-level API calls will not trigger tracking. If you use the XML-RPC API or batch operations, verify that writes go through the ORM layer.
Conflicts Between Studio and Python Definitions
If a field was originally created and configured in Odoo Studio with tracking enabled, be careful when also modifying the same field in a Python module. Conflicting definitions between Studio and code can lead to unexpected behavior during module upgrades or database updates.
FAQ
Can I track a field on any model in Odoo?
Only models that inherit from mail.thread support field tracking. Most standard business models in Odoo already include this mixin, but custom models need to explicitly declare it in their class definition.
Will enabling tracking affect performance?
The impact is minimal for most use cases. Each tracked change creates a mail.message record, which adds a small overhead to the write operation. For very high-volume transactional models, be thoughtful about how many fields you track to avoid creating an excessive number of log records.
Can I disable tracking on a field without losing existing history?
Yes. Disabling tracking stops recording new changes, but all existing log messages in the chatter remain accessible. The history already captured is preserved and will not be deleted.
Does tracking work on Many2many fields?
Many2many field tracking is supported in Odoo. The chatter displays which records were added or removed from the relation, rather than showing a before and after value. It works, but keep in mind the display format is different from simple value fields.
Can I use tracking without Odoo Studio?
Absolutely. The tracking parameter is a standard Python field attribute in the Odoo framework. You can enable it in any custom module without using Studio at all. Studio simply provides a visual, no-code interface for the same underlying functionality. This is a standard part of any odoo field tutorial or odoo developer guide.
Conclusion
The tracking attribute is one of those Odoo features that quietly adds a lot of value without requiring much setup. By enabling it on the right fields, you give your team a reliable audit trail, reduce disputes about who changed what, and build a foundation for better data governance across your organization.
Whether you configure it through Odoo Studio for a fast no-code setup, or implement it through a custom Python module as part of a broader odoo development or odoo customization project, the result is the same: full visibility into how your business data changes over time.
The key is knowing where to apply it. Focus on the fields that drive decisions, approvals, and accountability in your workflows, and you will get most of the value with very little effort.
At Dasolo, we help companies implement, customize, and optimize Odoo to fit their specific business processes. Whether you need help designing your data model, enabling field tracking across your workflows, or building custom modules from scratch, our team is here to support you.
Reach out to us today to discuss your Odoo implementation. Contact us and let's figure out the best approach for your project together.