This is a really interesting question, as the behavior differs depending on whether you are using a page or a constant background page .
Note that this answer applies to the contextMenu API!
Permanent background page
You should just put your code at the top level.
Then it will be executed every time the background page of the extension is loaded.
If you have a constant background page, this is exactly what you want: do it once when the extension starts for any reason.
If you want you to not create a duplicate element, include the id attribute in create() .
Google has a matching sample .
Event Page
The event page is loaded much more often than usual, throughout the life of the extension. In general, the context menu API requires special treatment with event pages.
First of all, including the id attribute in contextMenus.create() is a requirement for event pages. In addition, since the code does not load in standby mode, you should use chrome.contextMenus.onClicked instead of the onclick attribute.
The documentation recommends using onInstalled :
If you need to do some initialization when your extension is installed or updated, listen for the runtime.onInstalled event. This is a good place to register for declarativeWebRequest rules, contextMenu entries, and other such one-time initializations.
In fact, what they do in the sample .
I tested it, and really context menus are saved through restarting the extension and browser. However, this difference is not explicitly documented.
Bug Alert! In response to Rob's comment about this error , the method is not 100% reliable if the extension is disabled.