{"id":13710060,"url":"https://github.com/jerednel/markov-chain-attribution","last_synced_at":"2026-01-22T00:31:11.307Z","repository":{"id":46333691,"uuid":"141180079","full_name":"jerednel/markov-chain-attribution","owner":"jerednel","description":"A PoC for a fractional attribution model leveraging first order Markov Chains.","archived":false,"fork":false,"pushed_at":"2024-09-27T20:35:19.000Z","size":89,"stargazers_count":84,"open_issues_count":1,"forks_count":15,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-11-06T20:12:55.837Z","etag":null,"topics":["attribution","marketing-analytics","markov-chain-attribution","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jerednel.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-07-16T18:49:14.000Z","updated_at":"2025-08-19T16:06:03.000Z","dependencies_parsed_at":"2025-05-06T18:40:47.668Z","dependency_job_id":null,"html_url":"https://github.com/jerednel/markov-chain-attribution","commit_stats":{"total_commits":40,"total_committers":4,"mean_commits":10.0,"dds":"0.30000000000000004","last_synced_commit":"dea0769d80b0f138202d35dbe601bedd3cb164f1"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/jerednel/markov-chain-attribution","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jerednel%2Fmarkov-chain-attribution","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jerednel%2Fmarkov-chain-attribution/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jerednel%2Fmarkov-chain-attribution/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jerednel%2Fmarkov-chain-attribution/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jerednel","download_url":"https://codeload.github.com/jerednel/markov-chain-attribution/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jerednel%2Fmarkov-chain-attribution/sbom","scorecard":{"id":515308,"data":{"date":"2025-08-11","repo":{"name":"github.com/jerednel/markov-chain-attribution","commit":"ddd13551b0995e971493ebb9ce71b32f7768c043"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.txt:0","Info: FSF or OSI recognized license: MIT License: LICENSE.txt:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-20T01:39:18.916Z","repository_id":46333691,"created_at":"2025-08-20T01:39:18.916Z","updated_at":"2025-08-20T01:39:18.916Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28648460,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-21T21:29:11.980Z","status":"ssl_error","status_checked_at":"2026-01-21T21:24:31.872Z","response_time":86,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["attribution","marketing-analytics","markov-chain-attribution","python"],"created_at":"2024-08-02T23:00:51.374Z","updated_at":"2026-01-22T00:31:11.273Z","avatar_url":"https://github.com/jerednel.png","language":"Python","funding_links":[],"categories":["Attribution"],"sub_categories":[],"readme":" \n## Markov Chains for Attribution Modeling\n\nThis is a proof-of-concept I built out that leverages a first order Markov chain to reallocate conversions in the manner explained by [Anderl, Eva and Becker, Ingo and Wangenheim, Florian V. and Schumann, Jan Hendrik](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=2343077) in \" Mapping the Customer Journey: A Graph-Based Framework for Online Attribution Modeling\"\n\nIf this concept is new, check out the post on [markov chain attribution modeling](https://jeremy.bearblog.dev/building-an-attribution-model-with-markov-chains/).   \n\nBig thanks to people writing and commenting on this [AnalyzeCore article](https://analyzecore.com/2016/08/03/attribution-model-r-part-1/) for a very useful article and comment section.\n\n### Motivation\n\nThere is an amazing R package called ChannelAttribution which does this as well as higher-order models very well.  My day-to-day workflow is centered around Python so I wanted to build out a version to A) have something I can go-to for connecting directly to SQL tables to path journeys and B) better understand the process by which these attribution models are generated.  ChannelAttribution makes it very easy to faceroll a fractional attribution model without really understanding what's going on.  Which is great!  But if you want to understand better, building your own tends to help.\n\nTo get started quickly you can install via pip.\n\n### Installation\nMake sure your version is at least 0.4 - prior versions included suboptimal ways of generating our initial transition states that resulted in negative conversions in large datasets.\n```#python\npip install markov-model-attribution\n```\n\n### Use\n* This package currently accepts a single-column Pandas dataframe. \n* Each path should begin with \"start\" and end with either \"conv\" or \"null\".\n* Each path should be delimited by \" \u003e \"\n\nThe argument to pass is ```paths```, where paths is the Pandas dataframe containing your paths.\n\n\n```#python\nimport markov_model_attribution as mma\nimport pandas as pd\n\n# generate a sample dataset\ndf = pd.DataFrame({'Paths':['start \u003e cone \u003e ctwo \u003e cthree \u003e conv',\n                           'start \u003e cone \u003e null',\n                           'start \u003e ctwo \u003e cthree \u003e null']})\n\nmodel = mma.run_model(paths=df)\n\n```\n\nOnce you have the model constructed you can access a couple of things to compare how a fractional model does against a standard last touch model.\n\nYou can access these via\n\n```python\n\nprint(model['markov_conversions'])\n\n# This outputs a dictionary containing the markov conversion count\n# {'cone': 0.2, 'cthree': 0.4, 'ctwo': 0.4}\n\n\nprint(model['last_touch_conversions'])\n# This outputs the last touch conversions for comparison\n# {'cone': 0, 'cthree': 1, 'ctwo': 0}\n```\n\nYou can also access the removal effect matrix of the underlying result.  \n\n```python\nprint(model['removal_effects'])\n\n# {'cone': 0.5, 'cthree': 1.0, 'ctwo': 1.0}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjerednel%2Fmarkov-chain-attribution","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjerednel%2Fmarkov-chain-attribution","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjerednel%2Fmarkov-chain-attribution/lists"}