{"id":15069971,"url":"https://github.com/amplitude/react-amplitude","last_synced_at":"2025-10-05T06:31:33.845Z","repository":{"id":40790817,"uuid":"116755809","full_name":"amplitude/react-amplitude","owner":"amplitude","description":"A React component library for easy product analytics instrumentation (deprecated)","archived":true,"fork":false,"pushed_at":"2023-01-25T07:00:13.000Z","size":1103,"stargazers_count":118,"open_issues_count":29,"forks_count":14,"subscribers_count":82,"default_branch":"master","last_synced_at":"2024-09-30T13:22:33.512Z","etag":null,"topics":["amplitude","analytics","javascript","js","react"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/amplitude.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-01-09T02:36:48.000Z","updated_at":"2024-04-03T08:08:58.000Z","dependencies_parsed_at":"2023-02-14T05:31:53.169Z","dependency_job_id":null,"html_url":"https://github.com/amplitude/react-amplitude","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amplitude%2Freact-amplitude","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amplitude%2Freact-amplitude/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amplitude%2Freact-amplitude/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amplitude%2Freact-amplitude/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/amplitude","download_url":"https://codeload.github.com/amplitude/react-amplitude/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235370461,"owners_count":18979093,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["amplitude","analytics","javascript","js","react"],"created_at":"2024-09-25T01:46:02.184Z","updated_at":"2025-10-05T06:31:28.563Z","avatar_url":"https://github.com/amplitude.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# react-amplitude\n\n[![Travis](https://img.shields.io/travis/amplitude/react-amplitude.svg?style=flat-square)](https://travis-ci.org/amplitude/react-amplitude)\n[![npm](https://img.shields.io/npm/v/@amplitude/react-amplitude.svg?style=flat-square)](https://www.npmjs.com/package/@amplitude/react-amplitude)\n\nA React component library for easy product analytics instrumentation.\n\n\n## Project Status\n\nreact-amplitude is not an officially supported Amplitude SDK or library, and deprecated now.\n\nPlease use our offical [Typescript SDK](https://github.com/amplitude/Amplitude-TypeScript) to track with React!\n\n## The problems with traditional, imperative event-based logging\n\n- Contextual event information (i.e. \"event properties\") often require lots of plumbing to the code path where the events are logged, requiring more code and breaking encapsulation.\n- Similarly, it can be difficult to provide contextual information to events fired in low-level, reusable components (e.g. Buttons, Dropdowns, Links, etc.).\n- Traditional event-based analytics logging often use imperative APIs, which can sometimes require more code and be more painful when writing declarative React components.\n\n## The problems with \"autotrack\" solutions\n\n- Autotrack solutions can be unreliable, as they may depend on attributes that engineers may unintentionally change (like CSS selectors).\n- Autotrack solutions may unintentionally track sensitive user data.\n- Autotrack can't capture all kinds of events, so you may end up requiring to implement manual event logging.\n\n## The solution\n\nreact-amplitude has a modern, declarative API to make it easy to instrument new events and properties with Amplitude. It takes advantage of core React features to propagate contextual information down through the component hierarchy. This makes it far less painful to add new event properties to existing events.\n\nUnlike \"autotrack\" solutions, react-amplitude does require _some_ code changes in order to start sending data to Amplitude. However, it aims to minimize the amount of code required to start collecting data and make instrumentation seem less like a chore.\n\nIf you use common reusable components in your React application like Buttons, Dropdowns, Links, etc., you should be able to achieve \"autotrack\"-like instrumentation with just a few lines of code. And from there, it can be really simple to instrument new properties and context throughout your application, giving you the same flexibility as manual event logging.\n\n## Example: Instrumenting Tic-Tac-Toe (From Facebook's [Intro to React Tutorial](https://reactjs.org/tutorial/tutorial.html))\n\nEvents logged:\n - start game\n - game won\n - click square\n - jump to move\n - go to game start\n\n Event properties:\n - scope (array; \"square\", \"history\", \"game\")\n - moves made (number)\n - winner (\"X\" or \"O\")\n - current player (\"X\" or \"O\")\n \n\n```jsx\nimport React from \"react\";\nimport { render } from \"react-dom\";\nimport amplitude from \"amplitude-js\";\nimport {\n  AmplitudeProvider,\n  Amplitude,\n  LogOnMount\n} from \"@amplitude/react-amplitude\";\n\nconst AMPLITUDE_KEY = \"\";\n\nfunction Square(props) {\n  return (\n    \u003cAmplitude\n      eventProperties={inheritedProps =\u003e ({\n        ...inheritedProps,\n        scope: [...inheritedProps.scope, \"square\"]\n      })}\n    \u003e\n      {({ instrument }) =\u003e (\n        \u003cbutton\n          className=\"square\"\n          onClick={instrument(\"click square\", props.onClick)}\n        \u003e\n          {props.value}\n        \u003c/button\u003e\n      )}\n    \u003c/Amplitude\u003e\n  );\n}\n\nclass Board extends React.Component {\n  renderSquare(i) {\n    return (\n      \u003cSquare\n        value={this.props.squares[i]}\n        onClick={() =\u003e this.props.onClick(i)}\n      /\u003e\n    );\n  }\n\n  render() {\n    return (\n      \u003cdiv\u003e\n        \u003cdiv className=\"board-row\"\u003e\n          {this.renderSquare(0)}\n          {this.renderSquare(1)}\n          {this.renderSquare(2)}\n        \u003c/div\u003e\n        \u003cdiv className=\"board-row\"\u003e\n          {this.renderSquare(3)}\n          {this.renderSquare(4)}\n          {this.renderSquare(5)}\n        \u003c/div\u003e\n        \u003cdiv className=\"board-row\"\u003e\n          {this.renderSquare(6)}\n          {this.renderSquare(7)}\n          {this.renderSquare(8)}\n        \u003c/div\u003e\n      \u003c/div\u003e\n    );\n  }\n}\n\nclass Game extends React.Component {\n  constructor(props) {\n    super(props);\n    this.state = {\n      history: [\n        {\n          squares: Array(9).fill(null)\n        }\n      ],\n      stepNumber: 0,\n      xIsNext: true\n    };\n  }\n\n  handleClick(i) {\n    const history = this.state.history.slice(0, this.state.stepNumber + 1);\n    const current = history[history.length - 1];\n    const squares = current.squares.slice();\n    if (calculateWinner(squares) || squares[i]) {\n      return;\n    }\n    squares[i] = this.state.xIsNext ? \"X\" : \"O\";\n    this.setState({\n      history: history.concat([\n        {\n          squares: squares\n        }\n      ]),\n      stepNumber: history.length,\n      xIsNext: !this.state.xIsNext\n    });\n  }\n\n  jumpTo(step) {\n    this.setState({\n      stepNumber: step,\n      xIsNext: step % 2 === 0\n    });\n  }\n\n  render() {\n    const history = this.state.history;\n    const current = history[this.state.stepNumber];\n    const winner = calculateWinner(current.squares);\n\n    const moves = history.map((step, move) =\u003e {\n      const desc = move ? \"Go to move #\" + move : \"Go to game start\";\n      return (\n        \u003cli key={move}\u003e\n          \u003cAmplitude\n            eventProperties={inheritedProps =\u003e ({\n              ...inheritedProps,\n              scope: [...inheritedProps.scope, \"move button\"]\n            })}\n          \u003e\n            {({ logEvent }) =\u003e (\n              \u003cbutton\n                onClick={() =\u003e {\n                  logEvent(move ? \"jump to move\" : \"go to game start\");\n                  this.jumpTo(move);\n                }}\n              \u003e\n                {desc}\n              \u003c/button\u003e\n            )}\n          \u003c/Amplitude\u003e\n        \u003c/li\u003e\n      );\n    });\n\n    let status;\n    if (winner) {\n      status = \"Winner: \" + winner;\n    } else {\n      status = \"Current player: \" + (this.state.xIsNext ? \"X\" : \"O\");\n    }\n\n    return (\n      \u003cAmplitudeProvider\n        amplitudeInstance={amplitude.getInstance()}\n        apiKey={AMPLITUDE_KEY}\n      \u003e\n        \u003cAmplitude\n          eventProperties={{\n            scope: [\"game\"],\n            \"moves made\": this.state.step,\n            \"current player\": this.state.xIsNext ? \"X\" : \"O\",\n            winner\n          }}\n        \u003e\n          \u003cLogOnMount eventType=\"start game\" /\u003e\n          {!!winner \u0026\u0026 \u003cLogOnMount eventType=\"game won\" /\u003e}\n          \u003cdiv className=\"game\"\u003e\n            \u003cdiv className=\"game-board\"\u003e\n              \u003cBoard\n                squares={current.squares}\n                onClick={i =\u003e this.handleClick(i)}\n              /\u003e\n            \u003c/div\u003e\n            \u003cAmplitude\n              eventProperties={inheritedProps =\u003e ({\n                ...inheritedProps,\n                scope: [...inheritedProps.scope, \"history\"]\n              })}\n            \u003e\n              \u003cdiv className=\"game-info\"\u003e\n                \u003cdiv\u003e{status}\u003c/div\u003e\n                \u003col\u003e{moves}\u003c/ol\u003e\n              \u003c/div\u003e\n            \u003c/Amplitude\u003e\n          \u003c/div\u003e\n        \u003c/Amplitude\u003e\n      \u003c/AmplitudeProvider\u003e\n    );\n  }\n}\n\n// ========================================\n\nrender(\u003cGame /\u003e, document.getElementById(\"root\"));\n\nfunction calculateWinner(squares) {\n  const lines = [\n    [0, 1, 2],\n    [3, 4, 5],\n    [6, 7, 8],\n    [0, 3, 6],\n    [1, 4, 7],\n    [2, 5, 8],\n    [0, 4, 8],\n    [2, 4, 6]\n  ];\n  for (let i = 0; i \u003c lines.length; i++) {\n    const [a, b, c] = lines[i];\n    if (squares[a] \u0026\u0026 squares[a] === squares[b] \u0026\u0026 squares[a] === squares[c]) {\n      return squares[a];\n    }\n  }\n  return null;\n}\n```\n\n[![Edit nnowj5nonj](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/nnowj5nonj)\n\n## Installation\n\nWith npm:\n\n```\nnpm install --save @amplitude/react-amplitude\n```\n\nWith yarn:\n\n```\nyarn add @amplitude/react-amplitude\n```\n\nreact-amplitude does not come with its own copy of the Amplitude JavaScript SDK. You can either install the Amplitude SDK via npm or with a JavaScript snippet.\n\n## API\n\n### AmplitudeProvider props\n\n#### amplitudeInstance\n\nA required prop. You should be providing an Amplitude instance returned from the Amplitude JS SDK's [`getInstance`](https://amplitude.zendesk.com/hc/en-us/articles/115002889587-JavaScript-SDK-Reference#amplitudeclient) method.\n\n#### apiKey\n\nAn optional prop that can be used to initialize the Amplitude instance with the provided key.\n\n#### userId\n\nAn optional prop that can be used to attribute all events to a specific user.\n\n### Amplitude props\n\n#### children\n\nIf can pass a function as the children prop, it will be called with a single object parameter, and the return value of that function will be used for rendering the actual React subtree.\n\nThe single object parameter has two useful fields: `logEvent` and `instrument`.\n\n`logEvent` is a function that can be used to imperatively log events. All event properties from this component's `eventProperties` prop and any inherited properties will be included in these events.\n\nExample:\n\n```jsx\nfunction Button(props) {\n  return (\n    \u003cAmplitude\u003e\n      {({ logEvent }) =\u003e\n        \u003cbutton\n          onClick={() =\u003e {\n            logEvent('button click');\n            props.onClick();\n          }}\n        \u003e\n          {props.children}\n        \u003c/button\u003e\n      }\n    \u003c/Amplitude\u003e\n  )\n}\n```\n\n`instrument` is a function that can be used to declaratively log events. If you have pre-existing event handlers, just wrap the functions with an `instrument`, and events will fire every time your normal event handlers are executed. `instrument` takes two parameters, the event type and the function to proxy.\n\n`instrument` is also useful if you would like to prevent re-rendering via shouldComponentUpdate optimizations like PureComponent. It memoizes its arguments and returns the same function instance across re-renders. For this reason, it's not recommended to use `instrument` for functions that change on every render (i.e. inlined or \"arrow\" functions in `render`).\n\nExample:\n\n```jsx\nfunction Button(props) {\n  return (\n    \u003cAmplitude\u003e\n      {({ instrument }) =\u003e\n        \u003cbutton\n          onClick={instrument('button click', props.onClick)}\n        \u003e\n          {props.children}\n        \u003c/button\u003e\n      }\n    \u003c/Amplitude\u003e\n  )\n}\n```\n\n#### eventProperties\n\nIf an object is provided, the object will be merged with event properties higher-up in the component hierarchy and included in all events logged in this component or any components in its subtree.\n\nIf a function is provided, it will be called with a single parameter, `inheritedProperties`, that contains all of the event properties from components higher in the React component hierarchy. The return value from this function will be used for all logged events in this component or other components in its subtree.\n\n####  debounceInterval\n\nIf provided, events logged by the component will be debounced by this amount, in milliseconds.\n\n#### userProperties\n\nAn optional object that if provided, will trigger updates to the current user's \"user properties.\"\n\n### LogOnMount props\n\n#### eventType\n\nWhen this component mounts, it will log an event with this value as the event type.\n\n#### eventProperties\n\nThese properties will be applied to the event when the component mounts.\n\n### instanceName\n\nTHe Amplitude instance to log events to.\n\n### LogOnChange props\n\n#### value\n\nRequired prop, that when changes (diffing is done with shallow equality comparison), logs an event.\n\n#### eventType\n\nWhen the `value` prop changes, it will log an event with this value as the event type.\n\n#### eventProperties\n\nThese properties will be applied to the event when the component mounts.\n\n### instanceName\n\nThe Amplitude instance to log events to.\n\n## License\n\nMIT\n\n## Friends \u0026 Related Projects\n+ [analytics-react](https://github.com/segmentio/analytics-react): Write analytics code once with Segment and collect customer data from any source and send it to over 250+ destinations.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famplitude%2Freact-amplitude","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Famplitude%2Freact-amplitude","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famplitude%2Freact-amplitude/lists"}